GCC(1)
๐ GCC(1) from GNU โจ (part 1 of 130)
๐ง NAME ๐ง
okay so gcc is the GNU project's C and C++ compiler ๐
literally the main character of compiling ๐
๐ SYNOPSIS ๐
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
Only the most useful options are listed here, bestie ๐ซถ see below for the rest. g++ accepts mostly the same options as gcc โจ
๐ DESCRIPTION ๐
okay so when you invoke GCC, it normally does preprocessing, compilation, assembly and linking ๐ฅ The "overall options" let you stop this process at an intermediate stage. For example, the -c option says not to run the linker, so the output is the object files the assembler spits out ๐ฆ
Other options get passed on to one or more stages of processing. Some control the preprocessor, some control the compiler itself, and yet other options control the assembler and linker. Most of those aren't documented here because you rarely need to touch them ๐
Most of the command-line options you can use with GCC are useful for C programs. When an option is only useful with another language (usually C++), the explanation says so explicitly. If an option's description doesn't mention a source language, you can use it with all supported languages ๐
The usual way to run GCC is the executable called gcc, or machine-gcc when cross-compiling, or machine-gcc-version if you want a specific version of GCC. When you compile C++ programs, invoke GCC as g++ instead ๐
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so you can't bundle single-letter options together. -dv is very different from -d -v ๐ญ
You can mix options and other arguments, and for the most part the order doesn't matter ๐ธ Order does matter when you use several options of the same kind. For example, if you specify -L more than once, the directories get searched in the order you specified them. Also, the placement of the -l option is significant โญ
Lots of options have long names starting with -f or with -W---for, for example -fmove-loop-invariants, -Wformat and so on. Most of these have both positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one is not the default ๐ง
Some options take one or more arguments, usually separated from the option name by either a space or the equals sign (=). Unless documented otherwise, an argument can be either numeric or a string. Numeric arguments must typically be small unsigned decimal or hexadecimal integers, and hexadecimal arguments must begin with the 0x prefix ๐ข
Arguments to options that specify a size threshold can be arbitrarily large decimal or hexadecimal integers followed by a byte size suffix for a multiple of bytes. That's kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, GB and GiB for gigabyte and gigibyte, and so on. These are called byte-size in the rest of the text. For the full listing and explanation of the binary and decimal byte size prefixes, check the NIST, IEC, and other relevant national and international standards ๐
๐ OPTIONS ๐
๐ธ Option Summary
Here's a summary of all the options, grouped by type ๐ The explanations live in the following sections.
๐ฆ Overall Options
-c -S -E -o file -dumpbase dumpbase -dumpbase-ext auxdropsuf
-dumpdir dumppfx -x language -v -### --help[=class[,...]]
--target-help --version -pass-exit-codes -pipe -wrapper @file
-ffile-prefix-map=old=new -fcanon-prefix-map -fplugin=file
-fplugin-arg-name=arg -fdump-ada-spec[-slim] -fada-spec-parent=unit
-fdump-go-spec=file --assemble --compile --dumpbase dumpbase
--dumpbase-ext auxdropsuf --dumpdir dumppfx --language=language
--output=file --pass-exit-codes --pipe --preprocess --verbose
๐ C Language Options
-ansi -std=standard -aux-info filename -fno-asm -fno-builtin
-fno-builtin-function -fcond-mismatch -ffreestanding -fgimple
-fgnu-tm -fgnu89-inline -fhosted -flax-vector-conversions
-fms-extensions -fpermitted-flt-eval-methods=standard
-fplan9-extensions -fsigned-bitfields -funsigned-bitfields
-fsigned-char -funsigned-char -fstrict-flex-arrays[=n]
-fsso-struct=endianness --ansi
๐ฎ C++ Language Options
--compile-std-module -fabi-compat-version=n -fabi-version=n
-fno-access-control -faligned-new=[n]
-fno-assume-sane-operators-new-delete -fchar8_t -fcheck-new
-fconcepts -fconcepts-diagnostics-depth=n -fconstexpr-depth=n
-fconstexpr-cache-depth=n -fconstexpr-loop-limit=n
-fconstexpr-ops-limit=n -fcontracts
-fcontract-evaluation-semantic=[ignore|observe|enforce|quick_enforce]
-fcontracts-conservative-ipa -fcontract-checks-outlined
-fcontract-disable-optimized-checks
-fcontracts-client-check=[none|pre|all]
-fcontracts-definition-check=[on|off] -fcoroutines
-fdiagnostics-all-candidates -fno-elide-constructors
-fno-enforce-eh-specs -fext-numeric-literals -fno-gnu-keywords
-fno-immediate-escalation -fno-implement-inlines
-fimplicit-constexpr -fno-implicit-inline-templates
-fno-implicit-templates -fmodule-header[=kind]
-fmodule-implicit-inline -fno-module-lazy
-fmodule-mapper=specification -fmodule-only -fmodules
-fms-extensions -fnew-inheriting-ctors -fnew-ttp-matching
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names
-fno-optional-diags -fno-pretty-templates -frange-for-ext-temps
-freflection -fno-rtti -fsized-deallocation -fstrict-enums
-fstrong-eval-order[=kind] -ftemplate-backtrace-limit=n
-ftemplate-depth=n -fno-threadsafe-statics -fuse-cxa-atexit
-fno-use-cxa-get-exception-ptr -fno-weak -nostdinc++
-fvisibility-inlines-hidden -fvisibility-ms-compat
-flang-info-include-translate[=header]
-flang-info-include-translate-not -flang-info-module-cmi[=module]
-stdlib=libstdc++,libc++ -Wabbreviated-auto-in-template-arg
-Wabi-tag -Waligned-new[=kind] -Wcatch-value -Wcatch-value=n
-Wno-class-conversion -Wclass-memaccess -Wcomma-subscript
-Wconditionally-supported -Wno-conversion-null
-Wctad-maybe-unsupported -Wctor-dtor-privacy -Wdangling-reference
-Wno-defaulted-function-deleted -Wno-delete-incomplete
-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare
-Wdeprecated-copy -Wdeprecated-copy-dtor
-Wno-deprecated-enum-enum-conversion
-Wno-deprecated-enum-float-conversion
-Wno-deprecated-literal-operator
-Wdeprecated-variadic-comma-omission -Weffc++
-Wno-elaborated-enum-base -Wno-exceptions
-Wno-expose-global-module-tu-local -Wno-external-tu-local
-Wextra-semi -Wno-global-module -Wno-inaccessible-base
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime
-Winvalid-constexpr -Winvalid-imported-macros -Wno-invalid-offsetof
-Wno-literal-suffix -Wmismatched-new-delete -Wmismatched-tags
-Wmultiple-inheritance -Wnamespaces -Wnarrowing -Wnoexcept
-Wnoexcept-type -Wnon-virtual-dtor -Wpessimizing-move
-Wno-placement-new -Wplacement-new=n -Wrange-loop-construct
-Wredundant-move -Wredundant-tags -Wreorder -Wregister
-Wno-sfinae-incomplete -Wstrict-null-sentinel
-Wno-subobject-linkage -Wtemplates -Wno-non-c-typedef-for-linkage
-Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual
-Wno-pmf-conversions -Wself-move -Wsign-promo -Wsized-deallocation
-Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override
-Wno-template-body -Wno-template-id-cdtor -Wtemplate-names-tu-local
-Wno-terminate -Wno-vexing-parse -Wvirtual-inheritance
-Wno-virtual-move-assign -Wvolatile
๐ Objective-C and Objective-C++ Language Options
-fconstant-string-class=class-name -fgnu-runtime -fnext-runtime
-fno-nil-receivers -fobjc-abi-version=n -fobjc-call-cxx-cdtors
-fobjc-direct-dispatch -fobjc-exceptions -fobjc-gc -fobjc-nilcheck
-fobjc-std=objc1 -fno-local-ivars
-fivar-visibility=[public|protected|private|package]
-freplace-objc-classes -fzero-link -gen-decls -Wassign-intercept
-Wno-property-assign-default -Wno-protocol -Wobjc-root-class
-Wselector -Wstrict-selector-match -Wundeclared-selector
๐ง OpenMP and OpenACC Options
-foffload=arg -foffload-options=arg -fopenacc -fopenacc-dim=geom
-fopenmp -fopenmp-simd -fopenmp-target-simd-clone[=device-type]
๐ Diagnostic Message Formatting Options
-fmessage-length=n -fdiagnostics-plain-output
-fdiagnostics-show-location=[once|every-line]
-fdiagnostics-color=[auto|never|always]
-fdiagnostics-urls=[auto|never|always]
-fdiagnostics-format=[text|sarif-stderr|sarif-file]
-fdiagnostics-add-output=DIAGNOSTICS-OUTPUT-SPEC
-fdiagnostics-set-output=DIAGNOSTICS-OUTPUT-SPEC
-fno-diagnostics-json-formatting -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-event-links
-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers
-fno-diagnostics-show-cwe -fno-diagnostics-show-rules
-fno-diagnostics-show-highlight-colors -fno-diagnostics-show-nesting
-fno-diagnostics-show-nesting-locations
-fdiagnostics-show-nesting-levels
-fdiagnostics-minimum-margin-width=width
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type
-fdiagnostics-path-format=[none|separate-events|inline-events]
-fdiagnostics-show-path-depths -fno-show-column
-fdiagnostics-column-unit=[display|byte]
-fdiagnostics-column-origin=origin
-fdiagnostics-escape-format=[unicode|bytes]
-fdiagnostics-text-art-charset=[none|ascii|unicode|emoji]
-fdiagnostics-show-context[=depth]
โจ Warning Options โจ
okay bestie, this is the whole warnings wardrobe ๐ every single one of these is listed below, no cap ๐ซถ
-fsyntax-only-fmax-errors=n-Wpedantic-pedantic-errors-fpermissive-w-Wextra-Wall-Wabi=n-Waddress-Wno-address-of-packed-member-Waggregate-return-Walloc-size-Walloc-size-larger-than=byte-size-Walloc-zero-Walloca-Walloca-larger-than=byte-size-Wauto-profile-Wno-aggressive-loop-optimizations-Warith-conversion-Warray-bounds-Warray-bounds=n-Warray-compare-Warray-parameter-Warray-parameter=n-Wno-attributes-Wattribute-alias=n-Wno-attribute-alias-Wno-attribute-warning-Wbidi-chars=[none|unpaired|any|ucn]-Wbool-compare-Wbool-operation-Wno-builtin-declaration-mismatch-Wno-builtin-macro-redefined-Wc90-c99-compat-Wc99-c11-compat-Wc11-c23-compat-Wc23-c2y-compat-Wc++-compat-Wc++11-compat-Wc++14-compat-Wc++17-compat-Wc++20-compat-Wc++26-compat-Wno-c++11-extensions-Wno-c++14-extensions-Wno-c++17-extensions-Wno-c++20-extensions-Wno-c++23-extensions-Wcalloc-transposed-args-Wcannot-profile-Wcast-align-Wcast-align=strict-Wcast-function-type-Wcast-qual-Wchar-subscripts-Wclobbered-Wcomment-Wcompare-distinct-pointer-types-Wno-complain-wrong-lang-Wconversion-Wno-coverage-mismatch-Wno-cpp-Wdangling-else-Wdangling-pointer-Wdangling-pointer=n-Wdate-time-Wno-deprecated-Wno-deprecated-declarations-Wno-designated-init-Wno-deprecated-openmp-Wdisabled-optimization-Wno-discarded-array-qualifiers-Wno-discarded-qualifiers-Wno-div-by-zero-Wdouble-promotion-Wduplicated-branches-Wduplicated-cond-Wempty-body-Wno-endif-labels-Wenum-compare-Wenum-conversion-Wenum-int-mismatch-Werror-Werror=*-Wexpansion-to-defined-Wfatal-errors-Wflex-array-member-not-at-end-Wfloat-conversion-Wfloat-equal-Wformat-Wformat=2-Wno-format-contains-nul-Wno-format-diag-Wno-format-extra-args-Wformat-nonliteral-Wformat-overflow=n-Wformat-security-Wformat-signedness-Wformat-truncation=n-Wformat-y2k-Wframe-address-Wframe-larger-than=byte-size-Wno-free-nonheap-object-Wheader-guard-Wno-if-not-aligned-Wno-ignored-attributes-Wignored-qualifiers-Wno-incompatible-pointer-types-Whardened-Wimplicit-Wimplicit-fallthrough-Wimplicit-fallthrough=n-Wno-implicit-function-declaration-Wno-implicit-int-Winfinite-recursion-Winit-self-Winline-Wno-int-conversion-Wint-in-bool-context-Wno-int-to-pointer-cast-Wno-invalid-memory-model-Winvalid-pch-Winvalid-utf8-Wno-unicode-Wjump-misses-init-Wkeyword-macro-Wlarger-than=byte-size-Wleading-whitespace=kind-Wlogical-not-parentheses-Wlogical-op-Wlong-long-Wno-lto-type-mismatch-Wmain-Wmaybe-uninitialized-Wmemset-elt-size-Wmemset-transposed-args-Wmisleading-indentation-Wmissing-attributes-Wmissing-braces-Wmissing-field-initializers-Wmissing-format-attribute-Wmissing-include-dirs-Wmissing-noreturn-Wmusttail-local-addr-Wmaybe-musttail-local-addr-Wno-missing-profile-Wno-multichar-Wmultistatement-macros-Wnonnull-Wnonnull-compare-Wnormalized=[none|id|nfc|nfkc]-Wnull-dereference-Wno-odr-Wopenacc-parallelism-Wopenmp-Wopenmp-simd-Wno-overflow-Woverlength-strings-Wno-override-init-side-effects-Wpacked-Wno-packed-bitfield-compat-Wpacked-not-aligned-Wpadded-Wparentheses-Wno-pedantic-ms-format-Wpointer-arith-Wno-pointer-compare-Wno-pointer-to-int-cast-Wno-pragmas-Wno-pragma-once-outside-header-Wno-prio-ctor-dtor-Wno-psabi-Wredundant-decls-Wrestrict-Wno-return-local-addr-Wreturn-type-Wno-scalar-storage-order-Wsequence-point-Wshadow-Wshadow=global-Wshadow=local-Wshadow=compatible-local-Wno-shadow-ivar-Wno-shift-count-negative-Wno-shift-count-overflow-Wshift-negative-value-Wno-shift-overflow-Wshift-overflow=n-Wsign-compare-Wsign-conversion-Wno-sizeof-array-argument-Wsizeof-array-div-Wsizeof-pointer-div-Wsizeof-pointer-memaccess-Wstack-protector-Wstack-usage=byte-size-Wstrict-aliasing-Wstrict-aliasing=n-Wstrict-overflow-Wstrict-overflow=n-Wstring-compare-Wno-stringop-overflow-Wno-stringop-overread-Wno-stringop-truncation-Wstrict-flex-arrays-Wsuggest-attribute=attribute-name-Wswitch-Wno-switch-bool-Wswitch-default-Wswitch-enum-Wno-switch-outside-range-Wno-switch-unreachable-Wsync-nand-Wsystem-headers-Wtautological-compare-Wtrailing-whitespace-Wtrailing-whitespace=kind-Wtrampolines-Wtrigraphs-Wtrivial-auto-var-init-Wno-tsan-Wtype-limits-Wundef-Wuninitialized-Wunknown-pragmas-Wunsuffixed-float-constants-Wunterminated-string-initialization-Wunused-Wunused-but-set-parameter-Wunused-but-set-parameter=n-Wunused-but-set-variable-Wunused-but-set-variable=n-Wunused-const-variable-Wunused-const-variable=n-Wunused-function-Wunused-label-Wunused-local-typedefs-Wunused-macros-Wunused-parameter-Wno-unused-result-Wunused-value-Wunused-variable-Wuse-after-free-Wuse-after-free=n-Wuseless-cast-Wno-varargs-Wvariadic-macros-Wvector-operation-performance-Wvla-Wvla-larger-than=byte-size-Wno-vla-larger-than-Wvolatile-register-var-Wwrite-strings-Wno-xor-used-as-pow-Wzero-as-null-pointer-constant-Wzero-length-bounds--all-warnings--extra-warnings--no-warnings--pedantic--pedantic-errors
๐ Static Analyzer Options ๐
the analyzer squad has arrived ๐ฆ here's every flag they came with, iykyk โจ
-fanalyzer-fanalyzer-assume-nothrow-fanalyzer-call-summaries-fanalyzer-checker=name-fno-analyzer-feasibility-fanalyzer-show-events-in-system-headers-fno-analyzer-state-merge-fno-analyzer-state-purge-fno-analyzer-suppress-followups-fanalyzer-transitivity-fno-analyzer-undo-inlining-fanalyzer-verbose-edges-fanalyzer-verbose-state-changes-fanalyzer-verbosity=level-fdump-analyzer-fdump-analyzer-callgraph-fdump-analyzer-exploded-graph-fdump-analyzer-exploded-nodes-fdump-analyzer-exploded-nodes-2-fdump-analyzer-exploded-nodes-3-fdump-analyzer-exploded-paths-fdump-analyzer-feasibility-fdump-analyzer-infinite-loop-fdump-analyzer-json-fdump-analyzer-state-purge-fdump-analyzer-stderr-fdump-analyzer-supergraph-fdump-analyzer-untracked-Wno-analyzer-double-fclose-Wno-analyzer-double-free-Wno-analyzer-exposure-through-output-file-Wno-analyzer-exposure-through-uninit-copy-Wno-analyzer-fd-access-mode-mismatch-Wno-analyzer-fd-double-close-Wno-analyzer-fd-leak-Wno-analyzer-fd-phase-mismatch-Wno-analyzer-fd-type-mismatch-Wno-analyzer-fd-use-after-close-Wno-analyzer-fd-use-without-check-Wno-analyzer-file-leak-Wno-analyzer-free-of-non-heap-Wno-analyzer-imprecise-fp-arithmetic-Wno-analyzer-infinite-loop-Wno-analyzer-infinite-recursion-Wno-analyzer-jump-through-null-Wno-analyzer-malloc-leak-Wno-analyzer-mismatching-deallocation-Wno-analyzer-null-argument-Wno-analyzer-null-dereference-Wno-analyzer-out-of-bounds-Wno-analyzer-overlapping-buffers-Wno-analyzer-possible-null-argument-Wno-analyzer-possible-null-dereference-Wno-analyzer-putenv-of-auto-var-Wno-analyzer-shift-count-negative-Wno-analyzer-shift-count-overflow-Wno-analyzer-stale-setjmp-buffer-Wno-analyzer-tainted-allocation-size-Wno-analyzer-tainted-assertion-Wno-analyzer-tainted-array-index-Wno-analyzer-tainted-divisor-Wno-analyzer-tainted-offset-Wno-analyzer-tainted-size-Wno-analyzer-throw-of-unexpected-type-Wanalyzer-symbol-too-complex-Wanalyzer-too-complex-Wno-analyzer-undefined-behavior-ptrdiff-Wno-analyzer-undefined-behavior-strtok-Wno-analyzer-unsafe-call-within-signal-handler-Wno-analyzer-use-after-free-Wno-analyzer-use-of-pointer-in-stale-stack-frame-Wno-analyzer-use-of-uninitialized-value-Wno-analyzer-va-arg-type-mismatch-Wno-analyzer-va-list-exhausted-Wno-analyzer-va-list-leak-Wno-analyzer-va-list-use-after-va-end-Wno-analyzer-write-to-const-Wno-analyzer-write-to-string-literal
๐ธ C and Objective-C-only Warning Options ๐ธ
these ones are C and Objective-C only, so they're a little picky ๐
-Wbad-function-cast-Wdeprecated-non-prototype-Wfree-labels-Wmissing-declarations-Wmissing-parameter-name-Wmissing-parameter-type-Wdeclaration-missing-parameter-type-Wmissing-prototypes-Wmissing-variable-declarations-Wmultiple-parameter-fwd-decl-lists-Wnested-externs-Wold-style-declaration-Wold-style-definition-Wstrict-prototypes-Wtraditional-Wtraditional-conversion-Wdeclaration-after-statement-Wpointer-sign
๐ Debugging Options ๐
the debug drip is UNREAL ๐ every flag is here, no skipping ๐ง
-g-glevel-gdwarf-gdwarf-version-gbtf-gctf-gctflevel-gno-prune-btf-ggdb-gno-record-gcc-switches-gstrict-dwarf-gas-loc-support-gas-locview-support-gcodeview-gcolumn-info-gdwarf32-gdwarf64-gno-statement-frontiers-gno-variable-location-views-gvariable-location-views=incompat5-ginternal-reset-location-views-ginline-points-gvms-gz[=type]-gsplit-dwarf-gdescribe-dies-fdebug-prefix-map=old=new-fdebug-types-section-fno-eliminate-unused-debug-types-femit-struct-debug-baseonly-femit-struct-debug-reduced-femit-struct-debug-detailed[=spec-list]-fno-eliminate-unused-debug-symbols-femit-class-debug-always-fno-merge-debug-strings-fno-dwarf2-cfi-asm-fvar-tracking-fvar-tracking-assignments-fvar-tracking-uninit--debug
โจ Optimization Options โจ
okay bestie, the optimization drawer is SO full ๐ฅ here's every single flag, no cap ๐
-faggressive-loop-optimizations-falign-functions[=n[:m:[n2[:m2]]]]-falign-jumps[=n[:m:[n2[:m2]]]]-falign-labels[=n[:m:[n2[:m2]]]]-falign-loops[=n[:m:[n2[:m2]]]]-fmin-function-alignment=[n]-fno-allocation-dce-fallow-store-data-races-fassociative-math-fauto-profile-fauto-profile[=path]-fauto-profile-inlining-fauto-inc-dec-fbranch-probabilities-fcaller-saves-fcombine-stack-adjustments-fconserve-stack-ffold-mem-offsets-fcompare-elim-fcprop-registers-fcrossjumping-fcse-follow-jumps-fcse-skip-blocks-fcx-fortran-rules-fcx-limited-range-fcx-method-fdata-sections-fdce-fdelayed-branch-fdelete-null-pointer-checks-fdep-fusion-fdevirtualize-fdevirtualize-speculatively-fdevirtualize-at-ltrans-fdse-fearly-inlining-fexcess-precision=style-fexpensive-optimizations-fext-dce-ffast-math-ffat-lto-objects-ffinite-loops-ffinite-math-only-ffloat-store-fforward-propagate-ffp-contract=style-ffp-int-builtin-inexact-ffunction-sections-ffuse-ops-with-volatile-access-fgcse-fgcse-after-reload-fgcse-las-fgcse-lm-fgraphite-identity-fgcse-sm-fhoist-adjacent-loads-fif-conversion-fif-conversion2-findirect-inlining-finline-atomics-finline-functions-finline-functions-called-once-finline-limit=n-finline-small-functions-finline-stringops[=fn]-fipa-modref-fipa-cp-fipa-cp-clone-fipa-bit-cp-fipa-vrp-fipa-pta-fipa-profile-fipa-pure-const-fipa-reference-fipa-reference-addressable-fipa-reorder-for-locality-fipa-sra-fipa-stack-alignment-fipa-icf-fipa-icf-functions-fipa-icf-variables-fira-algorithm=algorithm-flate-combine-instructions-flifetime-dse-flive-patching=level-fira-region=region-fira-hoist-pressure-fira-loop-pressure-fno-ira-share-save-slots-fno-ira-share-spill-slots-fisolate-erroneous-paths-dereference-fisolate-erroneous-paths-attribute-fivopts-fkeep-inline-functions-fkeep-static-functions-fkeep-static-consts-flimit-function-alignment-flive-range-shrinkage-floop-block-floop-interchange-floop-strip-mine-floop-unroll-and-jam-floop-nest-optimize-floop-parallelize-all-flra-remat-flto-flto-compression-level=n-flto-toplevel-asm-heuristics-flto-partition=alg-flto-incremental=path-flto-incremental-cache-size=n-fmalloc-dce-fmerge-all-constants-fmerge-constants-fmodulo-sched-fmodulo-sched-allow-regmoves-fmove-loop-invariants-fmove-loop-stores-fno-branch-count-reg-fno-defer-pop-fno-function-cse-fno-guess-branch-probability-fno-inline-fno-math-errno-fno-peephole-fno-peephole2-fno-printf-return-value-fno-sched-interblock-fno-sched-spec-fno-signed-zeros-fno-toplevel-reorder-fno-trapping-math-fno-zero-initialized-in-bss-fomit-frame-pointer-foptimize-crc-foptimize-sibling-calls-fpartial-inlining-fpeel-loops-fpredictive-commoning-fprefetch-loop-arrays-fprofile-correction-fprofile-use-fprofile-use=path-fprofile-partial-training-fprofile-values-fprofile-reorder-functions-freciprocal-math-free-frename-registers-freorder-blocks-freorder-blocks-algorithm=algorithm-freorder-blocks-and-partition-freorder-functions-frerun-cse-after-loop-freschedule-modulo-scheduled-loops-frounding-math-fsave-optimization-record-fsched2-use-superblocks-fsched-pressure-fsched-spec-load-fsched-spec-load-dangerous-fsched-stalled-insns-dep[=n]-fsched-stalled-insns[=n]-fsched-group-heuristic-fsched-critical-path-heuristic-fsched-spec-insn-heuristic-fsched-rank-heuristic-fsched-last-insn-heuristic-fsched-dep-count-heuristic-fschedule-fusion-fschedule-insns-fschedule-insns2-fsection-anchors-fselective-scheduling-fselective-scheduling2-fsel-sched-pipelining-fsel-sched-pipelining-outer-loops-fsemantic-interposition-fshrink-wrap-fshrink-wrap-separate-fsignaling-nans-fsingle-precision-constant-fsplit-ivs-in-unroller-fsplit-loops-fspeculatively-call-stored-functions-fsplit-paths-fsplit-wide-types-fsplit-wide-types-early-fssa-backprop-fssa-phiopt-fstdarg-opt-fstore-merging-fstrict-aliasing-fipa-strict-aliasing-fthread-jumps-ftracer-ftree-bit-ccp-ftree-builtin-call-dce-ftree-ccp-ftree-ch-ftree-coalesce-vars-ftree-copy-prop-ftree-cselim-ftree-dce-ftree-dominator-opts-ftree-dse-ftree-forwprop-ftree-fre-fcode-hoisting-ftree-loop-if-convert-ftree-loop-im-ftree-phiprop-ftree-loop-distribution-ftree-loop-distribute-patterns-ftree-loop-ivcanon-ftree-loop-linear-ftree-loop-optimize-ftree-loop-vectorize-ftree-parallelize-loops[=n]-ftree-pre-ftree-partial-pre-ftree-pta-ftree-reassoc-ftree-scev-cprop-ftree-sink-ftree-slsr-ftree-sra-ftree-switch-conversion-ftree-tail-merge-ftree-ter-ftree-vectorize-ftree-vrp-ftrivial-auto-var-init-funconstrained-commons-funit-at-a-time-funroll-all-loops-funroll-loops-funsafe-math-optimizations-funswitch-loops-fipa-ra-fvariable-expansion-in-unroller-fvect-cost-model-fvpt-fweb-fwhole-program-fwpa-fuse-linker-plugin-fzero-call-used-regs-O-O0-O1-O2-O3-Os-Ofast-Og-Oz--optimize
โจ Program Instrumentation Options โจ
the instrumentation drawer is next, bestie ๐๐ profiling, coverage, sanitizers, hardening, the whole glam squad ๐ซถ
-p-pg-fprofile-arcs-coverage-ftest-coverage-fcondition-coverage-fpath-coverage-fprofile-fprofile-abs-path-fprofile-dir=path-fprofile-generate-fprofile-generate=path-fprofile-info-section-fprofile-info-section=name-fprofile-note=path-fprofile-prefix-path=path-fprofile-update=method-fprofile-filter-files=regex-fprofile-exclude-files=regex-fprofile-reproducible=[multithreaded|parallel-runs|serial]-fsanitize=style-fsanitize-recover-fsanitize-recover=style-fsanitize-trap-fsanitize-trap=style-fasan-shadow-offset=number-fsanitize-sections=s1,s2,...-fsanitize-undefined-trap-on-error-fcf-protection-fcf-protection=[full|branch|return|none|check]-fharden-compares-fharden-conditional-branches-fhardened-fharden-control-flow-redundancy-fhardcfr-skip-leaf-fhardcfr-check-exceptions-fhardcfr-check-returning-calls-fhardcfr-check-noreturn-calls=[always|no-xthrow|nothrow|never]-fstack-protector-fstack-protector-all-fstack-protector-strong-fstack-protector-explicit-fstack-check-fstack-limit-register=reg-fstack-limit-symbol=sym-fno-stack-limit-fsplit-stack-fstrub=disable-fstrub=strict-fstrub=relaxed-fstrub=all-fstrub=at-calls-fstrub=internal-fvtable-verify=[std|preinit|none]-fvtv-counts-fvtv-debug-finstrument-functions-finstrument-functions-once-finstrument-functions-exclude-function-list=sym,sym,...-finstrument-functions-exclude-file-list=file,file,...-fprofile-prefix-map=old=new-fpatchable-function-entry=N[,M]--coverage--profile
โจ Preprocessor Options โจ
the preprocessor drawer ๐ let's see what's in here, bestie ๐ง
-C-CC-Dmacro[=defn]-dD-dI-dM-dN-dU-fdebug-cpp-fdirectives-only-fdollars-in-identifiers-fexec-charset=charset-fextended-identifiers-finput-charset=charset-fmacro-prefix-map=old=new-fmax-include-depth=depth-fno-canonical-system-headers-fpch-deps-fpch-preprocess-fpreprocessed-ftabstop=width-ftrack-macro-expansion-fwide-exec-charset=charset-fworking-directory-H-imacros file-include file-M-MD-MF-MG-MM-MMD-MP-MQ-MT-Mno-modules-no-integrated-cpp-P-pthread-remap-traditional-traditional-cpp-trigraphs-Umacro-undef-Wp,option-Xpreprocessor option--comments--comments-in-macros--define-macro=macro[=defn]--dependencies--dump=letters--imacros=file--include=file--no-integrated-cpp--no-line-commands--print-missing-file-dependencies--traditional--traditional-cpp--trigraphs--trace-includes--undefine-macro=macro--user-dependencies--write-dependencies--write-user-dependencies
โจ Assembler Options โจ
-Wa,option-Xassembler option--for-assembler=option
โจ Linker Options โจ
object-file-name-flink-libatomic-fuse-ld=linker-llibrary-nostartfiles-nodefaultlibs-nolibc-nostdlib-nostdlib++-e entry-pie-pthread-r-rdynamic-s-static-static-pie-static-libgcc-static-libstdc++-static-libasan-static-libtsan-static-liblsan-static-libubsan-shared-shared-libgcc-symbolic-T script-Wl,option-Xlinker option-u symbol-Tbss=addr-Tdata=addr-Ttext=addr-N-n-t-Z-z keyword--entry=entry--for-linker=option--force-link=symbol--no-standard-library--pie--static--static-pie--symbolic
โจ Directory Options โจ
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-imultiarch dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--embed-dir=dir--embed-directory=dir--include-barrier--include-directory=dir--include-directory-after=dir--include-prefix=prefix--include-with-prefix=prefix--include-with-prefix-after=prefix--include-with-prefix-before=prefix--no-canonical-prefixes--no-standard-includes--prefix=prefix--sysroot=dir
โจ Picolibc Options โจ
--oslib=library--crt0=[none|minimal|hosted|semihost]--printf=[d|f|l|i|m]--scanf=[d|f|l|i|m]
โจ Code Generation Options โจ
-fcall-saved-reg-fcall-used-reg-ffixed-reg-fexceptions-fnon-call-exceptions-fdelete-dead-exceptions-funwind-tables-fasynchronous-unwind-tables-fno-gnu-unique-finhibit-size-directive-fcommon-fno-ident-fpcc-struct-return-fpic-fPIC-fpie-fPIE-fno-plt-fno-jump-tables-fno-bit-tests-frecord-gcc-switches-freg-struct-return-fshort-enums-fshort-wchar-fverbose-asm-fpack-struct[=n]-fleading-underscore-ftls-model=model-fstack-reuse=reuse_level-ftrampolines-ftrampoline-impl=[stack|heap]-ftrapv-fwrapv-fwrapv-pointer-fvisibility=[default|internal|hidden|protected]-fstrict-volatile-bitfields-fsync-libcalls-fzero-init-padding-bits=value-Qy-Qn
๐ Developer Options ๐
okay bestie, this is the dev-only lineup ๐ Every flag below is copied exactly as the page lists it, so you can pick them out without any guesswork โจ
-dlettersโ bestie, look at this one ๐-dumpspecsโ main character flag ๐-dumpmachineโ iykyk ๐ซถ-dumpversionโ not me staring at this ๐-dumpfullversionโ the vibe is immaculate โจ-fcallgraph-info[=su,da]โ a total slay ๐-fcheckingโ lowkey dev-only energy ๐ฅ-fchecking=nโ iconic ๐ฆ-fdbg-cnt-listโ periodt ๐-fdbg-cnt=counter-value-listโ pretty little option ๐ธ-fdisable-ipa-pass_nameโ extremely on brand ๐ง-fdisable-rtl-pass_nameโ sparkle moment โญ-fdisable-rtl-pass-name=range-listโ bestie, look at this one ๐-fdisable-tree-pass_nameโ main character flag ๐-fdisable-tree-pass-name=range-listโ iykyk ๐ซถ-fdump-debugโ not me staring at this ๐-fdump-earlydebugโ the vibe is immaculate โจ-fdump-noaddrโ a total slay ๐-fdump-unnumberedโ lowkey dev-only energy ๐ฅ-fdump-unnumbered-linksโ iconic ๐ฆ-fdump-final-insns[=file]โ periodt ๐-fdump-internal-locationsโ pretty little option ๐ธ-fdump-ipa-allโ extremely on brand ๐ง-fdump-ipa-cgraphโ sparkle moment โญ-fdump-ipa-inlineโ bestie, look at this one ๐-fdump-lang-allโ main character flag ๐-fdump-lang-switchโ iykyk ๐ซถ-fdump-lang-switch-optionsโ not me staring at this ๐-fdump-lang-switch-options=filenameโ the vibe is immaculate โจ-fdump-passesโ a total slay ๐-fdump-rtl-passโ lowkey dev-only energy ๐ฅ-fdump-rtl-pass=filenameโ iconic ๐ฆ-fdump-statisticsโ periodt ๐-fdump-tree-allโ pretty little option ๐ธ-fdump-tree-switchโ extremely on brand ๐ง-fdump-tree-switch-optionsโ sparkle moment โญ-fdump-tree-switch-options=filenameโ bestie, look at this one ๐-fcompare-debug[=opts]โ main character flag ๐-fcompare-debug-secondโ iykyk ๐ซถ-fenable-kind-passโ not me staring at this ๐-fenable-kind-pass=range-listโ the vibe is immaculate โจ-fira-verbose=nโ a total slay ๐-flto-reportโ lowkey dev-only energy ๐ฅ-flto-report-wpaโ iconic ๐ฆ-fmem-report-wpaโ periodt ๐-fmem-reportโ pretty little option ๐ธ-fpre-ipa-mem-reportโ extremely on brand ๐ง-fpost-ipa-mem-reportโ sparkle moment โญ-fopt-infoโ bestie, look at this one ๐-fopt-info-options[=file]โ main character flag ๐-fmultiflagsโ iykyk ๐ซถ-fprofile-reportโ not me staring at this ๐-frandom-seed=stringโ the vibe is immaculate โจ-fsched-verbose=nโ a total slay ๐-fsel-sched-verboseโ lowkey dev-only energy ๐ฅ-fsel-sched-dump-cfgโ iconic ๐ฆ-fsel-sched-pipelining-verboseโ periodt ๐-fstatsโ pretty little option ๐ธ-fstack-usageโ extremely on brand ๐ง-ftime-reportโ sparkle moment โญ-ftime-report-detailsโ bestie, look at this one ๐-fvar-tracking-assignments-toggleโ main character flag ๐-gtoggleโ iykyk ๐ซถ-print-autofdo-gcov-versionโ not me staring at this ๐-print-file-name=libraryโ the vibe is immaculate โจ-print-libgcc-file-nameโ a total slay ๐-print-multi-directoryโ lowkey dev-only energy ๐ฅ-print-multi-libโ iconic ๐ฆ-print-multi-os-directoryโ periodt ๐-print-multiarchโ pretty little option ๐ธ-print-prog-name=programโ extremely on brand ๐ง-print-search-dirsโ sparkle moment โญ-Qโ bestie, look at this one ๐-print-sysrootโ main character flag ๐-print-sysroot-headers-suffixโ iykyk ๐ซถ-save-tempsโ not me staring at this ๐-save-temps=cwdโ the vibe is immaculate โจ-save-temps=objโ a total slay ๐-specs=fileโ lowkey dev-only energy ๐ฅ-time[=file]โ iconic ๐ฆ--dump=lettersโ periodt ๐--print-autofdo-gcov-versionโ pretty little option ๐ธ--print-file-name=libraryโ extremely on brand ๐ง--print-libgcc-file-file-nameโ sparkle moment โญ--print-multi-directoryโ bestie, look at this one ๐--print-multi-libโ main character flag ๐--print-multi-os-directoryโ iykyk ๐ซถ--print-multiarchโ not me staring at this ๐--print-prog-name=programโ the vibe is immaculate โจ--print-search-dirsโ a total slay ๐--print-sysrootโ lowkey dev-only energy ๐ฅ--print-sysroot-headers-suffixโ iconic ๐ฆ--save-tempsโ periodt ๐--specs=fileโ pretty little option ๐ธ--param name=valueโ extremely on brand ๐ง
the page spells this one --print-libgcc-file-file-name with the doubled "file", so copy it exactly ๐
๐ Machine-Dependent Options ๐
these are the target-specific ones, and each chip family gets its own little list ๐ฆ
โจ AArch64 Options โจ
-mabi=nameโ bestie, look at this one ๐-mbig-endianโ main character flag ๐-mlittle-endianโ iykyk ๐ซถ-menable-sysreg-checkingโ not me staring at this ๐-mgeneral-regs-onlyโ the vibe is immaculate โจ-mcmodel=tinyโ a total slay ๐-mcmodel=smallโ lowkey dev-only energy ๐ฅ-mcmodel=largeโ iconic ๐ฆ-mstrict-alignโ periodt ๐-momit-leaf-frame-pointerโ pretty little option ๐ธ-mtls-dialect=descโ extremely on brand ๐ง-mtls-dialect=traditionalโ sparkle moment โญ-mtls-size=sizeโ bestie, look at this one ๐-mtp=nameโ main character flag ๐-mfix-cortex-a53-835769โ iykyk ๐ซถ-mfix-cortex-a53-843419โ not me staring at this ๐-mlow-precision-recip-sqrtโ the vibe is immaculate โจ-mlow-precision-sqrtโ a total slay ๐-mlow-precision-divโ lowkey dev-only energy ๐ฅ-mmax-vectorizationโ iconic ๐ฆ-mautovec-preference=nameโ periodt ๐-mpc-relative-literal-loadsโ pretty little option ๐ธ-msign-return-address=scopeโ extremely on brand ๐ง-mbranch-protection=featuresโ sparkle moment โญ-mharden-sls=optsโ bestie, look at this one ๐-march=nameโ main character flag ๐-mcpu=nameโ iykyk ๐ซถ-mtune=nameโ not me staring at this ๐-moverride=stringโ the vibe is immaculate โจ-mstack-protector-guard=guardโ a total slay ๐-mstack-protector-guard-reg=sysregโ lowkey dev-only energy ๐ฅ-mstack-protector-guard-offset=offsetโ iconic ๐ฆ-mtrack-speculationโ periodt ๐-moutline-atomicsโ pretty little option ๐ธ-mearly-raโ extremely on brand ๐ง-mearly-ldp-fusionโ sparkle moment โญ-mlate-ldp-fusionโ bestie, look at this one ๐-msve-vector-bits=bitsโ main character flag ๐
โจ Adapteva Epiphany Options โจ
-mhalf-reg-fileโ iykyk ๐ซถ-mprefer-short-insn-regsโ not me staring at this ๐-mbranch-cost=numโ the vibe is immaculate โจ-mcmoveโ a total slay ๐-mnops=numโ lowkey dev-only energy ๐ฅ-msoft-cmpsfโ iconic ๐ฆ-msplit-lohiโ periodt ๐-mpost-incโ pretty little option ๐ธ-mpost-modifyโ extremely on brand ๐ง-mstack-offset=numโ sparkle moment โญ-mround-nearestโ bestie, look at this one ๐-mlong-callsโ main character flag ๐-mshort-callsโ iykyk ๐ซถ-msmall16โ not me staring at this ๐-mfp-mode=modeโ the vibe is immaculate โจ-mmay-round-for-truncโ a total slay ๐-mfp-iarithโ lowkey dev-only energy ๐ฅ-mvect-doubleโ iconic ๐ฆ-max-vect-align=numโ periodt ๐-msplit-vecmove-earlyโ pretty little option ๐ธ-m1reg-regโ extremely on brand ๐ง
โจ AMD GCN Options โจ
-march=gpuโ sparkle moment โญ-mtune=gpuโ bestie, look at this one ๐-mgang-private-size=bytesโ main character flag ๐-msram-ecc=[on|off|any]โ iykyk ๐ซถ-mxnack=[on|off|any]โ not me staring at this ๐-Wopenacc-dimsโ the vibe is immaculate โจ
โจ ARC Options โจ
-mbarrel-shifterโ a total slay ๐-mjli-alwaysโ lowkey dev-only energy ๐ฅ-mcpu=cpuโ iconic ๐ฆ-mA6โ periodt ๐-mARC600โ pretty little option ๐ธ-mA7โ extremely on brand ๐ง-mARC700โ sparkle moment โญ-mdpfpโ bestie, look at this one ๐-mdpfp-compactโ main character flag ๐-mdpfp-fastโ iykyk ๐ซถ-mno-dpfp-lrsrโ not me staring at this ๐-meaโ the vibe is immaculate โจ-mmul32x16โ a total slay ๐-mmul64โ lowkey dev-only energy ๐ฅ-matomicโ iconic ๐ฆ-mnormโ periodt ๐-mspfpโ pretty little option ๐ธ-mspfp-compactโ extremely on brand ๐ง-mspfp-fastโ sparkle moment โญ-msimdโ bestie, look at this one ๐-msoft-floatโ main character flag ๐-mswapโ iykyk ๐ซถ-mlockโ not me staring at this ๐-mswapeโ the vibe is immaculate โจ-mxyโ a total slay ๐-misizeโ lowkey dev-only energy ๐ฅ-marclinuxโ iconic ๐ฆ-marclinux_profโ periodt ๐-mlong-callsโ pretty little option ๐ธ-mmedium-callsโ extremely on brand ๐ง-msdataโ sparkle moment โญ-mirq-ctrl-savedโ bestie, look at this one ๐-mrgf-banked-regsโ main character flag ๐-mlpc-width=widthโ iykyk ๐ซถ-G numโ not me staring at this ๐-mvolatile-cacheโ the vibe is immaculate โจ-mtp-regno=regnoโ a total slay ๐-mbitopsโ lowkey dev-only energy ๐ฅ-mcmemโ iconic ๐ฆ-munaligned-accessโ periodt ๐-mauto-modify-regโ pretty little option ๐ธ-mno-brccโ extremely on brand ๐ง-mcase-vector-pcrelโ sparkle moment โญ-mno-cond-execโ bestie, look at this one ๐-mearly-cbranchsiโ main character flag ๐-mindexed-loadsโ iykyk ๐ซถ-mlra-priority-noneโ not me staring at this ๐-mlra-priority-compactโ the vibe is immaculate โจ-mlra-priority-noncompactโ a total slay ๐-mmillicodeโ lowkey dev-only energy ๐ฅ-msize-level=levelโ iconic ๐ฆ-mtune=cpuโ periodt ๐-mmultcost=numโ pretty little option ๐ธ-mcode-density-frameโ extremely on brand ๐ง-mmpy-option=multoโ sparkle moment โญ-mdiv-remโ bestie, look at this one ๐-mcode-densityโ main character flag ๐-mll64โ iykyk ๐ซถ-mfpu=fpuโ not me staring at this ๐-mrf16โ the vibe is immaculate โจ-mbranch-indexโ a total slay ๐
โจ ARM Options โจ
-mapcs-frameโ lowkey dev-only energy ๐ฅ-mapcsโ iconic ๐ฆ-mabi=nameโ periodt ๐-mgeneral-regs-onlyโ pretty little option ๐ธ-mno-sched-prologโ extremely on brand ๐ง-mlittle-endianโ sparkle moment โญ-mbig-endianโ bestie, look at this one ๐-mbe8โ main character flag ๐-mbe32โ iykyk ๐ซถ-mfloat-abi=nameโ not me staring at this ๐-mfp16-format=nameโ the vibe is immaculate โจ-mthumb-interworkโ a total slay ๐-mcpu=nameโ lowkey dev-only energy ๐ฅ-march=nameโ iconic ๐ฆ-mfpu=nameโ periodt ๐-mtune=nameโ pretty little option ๐ธ-mstructure-size-boundary=nโ extremely on brand ๐ง-mabort-on-noreturnโ sparkle moment โญ-mlong-callsโ bestie, look at this one ๐-msingle-pic-baseโ main character flag ๐-mpic-register=regโ iykyk ๐ซถ-mpic-data-is-text-relativeโ not me staring at this ๐-mnop-fun-dllimportโ the vibe is immaculate โจ-mpoke-function-nameโ a total slay ๐-mthumbโ lowkey dev-only energy ๐ฅ-marmโ iconic ๐ฆ-mtpcs-frameโ periodt ๐-mtpcs-leaf-frameโ pretty little option ๐ธ-mcaller-super-interworkingโ extremely on brand ๐ง-mcallee-super-interworkingโ sparkle moment โญ-mtp=nameโ bestie, look at this one ๐-mtls-dialect=dialectโ main character flag ๐-mword-relocationsโ iykyk ๐ซถ-mfix-cortex-m3-ldrdโ not me staring at this ๐-mfix-cortex-a57-aes-1742098โ the vibe is immaculate โจ-mfix-cortex-a72-aes-1655431โ a total slay ๐-munaligned-accessโ lowkey dev-only energy ๐ฅ-mslow-flash-dataโ iconic ๐ฆ-masm-syntax-unifiedโ periodt ๐-mrestrict-itโ pretty little option ๐ธ-mpure-codeโ extremely on brand ๐ง-mcmseโ sparkle moment โญ-mfix-cmse-cve-2021-35465โ bestie, look at this one ๐-mstack-protector-guard=guardโ main character flag ๐-mstack-protector-guard-offset=offsetโ iykyk ๐ซถ-mfdpicโ not me staring at this ๐-mbranch-protection=featuresโ the vibe is immaculate โจ-mvectorize-with-neon-quadโ a total slay ๐-mvectorize-with-neon-doubleโ lowkey dev-only energy ๐ฅ
โจ AVR Options โจ
-mmcu=mcuโ iconic ๐ฆ-mabsdataโ periodt ๐-maccumulate-argsโ pretty little option ๐ธ-mcvtโ extremely on brand ๐ง-mbranch-cost=costโ sparkle moment โญ-mfuse-add=levelโ bestie, look at this one ๐-mfuse-move=levelโ main character flag ๐-mfuse-move2โ iykyk ๐ซถ-mcall-prologuesโ not me staring at this ๐-mgas-isr-prologuesโ the vibe is immaculate โจ-mint8โ a total slay ๐-mflmapโ lowkey dev-only energy ๐ฅ-mdouble=bitsโ iconic ๐ฆ-mlong-double=bitsโ periodt ๐-mno-call-mainโ pretty little option ๐ธ-mn_flash=sizeโ extremely on brand ๐ง-mfract-convert-truncateโ sparkle moment โญ-mno-interruptsโ bestie, look at this one ๐-mmain-is-OS_taskโ main character flag ๐-mrelaxโ iykyk ๐ซถ-mpmem-wrap-aroundโ not me staring at this ๐-mrmwโ the vibe is immaculate โจ-mstrict-Xโ a total slay ๐-mtiny-stackโ lowkey dev-only energy ๐ฅ-mrodata-in-ramโ iconic ๐ฆ-msplit-bit-shiftโ periodt ๐-msplit-ldstโ pretty little option ๐ธ-mshort-callsโ extremely on brand ๐ง-mskip-bugโ sparkle moment โญ-muse-nonzero-bitsโ bestie, look at this one ๐-nodevicelibโ main character flag ๐-nodevicespecsโ iykyk ๐ซถ-Waddr-space-convertโ not me staring at this ๐-Wmisspelled-isrโ the vibe is immaculate โจ
โจ Blackfin Options โจ
-mcpu=cpu[-sirevision]โ a total slay ๐-msimโ lowkey dev-only energy ๐ฅ-momit-leaf-frame-pointerโ iconic ๐ฆ-mspecld-anomalyโ periodt ๐-mcsync-anomalyโ pretty little option ๐ธ-mlow-64kโ extremely on brand ๐ง-mstack-check-l1โ sparkle moment โญ-mid-shared-libraryโ bestie, look at this one ๐-mleaf-id-shared-libraryโ main character flag ๐-mshared-library-id=nโ iykyk ๐ซถ-msep-dataโ not me staring at this ๐-mlong-callsโ the vibe is immaculate โจ-mfast-fpโ a total slay ๐-minline-pltโ lowkey dev-only energy ๐ฅ-mmulticoreโ iconic ๐ฆ-mcoreaโ periodt ๐-mcorebโ pretty little option ๐ธ-msdramโ extremely on brand ๐ง-micplbโ sparkle moment โญ
โจ C6X Options โจ
-mbig-endianโ bestie, look at this one ๐-mlittle-endianโ main character flag ๐-march=cpuโ iykyk ๐ซถ-msimโ not me staring at this ๐-msdata=sdata-typeโ the vibe is immaculate โจ-mdsbtโ a total slay ๐-mlong-callsโ lowkey dev-only energy ๐ฅ
โจ CRIS Options โจ
-mcpu=cpuโ iconic ๐ฆ-march=cpuโ periodt ๐-mtune=cpuโ pretty little option ๐ธ-mmax-stackframe=nโ extremely on brand ๐ง-metrax4โ sparkle moment โญ-metrax100โ bestie, look at this one ๐-mpdebugโ main character flag ๐-mcc-initโ iykyk ๐ซถ-mno-side-effectsโ not me staring at this ๐-mstack-alignโ the vibe is immaculate โจ-mdata-alignโ a total slay ๐-mconst-alignโ lowkey dev-only energy ๐ฅ-m32-bitโ iconic ๐ฆ-m16-bitโ periodt ๐-m8-bitโ pretty little option ๐ธ-mno-prologue-epilogueโ extremely on brand ๐ง-mbest-lib-optionsโ sparkle moment โญ-moverride-best-lib-optionsโ bestie, look at this one ๐-mtrap-using-break8โ main character flag ๐-mtrap-unaligned-atomicโ iykyk ๐ซถ-munaligned-atomic-may-use-libraryโ not me staring at this ๐-simโ the vibe is immaculate โจ-sim2โ a total slay ๐-mmul-bug-workaroundโ lowkey dev-only energy ๐ฅ
โจ C-SKY Options โจ
-march=archโ iconic ๐ฆ-mcpu=cpuโ periodt ๐-mbig-endianโ pretty little option ๐ธ-mlittle-endianโ extremely on brand ๐ง-mfpu=fpuโ sparkle moment โญ-mdouble-floatโ bestie, look at this one ๐-mfdivduโ main character flag ๐-mfloat-abi=nameโ iykyk ๐ซถ-melrwโ not me staring at this ๐-mistackโ the vibe is immaculate โจ-mmpโ a total slay ๐-mcpโ lowkey dev-only energy ๐ฅ-mcacheโ iconic ๐ฆ-msecurityโ periodt ๐-mtrustโ pretty little option ๐ธ-mdspโ extremely on brand ๐ง-medspโ sparkle moment โญ-mvdspโ bestie, look at this one ๐-mdivโ main character flag ๐-msmartโ iykyk ๐ซถ-mhigh-registersโ not me staring at this ๐-manchorโ the vibe is immaculate โจ-mpushpopโ a total slay ๐-mmultiple-stldโ lowkey dev-only energy ๐ฅ-mconstpoolโ iconic ๐ฆ-mstack-sizeโ periodt ๐-mccrtโ pretty little option ๐ธ-mbranch-cost=nโ extremely on brand ๐ง-msched-prologโ sparkle moment โญ-msimโ bestie, look at this one ๐
โจ Cygwin and MinGW Options โจ
-mconsoleโ main character flag ๐-mcrtdll=libraryโ iykyk ๐ซถ-mdllโ not me staring at this ๐-mnop-fun-dllimportโ the vibe is immaculate โจ-mthreadsโ a total slay ๐-municodeโ lowkey dev-only energy ๐ฅ-mwin32โ iconic ๐ฆ-mwindowsโ periodt ๐-fno-set-stack-executableโ pretty little option ๐ธ-fwritable-relocated-rdataโ extremely on brand ๐ง-mpe-aligned-commonsโ sparkle moment โญ-muse-libstdc-wrappersโ bestie, look at this one ๐
โจ Darwin Options โจ
-all_loadโ main character flag ๐-allowable_clientโ iykyk ๐ซถ-arch nameโ not me staring at this ๐-arch_errors_fatalโ the vibe is immaculate โจ-asm_macosx_version_min=versionโ a total slay ๐-bind_at_loadโ lowkey dev-only energy ๐ฅ-bundleโ iconic ๐ฆ-bundle_loaderโ periodt ๐-client_nameโ pretty little option ๐ธ-compatibility_versionโ extremely on brand ๐ง-current_versionโ sparkle moment โญ-dead_stripโ bestie, look at this one ๐-dependency-fileโ main character flag ๐-dylib_fileโ iykyk ๐ซถ-dylinkerโ not me staring at this ๐-dylinker_install_nameโ the vibe is immaculate โจ-dynamicโ a total slay ๐-dynamiclibโ lowkey dev-only energy ๐ฅ-exported_symbols_listโ iconic ๐ฆ-fapple-kextโ periodt ๐-fconstant-cfstringsโ pretty little option ๐ธ-ffix-and-continueโ extremely on brand ๐ง-filelistโ sparkle moment โญ-findirect-dataโ bestie, look at this one ๐-flat_namespaceโ main character flag ๐-force_cpusubtype_ALLโ iykyk ๐ซถ-force_flat_namespaceโ not me staring at this ๐-framework nameโ the vibe is immaculate โจ-gfullโ a total slay ๐-gusedโ lowkey dev-only energy ๐ฅ-headerpad_max_install_namesโ iconic ๐ฆ-iframeworkโ periodt ๐-image_baseโ pretty little option ๐ธ-init symbol-nameโ extremely on brand ๐ง-install_nameโ sparkle moment โญ-keep_private_externsโ bestie, look at this one ๐-matt-stubsโ main character flag ๐-mconstant-cfstringsโ iykyk ๐ซถ-mdynamic-no-picโ not me staring at this ๐-mfix-and-continueโ the vibe is immaculate โจ-mkernelโ a total slay ๐-mmacosx-version-min=versionโ lowkey dev-only energy ๐ฅ-mone-byte-boolโ iconic ๐ฆ-msymbol-stubsโ periodt ๐-mtarget-linker[=]versionโ pretty little option ๐ธ-nodefaultexportโ extremely on brand ๐ง-nodefaultrpathsโ sparkle moment โญ-pagezero_sizeโ bestie, look at this one ๐-preloadโ main character flag ๐-read_only_relocsโ iykyk ๐ซถ-sectalignโ not me staring at this ๐-sectcreateโ the vibe is immaculate โจ-seg_addr_tableโ a total slay ๐-seg1addrโ lowkey dev-only energy ๐ฅ-segaddrโ iconic ๐ฆ-segprotโ periodt ๐-segs_read_only_addrโ pretty little option ๐ธ-segs_read_write_addrโ extremely on brand ๐ง-sub_libraryโ sparkle moment โญ-sub_umbrellaโ bestie, look at this one ๐-twolevel_namespaceโ main character flag ๐-twolevel_namespace_hintsโ iykyk ๐ซถ-umbrellaโ not me staring at this ๐-undefinedโ the vibe is immaculate โจ-unexported_symbols_listโ a total slay ๐-weak_framework nameโ lowkey dev-only energy ๐ฅ-weak_reference_mismatchesโ iconic ๐ฆ-whatsloadedโ periodt ๐-whyloadโ pretty little option ๐ธ-Fโ extremely on brand ๐ง-ObjCโ sparkle moment โญ-ObjC++โ bestie, look at this one ๐-Wnonportable-cfstringsโ main character flag ๐
โจ DEC Alpha Options โจ
-mno-fp-regsโ iykyk ๐ซถ-msoft-floatโ not me staring at this ๐-mieeeโ the vibe is immaculate โจ-mieee-with-inexactโ a total slay ๐-mieee-conformantโ lowkey dev-only energy ๐ฅ-mfp-trap-mode=modeโ iconic ๐ฆ-mfp-rounding-mode=modeโ periodt ๐-mtrap-precision=modeโ pretty little option ๐ธ-mbuild-constantsโ extremely on brand ๐ง-mcpu=cpu-typeโ sparkle moment โญ-mtune=cpu-typeโ bestie, look at this one ๐-mbwxโ main character flag ๐-mmaxโ iykyk ๐ซถ-mfixโ not me staring at this ๐-mcixโ the vibe is immaculate โจ-msafe-bwaโ a total slay ๐-msafe-partialโ lowkey dev-only energy ๐ฅ-mfloat-vaxโ iconic ๐ฆ-mfloat-ieeeโ periodt ๐-mexplicit-relocsโ pretty little option ๐ธ-msmall-dataโ extremely on brand ๐ง-mlarge-dataโ sparkle moment โญ-msmall-textโ bestie, look at this one ๐-mlarge-textโ main character flag ๐-mmemory-latency=timeโ iykyk ๐ซถ-mtls-kernelโ not me staring at this ๐-mtls-size=bitsizeโ the vibe is immaculate โจ-mlong-double-128โ a total slay ๐-mlong-double-64โ lowkey dev-only energy ๐ฅ
โจ eBPF Options โจ
-mbig-endianโ iconic ๐ฆ-mlittle-endianโ periodt ๐-mframe-limit=bytesโ pretty little option ๐ธ-mxbpfโ extremely on brand ๐ง-mco-reโ sparkle moment โญ-mjmpextโ bestie, look at this one ๐-mjmp32โ main character flag ๐-malu32โ iykyk ๐ซถ-mv3-atomicsโ not me staring at this ๐-mbswapโ the vibe is immaculate โจ-msdivโ a total slay ๐-msmovโ lowkey dev-only energy ๐ฅ-mcpu=versionโ iconic ๐ฆ-masm=dialectโ periodt ๐-minline-memops-threshold=bytesโ pretty little option ๐ธ-Wco-reโ extremely on brand ๐ง
โจ FR30 Options โจ
-msmall-modelโ sparkle moment โญ-mno-lsimโ bestie, look at this one ๐
โจ FRV Options โจ
-mgpr-32โ main character flag ๐-mgpr-64โ iykyk ๐ซถ-mfpr-32โ not me staring at this ๐-mfpr-64โ the vibe is immaculate โจ-mhard-floatโ a total slay ๐-msoft-floatโ lowkey dev-only energy ๐ฅ-malloc-ccโ iconic ๐ฆ-mfixed-ccโ periodt ๐-mdwordโ pretty little option ๐ธ-mdoubleโ extremely on brand ๐ง-mmediaโ sparkle moment โญ-mmuladdโ bestie, look at this one ๐-mfdpicโ main character flag ๐-minline-pltโ iykyk ๐ซถ-mgprel-roโ not me staring at this ๐-multilib-library-picโ the vibe is immaculate โจ-mlinked-fpโ a total slay ๐-mlong-callsโ lowkey dev-only energy ๐ฅ-malign-labelsโ iconic ๐ฆ-mlibrary-picโ periodt ๐-macc-4โ pretty little option ๐ธ-macc-8โ extremely on brand ๐ง-mpackโ sparkle moment โญ-mno-eflagsโ bestie, look at this one ๐-mno-cond-moveโ main character flag ๐-mno-optimize-membarโ iykyk ๐ซถ-mno-sccโ not me staring at this ๐-mno-cond-execโ the vibe is immaculate โจ-mno-vliw-branchโ a total slay ๐-mno-multi-cond-execโ lowkey dev-only energy ๐ฅ-mno-nested-cond-execโ iconic ๐ฆ-mtomcat-statsโ periodt ๐-mTLSโ pretty little option ๐ธ-mtlsโ extremely on brand ๐ง-mcpu=cpuโ sparkle moment โญ
โจ FT32 Options โจ
-msimโ bestie, look at this one ๐-mnodivโ main character flag ๐-mft32bโ iykyk ๐ซถ-mcompressโ not me staring at this ๐-mnopmโ the vibe is immaculate โจ
โจ GNU/Linux Options โจ
-mglibcโ a total slay ๐-muclibcโ lowkey dev-only energy ๐ฅ-mmuslโ iconic ๐ฆ-mbionicโ periodt ๐-mandroidโ pretty little option ๐ธ-tno-android-ccโ extremely on brand ๐ง-tno-android-ldโ sparkle moment โญ
โจ H8/300 Options โจ
-mrelaxโ bestie, look at this one ๐-mhโ main character flag ๐-msโ iykyk ๐ซถ-mnโ not me staring at this ๐-msxโ the vibe is immaculate โจ-ms2600โ a total slay ๐-mquickcallโ lowkey dev-only energy ๐ฅ-mslowbyteโ iconic ๐ฆ-mexrโ periodt ๐-mint32โ pretty little option ๐ธ-malign-300โ extremely on brand ๐ง
๐ธ HPPA Options (HPPA Options) ๐ธ
Okay bestie, the HPPA flags are literally so iconic ๐ Here's the whole squad:
-march=architecture-type-mno-atomic-libcalls-mcaller-copies-mdisable-fpregs-mdisable-indexing-mordered-mfast-indirect-calls-mgas-mgnu-ld-mhp-ld-mfixed-range=register-range-mcoherent-ldcw-mlinker-opt-mlong-calls-mlong-load-store-mno-space-regs-msoft-float-mpa-risc-1-0-mpa-risc-1-1-mpa-risc-2-0-mportable-runtime-mschedule=cpu-type-msoft-mult-msio-mwsio-munix=unix-std-nolibdld-static-threads
๐ฆ IA-64 Options (IA-64 Options) ๐ฆ
The IA-64 crew is huge, so grab a snack ๐
-mbig-endian-mlittle-endian-mgnu-as-mgnu-ld-mno-pic-mvolatile-asm-stop-mregister-names-msdata-mconstant-gp-mauto-pic-minline-float-divide-min-latency-minline-float-divide-max-throughput-mno-inline-float-divide-minline-int-divide-min-latency-minline-int-divide-max-throughput-mno-inline-int-divide-minline-sqrt-min-latency-minline-sqrt-max-throughput-mno-inline-sqrt-mdwarf2-asm-mearly-stop-bits-mfixed-range=register-range-mtls-size=tls-size-mtune=cpu-type-milp32-mlp64-msched-br-data-spec-msched-ar-data-spec-msched-control-spec-msched-br-in-data-spec-msched-ar-in-data-spec-msched-in-control-spec-msched-spec-ldc-msched-spec-control-ldc-msched-stop-bits-after-every-cycle-msched-count-spec-in-critical-path-msel-sched-dont-check-control-spec-msched-fp-mem-deps-zero-cost-msched-max-memory-insns-hard-limit-msched-max-memory-insns=max-insns
๐ง LM32 Options (LM32 Options) ๐ง
Small but mighty โจ
-mbarrel-shift-enabled-mdivide-enabled-mmultiply-enabled-msign-extend-enabled-muser-enabled
๐ LoongArch Options (LoongArch Options) ๐
The LoongArch list is giving main character energy ๐
-march=arch-type-mtune=tune-type-mabi=base-abi-type-mfpu=fpu-type-msimd=simd-type-msoft-float-msingle-float-mdouble-float-mlsx-mlasx-mbranch-cost=n-maddr-reg-reg-cost=n-mcheck-zero-division-mbreak-code=code-mcond-move-int-mcond-move-float-memcpy-mstrict-align-G num-mmax-inline-memcpy-size=n-mexplicit-relocs=style-mexplicit-relocs-mno-explicit-relocs-mdirect-extern-access-mcmodel=code-model-mrelax-mpass-mrelax-to-as-mrecip-mrecip=opt-mfrecipe-mdiv32-mlam-bh-mlamcas-mld-seq-sa-mscq-mtls-dialect=opt-mannotate-tablejump
๐ LynxOS Options (LynxOS Options) ๐
-mshared-mthreads-mlegacy-threads
๐ M32C Options (M32C Options) ๐
-mcpu=cpu-msim-memregs=number
๐ M32R/D Options (M32R/D Options) ๐
-m32r2-m32rx-m32r-mdebug-malign-loops-missue-rate=number-mbranch-cost=number-mmodel=code-size-model-type-msdata=sdata-type-mno-flush-func-mflush-func=name-mno-flush-trap-mflush-trap=number-G num
๐ซถ M680x0 Options (M680x0 Options) ๐ซถ
The M680x0 lineup is absolutely stacked ๐ฅ
-march=arch-mcpu=cpu-mtune=tune-m68000-m68020-m68020-40-m68020-60-m68030-m68040-m68060-m68302-m68332-m68851-mcpu32-mfidoa-m5200-m5206e-m528x-m5307-m5407-mcfv4e-mbitfield-mc68000-mc68020-mrtd-mdiv-mshort-mhard-float-m68881-msoft-float-mpcrel-malign-int-mstrict-align-msep-data-mshared-library-id=n-mid-shared-library-mxgot-mxtls-mlong-jump-table-offsets
๐ธ MCore Options (MCore Options) ๐ธ
-mhardlit-mdiv-mrelax-immediates-mwide-bitfields-m4byte-functions-mcallgraph-data-mslow-bytes-mno-lsim-mlittle-endian-mbig-endian-m210-m340-mstack-increment
๐ฆ MicroBlaze Options (MicroBlaze Options) ๐ฆ
-msoft-float-mhard-float-msmall-divides-mcpu=cpu-mmemcpy-mxl-soft-mul-mxl-soft-div-mxl-barrel-shift-mxl-pattern-compare-mxl-gp-opt-mxl-multiply-high-mxl-float-convert-mxl-float-sqrt-mbig-endian-mlittle-endian-mxl-reorder-mxl-mode-app-model-mxl-prefetch-mpic-data-is-text-relative
๐ MIPS Options (MIPS Options) ๐
Okay the MIPS section is the longest one, so get comfy bestie ๐๏ธโจ
-EL-EB-mel-meb-march=arch-mtune=arch-mips1-mips2-mips3-mips4-mips32-mips32r2-mips32r3-mips32r5-mips32r6-mips64-mips64r2-mips64r3-mips64r5-mips64r6-mips16-mmips16e2-mflip-mips16-minterlink-compressed-minterlink-mips16-mabi=abi-mabicalls-mshared-mplt-mxgot-mgp32-mgp64-mfp32-mfpxx-mfp64-mhard-float-msoft-float-mno-float-msingle-float-mdouble-float-modd-spreg-mabs=mode-mnan=encoding-mdsp-mdspr2-mmcu-meva-mvirt-mxpa-mcrc-mginv-mmicromips-mmsa-mloongson-mmi-mloongson-ext-mloongson-ext2-mfpu=fpu-type-msmartmips-mpaired-single-mdmx-mips3d-mmt-mllsc-mlong64-mlong32-msym32-Gnum-mno-local-sdata-mno-extern-sdata-mno-gopt-membedded-data-muninit-const-in-rodata-mcode-readable=setting-mno-data-in-code-mcode-xonly-msplit-addresses-mexplicit-relocs-mexplicit-relocs=release-mno-check-zero-division-mdivide-traps-mdivide-breaks-mno-load-store-pairs-mstrict-align-mno-unaligned-access-mmemcpy-mlong-calls-mmad-mimadd-mno-fused-madd-nocpp-mfix-24k-mfix-r4000-mfix-r4400-mfix-r5900-mfix-r10000-mfix-rm7000-mfix-vr4120-mfix-vr4130-mfix-sb1-mfix4300-mr10k-cache-barrier=setting-mflush-func=func-mno-flush-func-mbranch-cost=num-mbranch-likely-mcompact-branches=policy-mno-fp-exceptions-mvr4130-align-msynci-mno-lxc1-sxc1-mno-madd4-mno-relax-pic-calls-mmcount-ra-address-mframe-header-opt
๐ง MMIX Options (MMIX Options) ๐ง
-mlibfuncs-mepsilon-mabi=gnu-mabi=mmixware-mzero-extend-mknuthdiv-mtoplevel-symbols-melf-mbranch-predict-mbase-addresses-msingle-exit-mset-data-start=address-mset-program-start=address-mno-set-program-start
๐ MN10300 Options (MN10300 Options) ๐
-mmult-bug-mno-mult-bug-mam33-mam33-2-mam34-mtune=cpu-type-mno-return-pointer-on-d0-mno-crt0-mrelax-mno-liw-mno-setlb
๐ Moxie Options (Moxie Options) ๐
-meb-mel-mmul.x-mno-crt0
๐ MSP430 Options (MSP430 Options) ๐
Okay the MSP430 list has some seriously specific vibes ๐ฅ
-msim-masm-hex-mmcu=name-mlarge-msmall-mrelax-mwarn-mcu-mwarn-devices-csv-mcode-region=where-mdata-region=where-muse-lower-region-prefix-msilicon-errata=name[,name...]-msilicon-errata-warn=name[,name...]-mhwmult=type-minrt-mtiny-printf-mmax-inline-shift=n
๐ซถ NDS32 Options (NDS32 Options) ๐ซถ
-mbig-endian-mlittle-endian-EB-EL-mabi=name-mfloat-abi=name-mreduced-regs-mfull-regs-malways-align-malign-functions-mfp-as-gp-mcmov-mhw-abs-mext-perf-mext-perf2-mext-string-mext-dsp-mext-fpu-fma-mext-fpu-sp-mext-fpu-dp-mv3push-m16-bit-mvh-misr-vector-size=num-misr-secure=num-mcache-block-size=num-march=arch-mcpu=cpu-mconfig-fpu=num-mconfig-mul=type-mconfig-register-ports=kind-mcmodel=code-model-mctor-dtor-mrelax-mrelax-hint-msched-prolog-epilog-mno-ret-in-naked-func-malways-save-lp-munaligned-access-minline-asm-r15
๐ Nvidia PTX Options (Nvidia PTX Options) ๐
-m64-march=arch-misa=arch-march-map=arch-mptx=version-mmainkernel-moptimize-msoft-stack-msoft-stack-reserve-local=size-muniform-simt-mgomp
๐ฆ OpenRISC Options (OpenRISC Options) ๐ฆ
-mboard=name-mhard-mul-mhard-div-msoft-mul-msoft-div-msoft-float-mhard-float-mdouble-float-munordered-float-mcmov-mror-mrori-msext-msfimm-mshftimm-mcmodel=code-model
๐ PDP-11 Options (PDP-11 Options) ๐
-mfpu-msoft-float-mac0-m40-m45-m10-mint32-mint16-msplit-munix-asm-mdec-asm-mgnu-asm-mlra
๐ง PowerPC Options ๐ง
Soooo the PowerPC stuff lives somewhere else, bestie. Check out RS/6000 and PowerPC Options ๐
๐ธ PRU Options (PRU Options) ๐ธ
-mmcu=mcu-minrt-mno-relax-mloop-mmul-mfillzero-mabi=variant
๐ RISC-V Options (RISC-V Options) ๐
The RISC-V list is a whole vibe, iykyk ๐ฅโจ
-mbranch-cost=N-instruction-mabi=ABI-string-mfdiv-mdiv-mno-fence-tso-misa-spec=ISA-spec-string-march=[ISA|Profile|Profile_ISA|processor-string]-mcpu=processor-string-mtune=processor-string-mpreferred-stack-boundary=num-msmall-data-limit=N-bytes-msave-restore-mno-shorten-memrefs-mstrict-align-mscalar-strict-align-mno-vector-strict-align-mcmodel=medlow-mcmodel=medany-mcmodel=large-mexplicit-relocs-mrelax-mriscv-attribute-malign-data=type-mbig-endian-mlittle-endian-mstack-protector-guard=guard-mstack-protector-guard-reg=reg-mstack-protector-guard-offset=offset-mcsr-check-momit-leaf-frame-pointer-mmovcc-mno-inline-atomics-mno-inline-strlen-mno-inline-strcmp-mno-inline-strncmp-mstringop-strategy=strategy-mtls-dialect=desc-mtls-dialect=trad-mrvv-vector-bits=value-mrvv-max-lmul=value-madjust-lmul-cost-mmax-vectorization-mno-autovec-segment
๐ซถ RL78 Options (RL78 Options) ๐ซถ
Last but not least, the RL78 crew ๐ฆ๐
-msim-mallregs-mrelax-mes0-mmul=none-mmul=g13-mmul=g14-mmul=rl78-mcpu=g10-mcpu=g13-mcpu=g14-mcpu=rl78-mg10-mg13-mg14-mrl78-msave-mduc-in-interrupts
๐ RS/6000 and PowerPC Options
Okay bestie, this list is absolutely massive ๐ These are the flags for the PowerPC family, so they only matter when you're targeting that chip ๐ง
-mcpu=cpu-type -mtune=cpu-type -mcmodel=code-model -mprofile-kernel -mpowerpc64 -maltivec -mpowerpc-gpopt -mpowerpc-gfxopt -mmfcrf -mpopcntb -mpopcntd -mfprnd -mcmpb -mhard-dfp -mfull-toc -mminimal-toc -mno-fp-in-toc -mno-sum-in-toc -maix64 -maix32 -m64 -m32 -mxl-compat -mpe -malign-power -malign-natural -msoft-float -mhard-float -mmultiple -mupdate -mavoid-indexed-addresses -mfused-madd -mbit-align -mbit-word -mstrict-align -mrelocatable -mrelocatable-lib -mlittle -mlittle-endian -mbig -mbig-endian -mdynamic-no-pic -msingle-pic-base -mprioritize-restricted-insns=priority -msched-costly-dep=dependence_type -minsert-sched-nops=scheme -mcall-aixdesc -mcall-eabi -mcall-freebsd -mcall-linux -mcall-netbsd -mcall-openbsd -mcall-sysv -mcall-sysv-eabi -mcall-sysv-noeabi -mtraceback=traceback_type -maix-struct-return -msvr4-struct-return -mabi=abi-type -msecure-plt -mbss-plt -msplit-patch-nops -mregnames -mlongcall -mpltseq -mtls-markers -mblock-move-inline-limit=num -mblock-compare-inline-limit=num -mblock-compare-inline-loop-limit=num -mblock-ops-unaligned-vsx -mstring-compare-inline-limit=num -misel -mvsx -mvrsave -mmulhw -mdlmzb -mprototype -msim -mmvme -mads -myellowknife -memb -meabi -msdata -msdata=opt -mreadonly-in-sdata -mvxworks -G num -mrecip -mrecip=opt -mno-recip -mrecip-precision -mveclibabi=type -mfriz -mpointers-to-nested-functions -msave-toc-indirect -mpower8-fusion -mcrypto -mhtm -mquad-memory -mquad-memory-atomic -mcompat-align-parm -mfloat128 -mfloat128-hardware -mgnu-attribute -mstack-protector-guard=guard -mstack-protector-guard-reg=reg -mstack-protector-guard-offset=offset -mprefixed -mpcrel -mmma -mrop-protect -mprivileged -mno-splat-word-constant -mno-splat-float-constant -mno-ieee128-constant -mno-warn-altivec-long
๐ธ RX Options
Heads up: these are the RX chip flags, so they're only for RX targets ๐
-m64bit-doubles -m32bit-doubles -fpu -nofpu -mcpu=name -mbig-endian-data -mlittle-endian-data -msmall-data-limit=N -msim -mas100-syntax -mrelax -mmax-constant-size=N -mint-register=N -mpid -mno-allow-string-insns -mjsr -mno-warn-multiple-fast-interrupts -msave-acc-in-interrupts -mlra
๐ง S/390 and zSeries Options
-mtune=cpu-type -march=cpu-type -mhard-float -msoft-float -mhard-dfp -mlong-double-64 -mlong-double-128 -mbackchain -mpacked-stack -msmall-exec -mmvcle -m64 -m31 -mdebug -mesa -mzarch -mhtm -mvx -mzvector -mtpf-trace -mtpf-trace-skip -mmain -mfused-madd -mno-fused-madd -mwarn-framesize=framesize -mwarn-dynamicstack -mstack-size=stack-size -mno-stack-size -mstack-guard=stack-guard -mno-stack-guard -mstack-protector-guard=guard -mstack-protector-guard-record -mhotpatch=pre-halfwords,post-halfwords -mno-pic-data-is-text-relative -mindirect-branch=choice -mindirect-branch-jump=choice -mindirect-branch-call=choice -mfunction-return=choice -mfunction-return-mem=choice -mfunction-return-reg=choice -mindirect-branch-table -mfentry -mrecord-mcount -mnop-mcount -mpreserve-args -munaliged-symbols
๐ SH Options
-m1 -m2 -m2e -m2a -m2a-nofpu -m2a-single -m2a-single-only -m3 -m3e -m4 -m4-nofpu -m4-single -m4-single-only -m4-100 -m4-100-nofpu -m4-100-single -m4-100-single-only -m4-200 -m4-200-nofpu -m4-200-single -m4-200-single-only -m4-300 -m4-300-nofpu -m4-300-single -m4-300-single-only -m4-340 -m4-400 -m4-500 -m4a -m4al -m4a-nofpu -m4a-single -m4a-single-only -mb -ml -mdalign -mrelax -mbigtable -mbitops -mfmovd -mrenesas -mnomacsave -mieee -misize -minline-ic_invalidate -mprefergot -musermode -multcost=number -mdiv=strategy -mdivsi3_libfunc=name -mfixed-range=register-range -maccumulate-outgoing-args -matomic-model=atomic-model -mbranch-cost=num -mzdcbranch -mcbranch-force-delay-slot -mfsca -mfsrra -mpretend-cmove -mfdpic -mtas -mlra
๐ Solaris 2 Options
-mclear-hwcap -mno-clear-hwcap -mimpure-text -mno-impure-text -gsctf
๐ SPARC Options
-mcpu=cpu-type -mtune=cpu-type -mcmodel=code-model -mmemory-model=mem-model -m32 -m64 -mptr32 -mptr64 -mapp-regs -mfaster-structs -mflat -mfpu -mhard-float -msoft-float -mhard-quad-float -msoft-quad-float -mstack-bias -mstd-struct-return -munaligned-doubles -muser-mode -mv8plus -mvis -mvis2 -mvis3 -mvis3b -mvis4 -mvis4b -mcbcond -mfmaf -mfsmuld -mpopc -msubxc -mfix-at697f -mfix-ut699 -mfix-ut700 -mfix-gr712rc
๐ซถ System V Options
-YP,paths -Ym,dir
๐ฅ V850 Options
-mlong-calls -mep -mprolog-function -mspace -mtda=n -msda=n -mzda=n -mv850 -mv850e3v5 -m850e2v4 -mv850e2v3 -mv850e2 -mv850e1 -mv850es -mv850e -mdisable-callt -mrelax -mlong-jumps -msoft-float -mhard-float -mloop -mrh850-abi -mghs -mgcc-abi -m8byte-align -mbig-switch -mapp-regs -msmall-sld -mno-strict-align -mjump-tables-in-data-section
๐ฆ VAX Options
-munix -mgnu -md -md-float -mg -mg-float -mlra -mvaxc-alignment -mqmath
โจ Visium Options
-mdebug -msim -mfpu -mhard-float -msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
๐ VMS Options
-mvms-return-codes -mdebug-main=prefix -mmalloc64 -mpointer-size=size
๐ VxWorks Options
-mrtp -msmp -mvthreads -non-static -Bstatic -Bdynamic -Xbind-lazy -Xbind-now
๐ x86 Options
-mtune=cpu-type -march=cpu-type -mtune-ctrl=feature-list -mdump-tune-features -mno-default -mfpmath=unit -masm=dialect -mno-fancy-math-387 -mno-fp-ret-in-387 -m80387 -mhard-float -msoft-float -mieee-fp -mrtd -malign-double -mpreferred-stack-boundary=num -mincoming-stack-boundary=num -mcld -mcx16 -msahf -mmovbe -mcrc32 -mmwait -mrecip -mrecip=opt -mvzeroupper -mstv -mprefer-avx128 -mprefer-vector-width=opt -mpartial-vector-fp-math -mmove-max=bits -mstore-max=bits -mnoreturn-no-callee-saved-registers -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx -mavx2 -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mavx512vbmi -msha -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma -mpconfig -mwbnoinvd -mptwrite -mclflushopt -mclwb -mxsavec -mxsaves -msse4a -m3dnow -m3dnowa -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -madx -mlzcnt -mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mhle -mlwp -mmwaitx -mclzero -mpku -mgfni -mvaes -mwaitpkg -mshstk -mmanual-endbr -mcet-switch -mforce-indirect-call -mavx512vbmi2 -mavx512bf16 -menqcmd -mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b -mavx512vpopcntdq -mavx512vnni -mprfchw -mrdpid -mrdseed -msgx -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset -mavxvnni -mamx-fp8 -mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert -mcmpccxadd -mamx-fp16 -mprefetchi -mraoint -mamx-complex -mavxvnniint16 -msm3 -msha512 -msm4 -mapxf -musermsr -mavx10.1 -mavx10.2 -mamx-avx512 -mamx-tf32 -mmovrs -mamx-movrs -mavx512bmm -mcldemote -mms-bitfields -mno-align-stringops -minline-all-stringops -minline-stringops-dynamically -mstringop-strategy=alg -mkl -mwidekl -mmemcpy-strategy=strategy -mmemset-strategy=strategy -mpush-args -maccumulate-outgoing-args -m128bit-long-double -m96bit-long-double -mlong-double-64 -mlong-double-80 -mlong-double-128 -mregparm=num -msseregparm -mveclibabi=type -mvect8-ret-in-mem -mpc32 -mpc64 -mpc80 -mdaz-ftz -mstackrealign -mstack-arg-probe -momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs -mcmodel=code-model -mabi=name -maddress-mode=mode -m32 -m64 -mx32 -m16 -miamcu -mlarge-data-threshold=num -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv -minstrument-return=type -mrecord-return -mfentry-name=name -mfentry-section=name -mskip-rax-setup -mavx256-split-unaligned-load -mavx256-split-unaligned-store -malign-data=type -mstack-protector-guard=guard -mstack-protector-guard-reg=reg -mstack-protector-guard-offset=offset -mstack-protector-guard-symbol=symbol -mgeneral-regs-only -mcall-ms2sysv-xlogues -mtls-dialect=type -mrelax-cmpxchg-loop -mindirect-branch=choice -mfunction-return=choice -mindirect-branch-register -mharden-sls=choice -mindirect-branch-cs-prefix -mapx-inline-asm-use-gpr32 -mgather -mscatter -mneeded -mno-direct-extern-access -munroll-only-small-loops -mdispatch-scheduler -mlam=choice
๐ x86 Windows Options
See Cygwin and MinGW Options.
๐ท Xstormy16 Options
-msim
๐ Xtensa Options
-mconst16 -mforce-no-pic -mno-serialize-volatile -mtext-section-literals -mauto-litpools -mno-target-align -mlongcalls -mabi=abi-type -mextra-l32r-costs=cycles -mstrict-align
๐ง zSeries Options
See S/390 and zSeries Options.
โจ Options Controlling the Kind of Output
Okay, so compilation can have up to four stages ๐ซถ: preprocessing, compilation proper, assembly and linking, always in that order. GCC can preprocess and compile several files into several assembler input files, or into just one assembler input file. Then each assembler input file makes an object file, and linking mashes all the object files together (the ones just compiled and the ones you passed in) into one executable file ๐ฅ
The file name suffix decides what kind of compilation happens for each input file ๐
file.cโ C source code that must be preprocessed.file.iโ C source code that should not be preprocessed.file.iiโ C++ source code that should not be preprocessed.file.mโ Objective-C source code. Note that you must link with thelibobjclibrary to make an Objective-C program work.file.miโ Objective-C source code that should not be preprocessed.file.mm,file.Mโ Objective-C++ source code. Note that you must link with thelibobjclibrary to make an Objective-C++ program work. Note that.Mrefers to a literal capital M ๐file.miiโ Objective-C++ source code that should not be preprocessed.file.hโ C, C++, Objective-C or Objective-C++ header file to be turned into a precompiled header (default), or C, C++ header file to be turned into an Ada spec (via the-fdump-ada-specswitch) ๐ธ
okay bestie, this is the file-suffix cheat sheet ๐ gcc looks at the ending of each filename to decide what kind of source it's dealing with ๐
- C++ source that must be preprocessed ๐ธ:
file.cc,file.cp,file.cxx,file.cpp,file.CPP,file.c++,file.C. Heads up: in.cxx, the last two letters must both be a literal lowercasex, and.Cmeans a literal capitalC. - Objective-C++ source that must be preprocessed ๐ฆ:
file.mm,file.M. - Objective-C++ source that should not be preprocessed ๐ง:
file.mii. - C++ header file ๐, which gets turned into a precompiled header or an Ada spec:
file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tcc. - Fixed form Fortran that should not be preprocessed ๐:
file.f,file.for,file.ftn,file.fi. - Fixed form Fortran that must be preprocessed (with the traditional preprocessor) โจ:
file.F,file.FOR,file.fpp,file.FPP,file.FTN. - Free form Fortran that should not be preprocessed ๐:
file.f90,file.f95,file.f03,file.f08,file.fii. - Free form Fortran that must be preprocessed (with the traditional preprocessor) ๐:
file.F90,file.F95,file.F03,file.F08. - COBOL source code ๐พ:
file.cob,file.COB,file.cbl,file.CBL. - Go source code ๐น:
file.go. - D source code ๐ฅ:
file.d. - D interface file โญ:
file.di. - D documentation code (Ddoc) ๐:
file.dd. - Ada source code with a library unit declaration ๐ธ, meaning a declaration of a package, subprogram, or generic, or a generic instantiation, or a library unit renaming declaration (a package, generic, or subprogram renaming declaration). These files are also called specs:
file.ads. - Ada source code with a library unit body ๐ฆ, meaning a subprogram or package body. These files are also called bodies:
file.adb. - Assembler code ๐ซถ:
file.s. - Assembler code that must be preprocessed ๐
:
file.S,file.sx. - other ๐: an object file that gets fed straight into linking. Any filename with no recognized suffix is treated this way.
You can also name the input language yourself with the -x option, so gcc doesn't have to guess from the suffix ๐ง
-x language,--language=language,--language languageโจ โ explicitly sets the language for the input files that come after it, instead of letting the compiler pick a default from the filename suffix. This applies to every following input file until the next-xoption shows up. The possible values for language are:
c c-header cpp-output
c++ c++-header c++-system-header c++-user-header c++-cpp-output
c++-system-module
objective-c objective-c-header objective-c-cpp-output objc-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
objc++-cpp-output
assembler assembler-with-cpp
ada adascil adawhy
cobol
d
f77 f77-cpp-input f95 f95-cpp-input
go
modula-2 modula-2-cpp-output
rust
algol68
lto
โ ๏ธ bestie,-xdoes not pick a language standard for you ๐ For example,-x f77may also need-std=legacyfor some older source code.
-x none๐ โ turns off any language specification, so the files after it get handled by their filename suffixes, exactly like-xwas never used at all.
If you only want some stages of compilation, you can use -x (or filename suffixes) to say where gcc should start, and one of -c, -S, or -E to say where it should stop ๐ Heads up, some combos (like -x cpp-output -E) make gcc do absolutely nothing ๐ญ
-c,--compile๐ท โ compiles or assembles the source files but does not link. The linking stage just doesn't happen. The final output is an object file for each source file.
By default, the object file name for a source file is made by swapping the suffix .c, .i, .s, etc. for .o.
Unrecognized input files that don't need compiling or assembling get quietly ignored.
-S,--assemble๐ โ stops after the compilation proper and does not assemble. The output is an assembler code file for each input file that isn't already assembler code.
By default, the assembler file name for a source file is made by swapping .c, .i, etc. for .s.
Input files that don't need compiling get ignored.
-E,--preprocess๐ฎ โ stops after preprocessing and doesn't run the compiler proper. The output is preprocessed source code, sent straight to standard output.
Input files that don't need preprocessing get ignored.
-o file,--output=file,--output file๐ฏ โ puts the primary output in file. This works for whatever you're making, whether that's an executable, an object file, an assembler file, or preprocessed C.
If you don't specify -o, the defaults are: an executable goes in a.out, the object file for source.suffix goes in source.o, its assembler file goes in source.s, a precompiled header file goes in source.suffix.gch, and all the preprocessed C source goes to standard output ๐ง
Even though -o only names the primary output, it also affects how the auxiliary and dump outputs get named. Check the examples below! Unless overridden, both auxiliary and dump outputs land in the same directory as the primary output. For auxiliary outputs, the input file's suffix gets replaced with the suffix of the auxiliary output's file type. For dump outputs, the dump file's suffix gets tacked onto the input file's suffix. In compilation commands, the base name of both auxiliary and dump outputs is the primary output's base name. In compile and link commands, the primary output name (minus the executable suffix) gets combined with the input file name. If both share the same base name (ignoring the suffix), the result is just that base name. Otherwise, they get concatenated with a dash in between ๐
gcc -c foo.c ...
This will use foo.o as the primary output and put the aux outputs and dumps right next to it, for example the aux file foo.dwo for -gsplit-dwarf, and the dump file foo.c.???r.final for -fdump-rtl-final.
If a non-linker output file is explicitly specified, aux and dump files by default take the same base name:
gcc -c foo.c -o dir/foobar.o ...
This will name the aux outputs dir/foobar.* and the dump outputs dir/foobar.c.*.
A linker output does things a little differently and prefixes the aux and dump outputs instead:
gcc foo.c bar.c -o dir/foobar ...
This will generally name the aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and the dump outputs dir/foobar-foo.c.* and dir/foobar-bar.c.*.
The one exception is when the executable shares the base name with the single input:
gcc foo.c -o dir/foo ...
In that case the aux outputs are named dir/foo.* and the dump outputs are named dir/foo.c.*.
You can tweak the location and names of auxiliary and dump outputs with the options -dumpbase, -dumpbase-ext, -dumpdir, -save-temps=cwd, and -save-temps=obj ๐ ๏ธ
-dumpbase dumpbase,--dumpbase dumpbase๐ โ sets the base name for auxiliary and dump output files. It does not change the name of the primary output file. Intermediate outputs, when they get preserved, don't count as primary outputs. They count as auxiliary outputs instead:
gcc -save-temps -S foo.c
This saves the (no longer temporary) preprocessed file in foo.i, then compiles to the implied output file foo.s. Meanwhile:
gcc -save-temps -dumpbase save-foo -c foo.c
This preprocesses to save-foo.i, compiles to save-foo.s (now an intermediate, so an auxiliary output), and then assembles to the implied output file foo.o.
Without this option, dump and aux files take their names from the input file, or from the (non-linker) output file if one is explicitly specified. Dump output files, like the ones requested by -fdump-* options, keep the input name's suffix. Aux output files, like the ones requested by other non-dump options (for example -save-temps, -gsplit-dwarf, -fcallgraph-info), drop it.
You can get similar suffix differentiation between dump and aux outputs for an explicitly given -dumpbase basename.suf by also specifying -dumpbase-ext .suf ๐ฆ
If dumpbase is explicitly specified with any directory component, any dumppfx specification (like -dumpdir or -save-temps=*) gets ignored. Instead of appending to it, dumpbase fully overrides it:
gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
-dumpdir pfx- -save-temps=cwd ...
This creates auxiliary and dump outputs named alt/foo.*, ignoring the dir/ in -o, the ./ prefix implied by -save-temps=cwd, and the pfx- in -dumpdir.
When -dumpbase is specified in a command that compiles multiple inputs, or one that compiles and then links, it can be combined with dumppfx, as described under -dumpdir. Then each input file gets compiled using the combined dumppfx, and default values for dumpbase and auxdropsuf get computed for each input file:
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs. It also avoids overwriting the aux and dump outputs by using the dumpbase as a prefix, creating aux and dump outputs named main-foo.* and main-bar.*.
An empty string given as dumpbase avoids the influence of the output basename on naming aux and dump outputs during compilation, and default values get computed instead:
gcc -c foo.c -o dir/foobar.o -dumpbase " ...
This will name the aux outputs dir/foo.* and the dump outputs dir/foo.c.*. Notice how their basenames come from the input name, but the directory still defaults to the output's directory.
An empty-string dumpbase does not stop the output basename from being used for outputs during linking:
gcc foo.c bar.c -o dir/foobar -dumpbase " -flto ...
The compilation of the source files will name the aux outputs dir/foo.* and dir/bar.*, and the dump outputs dir/foo.c.* and dir/bar.c.*. LTO recompilation during linking will use dir/foobar. as the prefix for dumps and aux files ๐
-dumpbase-ext auxdropsuf,--dumpbase-ext auxdropsufโ the suffix-dropper for aux files ๐ฆ
Okay so when gcc is forming the name of an auxiliary output file (not a dump file, those are different, bestie), it drops the trailing auxdropsuf from dumpbase before it tacks on any suffixes. If you don't specify it, it defaults to the suffix of a default dumpbase. That means the suffix of the input file when -dumpbase isn't on the command line, or when dumpbase is combined with dumppfx. Literally so sneaky, but it works ๐
gcc foo.c -c -o dir/foo.o -dumpbase x-foo.c -dumpbase-ext .c ...
This one is giving main character energy ๐ It creates dir/foo.o as the main output, puts the auxiliary outputs in dir/x-foo.* (using the location of the primary output), and drops the .c suffix from the dumpbase. Dump outputs keep the suffix though, so you get dir/x-foo.c.* โจ
This option gets ignored if it doesn't match the suffix of a specified dumpbase, except as an alternative to the executable suffix when gcc is appending the linker output base name to dumppfx. Here's how that slays:
gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
This creates main.out as the primary output. It also avoids overwriting the auxiliary and dump outputs by using the executable name minus auxdropsuf as a prefix. So you get auxiliary outputs named main-foo.* and main-bar.*, and dump outputs named main-foo.c.* and main-bar.c.* ๐
-dumpdir dumppfx,--dumpdir dumppfxโ the prefix princess ๐
When gcc forms the name of an auxiliary or dump output file, it uses dumppfx as a prefix. Iconic.
gcc -dumpdir pfx- -c foo.c ...
This creates foo.o as the primary output, with auxiliary outputs named pfx-foo.*. It combines the given dumppfx with the default dumpbase, which comes from the default primary output, which in turn comes from the input name. Dump outputs also take the input name suffix, so you get pfx-foo.c.* ๐ง
If you want dumppfx to act as a directory name, it has to end with a directory separator. Don't skip this part, it's lowkey important ๐
gcc -dumpdir dir/ -c foo.c -o obj/bar.o ...
This creates obj/bar.o as the primary output, and auxiliary outputs named dir/bar.*. It combines the given dumppfx with the default dumpbase derived from the primary output name. Dump outputs take the input name suffix too: dir/bar.c.* ๐
By default, dumppfx is the location of the output file, unless the output file is a special file like "/dev/null". The options -save-temps=cwd and -save-temps=obj override this default, just like an explicit -dumpdir option does. If you give more than one of these, the last one prevails:
gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
This one outputs foo.o, with auxiliary outputs named foo.*, because -save-temps=* overrides the dumppfx from the earlier -dumpdir option. It doesn't matter that =obj is the default for -save-temps, or that the output directory is implicitly the current directory. Dump outputs are named foo.c.* ๐
When you compile from multiple input files and specify -dumpbase, the dumpbase (minus an auxdropsuf suffix) plus a dash gets appended to the dumppfx. This happens whether that dumppfx is explicit or defaulted. If the dumpbase has any directory components, it overrides the dumppfx instead of getting appended. This way every compilation gets its own differently-named aux and dump outputs, which is so organized ๐ซถ
gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
This sends auxiliary dumps to dir/pfx-main-foo.* and dir/pfx-main-bar.*, appending dumpbase- to dumppfx. Dump outputs keep the input file suffix: dir/pfx-main-foo.c.* and dir/pfx-main-bar.c.*, respectively.
Now contrast that with a single-input compilation:
gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
Applying -dumpbase to a single source doesn't compute and append a separate dumpbase per input file. Its auxiliary and dump outputs just go in dir/pfx-main.* โจ
When you compile and then link from multiple input files, a defaulted or explicitly specified dumppfx also goes through the dumpbase- transformation above. For example, that's the compilation of foo.c and bar.c from before, just without -c. If you specify neither -dumpdir nor -dumpbase, the linker output base name gets appended to the default dumppfx instead, plus a dash. That base name has the auxdropsuf removed if you specified it, or the executable suffix removed otherwise. Now, careful, because this is where it gets different:
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
This one does not append the output name main to dumppfx, because -dumpdir was explicitly specified. The idea is that an explicit dumppfx can include the output name as part of the prefix, if you want that. Only an explicitly specified -dumpbase would get combined with it, so gcc doesn't just throw away a meaningful option ๐ฆ
When you compile and then link from a single input file, the linker output base name only gets appended to the default dumppfx (like above) if it doesn't share the base name with the single input file name. This was covered in the single-input linking cases earlier, but it's different with an explicit -dumpdir that stops the combination. That's true even if -save-temps=* overrides it:
gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
Here the auxiliary outputs are foo.*, and the dump outputs are foo.c.*. They end up in the current working directory, as requested by -save-temps=cwd ๐ธ
Okay, here's the whole thing summed up in a slightly imprecise but super intuitive way. The primary output name gets split into a directory part and a basename part. The dumppfx is set to the directory part, unless -dumpdir or -save-temps=* overrides it. The dumpbase is set to the basename part, unless -dumpbase overrides it. If there are multiple inputs or you're linking, this dumpbase can combine with dumppfx and get taken from each input file. Auxiliary output names for each input are formed by combining dumppfx, dumpbase minus its suffix, and the auxiliary output suffix. Dump output names only differ because they keep the suffix from dumpbase ๐
When it comes to auxiliary and dump outputs created during LTO recompilation, here's the tea. A combination of dumppfx and dumpbase gets passed down to lto-wrapper as a -dumpdir option. This happens whether it's given or derived from the linker output name (but not from inputs), and even in cases where the combination wouldn't normally get used. The trailing period replaces the compiler-added dash, if there is one. Since this program is involved in linking, it doesn't normally get any -dumpbase or -dumpbase-ext, and it ignores them if it does ๐
When lto-wrapper runs sub-compilers, it appends the LTO stage names to the dumppfx it received. It makes sure the dumppfx contains a directory component so that it overrides any -dumpdir. Then it passes that along as -dumpbase to the sub-compilers ๐ง
-v,--verboseโ the show-your-work option ๐ฅ
This prints (on standard error output) the commands executed to run the stages of compilation. It also prints the version number of the compiler driver program, plus the version of the preprocessor and the compiler proper. Very receipts-y ๐งพ
-###โ the "what would you run" option ๐
This is like -v, except the commands are not executed. Arguments get quoted unless they only contain alphanumeric characters or "./-_". It's super useful for shell scripts that want to capture the command lines the driver generates, so they can keep track of what's going on behind the scenes โจ
--helpโ the menu, but make it cute ๐
This prints (on the standard output) a description of the command-line options that gcc understands. If you also specify -v, then --help gets passed on to the various processes gcc invokes, so each one can show you the command-line options it accepts. And if you specify -Wextra (before the --help option), command-line options that have no documentation attached are shown too. Undocumented options get to come to the party ๐
--target-helpโ the target-specific menu ๐
This prints (on the standard output) a description of the target-specific command-line options for each tool. For some targets, extra target-specific information may also be printed ๐ฆ
--help={class|[^]qualifier}[,...]โ the filtered menu, bestie ๐
This prints (on the standard output) a description of the command-line options the compiler understands that fit into all of the specified classes and qualifiers. Here are the supported classes:
optimizersโ shows every optimization option the compiler supports โญwarningsโ shows every option that controls the warning messages the compiler produces ๐ฅtargetโ shows target-specific options. Unlike--target-help, though, target-specific options of the linker and assembler are not displayed. Those tools don't currently support the extended--help=syntax, so they get left out ๐paramsโ shows the values the--paramoption recognizes ๐languageโ shows the options supported for language, where language is the name of one of the languages supported in this version of GCC. If an option is supported by all languages, you need to pick thecommonclass to see it ๐commonโ shows the options that are common to all languages ๐ซถ
Here are the supported qualifiers:
undocumentedโ only shows the options that are undocumented ๐ธjoinedโ shows options that take an argument appearing after an equal sign in the same continuous piece of text, like--help=target๐separateโ shows options that take an argument appearing as a separate word after the original option, like-o output-file๐ง
So if you want every undocumented target-specific switch the compiler supports, you'd type:
--help=target,undocumented
You can invert the sense of a qualifier by putting the ^ character in front of it. For example, to display all binary warning options (the ones that are either on or off and don't take an argument) that have a description, use:
--help=warnings,^joined,^undocumented
The argument to --help= should not consist solely of inverted qualifiers. Don't be that person ๐
โโ๏ธ
Combining several classes is possible, but it usually restricts the output so much that there's nothing to display. There's one case where it totally works, though: when one of the classes is target. For example, to display all the target-specific optimization options, use:
--help=target,optimizers
The --help= option can be repeated on the command line. Each successive use displays its requested class of options, skipping any that were already displayed. If --help is also specified anywhere on the command line, it takes precedence over any --help= option (the main character always wins) ๐
If you slip -Q in before --help= on the command line, the text --help= spits out gets a total glow-up โจ. Instead of describing the options, it tells you whether each one is enabled, disabled, or set to a specific value ๐. This only works if the compiler actually knows that value at the point where --help= shows up ๐ซถ.
Here's a truncated example from the ARM port of gcc ๐ฆ:
% gcc -Q -mabi=2 --help=target -c
The following options are target specific:
-mabi= 2
-mabort-on-noreturn [disabled]
-mapcs [disabled]
The output reacts to whatever command-line options came before it, so you can totally find out which optimizations are on at -O2 with:
-Q -O2 --help=optimizers
Or if you want the receipts ๐งพ, you can figure out which binary optimizations are enabled by -O3 by running:
gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
diff /tmp/O2-opts /tmp/O3-opts | grep enabled
--versionโ Shows the version number and copyrights of the GCC you invoked ๐ธ.-pass-exit-codes,--pass-exit-codesโ Okay, so normallygccexits with the code of 1 if any phase of the compiler returns a non-success return code ๐ฌ. With this flag, it instead returns the numerically highest error from any phase that reported an error ๐. The C, C++, and Fortran front ends return 4 if they hit an internal compiler error ๐.-pipe,--pipeโ Uses pipes instead of temporary files to pass stuff between the different stages of compilation ๐ง.
This one is a little risky bestie ๐. It fails to work on some systems where the assembler can't read from a pipe. The GNU assembler has no trouble though โจ.
-wrapperโ Invokes all subcommands under a wrapper program ๐. You pass the wrapper's name and its parameters as a comma separated list ๐ .
gcc -c t.c -wrapper gdb,--args
This runs all the subprograms of gcc under gdb --args, so the invocation of cc1 becomes gdb --args cc1 .... ๐.
-ffile-prefix-map=old=newโ When you compile files living in the directoryold, any references to them in the compilation result get recorded as if those files lived innewinstead ๐ฆ. Specifying this is the same as specifying all the individual-f*-prefix-mapoptions ๐. It's a great way to make reproducible builds that don't care about location ๐. Directories referenced by directives are not affected by these options. See also-fmacro-prefix-map,-fdebug-prefix-map,-fprofile-prefix-mapand-fcanon-prefix-map๐.-fcanon-prefix-mapโ Normally, for the-f*-prefix-mapoptions, the old prefix gets compared against the filename that would be referenced in the result using textual comparison of the prefixes ๐. That comparison ignores character case on case insensitive filesystems, and treats slashes and backslashes as equal on DOS based filesystems ๐ซ .-fcanon-prefix-mapmakes those comparisons happen on canonicalized paths ofoldand the referenced filename โจ.-fplugin=name.soโ Loads the plugin code in the filename.so, which is assumed to be a shared object that the compiler willdlopen'd ๐. The base name of the shared object file is used to identify the plugin when parsing arguments (see-fplugin-arg-name-key=valuebelow) ๐ง . Each plugin should define the callback functions specified in the Plugins API ๐ .-fplugin-arg-name-key=valueโ Defines an argument calledkeywith a value ofvaluefor the plugin calledname๐.-fdump-ada-spec[-slim]โ For C and C++ source and include files, generates the matching Ada specs ๐ธ.-fada-spec-parent=unitโ Works together with-fdump-ada-spec[-slim]above, and generates Ada specs as child units of the parentunit๐.-fdump-go-spec=fileโ For input files in any language, generates matching Go declarations infile๐น. This makes "const", "type", "var", and "func" declarations, which can be a super useful way to start writing a Go interface to code written in some other language ๐ซถ.@fileโ Reads command-line options fromfile๐. The options read get inserted in place of the original@fileoption ๐ฆ.- If
filedoes not exist, or can't be read, then the option is treated literally and does not get removed ๐. - Options in
fileare separated by whitespace ๐. A whitespace character can be included in an option by surrounding the entire option in either single or double quotes ๐. - Any character (including a backslash) can be included by prefixing the character to be included with a backslash ๐.
- The file may itself contain additional
@fileoptions, and any such options get processed recursively ๐.
- If
โจ Compiling C++ Programs โจ
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx ๐
. C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc ๐. Preprocessed C++ files use the suffix .ii ๐ง, and C++20 module interface units sometimes use .ixx, .cppm, .cxxm, .c++m, or .ccm ๐ธ.
GCC recognizes files with these names and compiles them as C++ programs, even if you call the compiler the same way you would for C programs (usually with the name gcc) ๐.
However, using gcc does not add the C++ library ๐ญ. That's where g++ comes in ๐. It's a program that calls GCC and automatically specifies linking against the C++ library ๐. It treats .c, .h and .i files as C++ source files instead of C source files, unless -x is used ๐. This program is also useful when precompiling a C header file with a .h extension for use in C++ compilations ๐ฆ. On many systems, g++ is also installed with the name c++ ๐ซถ.
When you compile C++ programs, you can specify many of the same command-line options you'd use for compiling programs in any language ๐. You can also use command-line options meaningful for C and related languages, or options that are meaningful only for C++ programs ๐.
๐ Options Controlling C Dialect ๐
The following options control the dialect of C (or languages derived from C, such as C++, Objective-C and Objective-C++) that the compiler accepts ๐:
-ansi,--ansiโ In C mode, this is the same as-std=c90. In C++ mode, it's the same as-std=c++98๐ธ.-std=โ Determines the language standard ๐. This option is currently only supported when compiling C or C++ ๐ซถ.
The compiler can accept several base standards, like c90 or c++98, plus GNU dialects of those standards, like gnu90 or gnu++98 โจ. When you specify a base standard, the compiler accepts all programs following that standard, plus those using GNU extensions that don't contradict it ๐. For example, -std=c90 turns off certain GCC features that are incompatible with ISO C90, like the "asm" and "typeof" keywords ๐. It does not turn off other GNU extensions that have no meaning in ISO C90, like omitting the middle term of a "?:" expression ๐ฆ.
On the other hand, when you specify a GNU dialect of a standard, every feature the compiler supports gets enabled, even when those features change the meaning of the base standard ๐. As a result, some strict-conforming programs may get rejected ๐. The particular standard is used by -Wpedantic to figure out which features are GNU extensions for that version of the standard ๐ง . For example, -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic does not ๐.
A value for this option must be provided. Possible values are:
c90,c89,iso9899:1990โ Supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code ๐ .iso9899:199409โ ISO C90 as modified in amendment 1 ๐.c99,c9x,iso9899:1999,iso9899:199xโ ISO C99 ๐ธ. This standard is substantially completely supported, modulo bugs and floating-point issues (mainly, but not entirely, relating to optional C99 features from Annexes F and G). See<https://gcc.gnu.org/projects/c-status.html>for more information ๐. The namesc9xandiso9899:199xare deprecated ๐ฌ.c11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard โจ. This standard is substantially completely supported, modulo bugs, floating-point issues (mainly, but not entirely, relating to optional C11 features from Annexes F and G), and the optional Annexes K (Bounds-checking interfaces) and L (Analyzability) ๐ง . The namec1xis deprecated ๐.c17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision of the ISO C standard (published in 2018) ๐. This standard is the same as C11 except for corrections of defects (all of which are also applied with-std=c11) and a new value of"__STDC_VERSION__", so it's supported to the same extent as C11 ๐ซถ.c23,c2x,iso9899:2024โ ISO C23, the 2023 revision of the ISO C standard (published in 2024) ๐. The namec2xis deprecated ๐.c2yโ The next version of the ISO C standard, still under development ๐ง. The support for this version is experimental and incomplete ๐งช.gnu90,gnu89โ GNU dialect of ISO C90 (including some C99 features) ๐ฆ.gnu99,gnu9xโ GNU dialect of ISO C99 ๐. The namegnu9xis deprecated ๐ฌ.gnu11,gnu1xโ GNU dialect of ISO C11 ๐ธ. The namegnu1xis deprecated ๐ฌ.gnu17,gnu18โ GNU dialect of ISO C17 โจ.gnu23,gnu2xโ GNU dialect of ISO C23 ๐. This is the default for C code ๐. The namegnu2xis deprecated ๐.gnu2yโ The next version of the ISO C standard, still under development, plus GNU extensions ๐ง. The support for this version is experimental and incomplete ๐งช. The namegnu2xis deprecated ๐ฌ.c++98,c++03โ The 1998 ISO C++ standard, plus the 2003 technical corrigendum and some additional defect reports ๐. Same as-ansifor C++ code ๐ .gnu++98,gnu++03โ GNU dialect of-std=c++98๐.c++11,c++0xโ The 2011 ISO C++ standard plus amendments ๐ธ. The namec++0xis deprecated ๐ฌ.gnu++11,gnu++0xโ GNU dialect of-std=c++11๐ฆ. The namegnu++0xis deprecated ๐.
Okay, the -std list keeps going, and bestie, these are the ones that get a little spicy ๐ถ๏ธ
c++14,c++1yโ โจ The 2014 ISO C++ standard plus amendments. The namec++1yis deprecated ๐ฅgnu++14,gnu++1yโ ๐ GNU dialect of-std=c++14. The namegnu++1yis deprecated.c++17,c++1zโ ๐ The 2017 ISO C++ standard plus amendments. The namec++1zis deprecated.gnu++17,gnu++1zโ ๐ฆ GNU dialect of-std=c++17. The namegnu++1zis deprecated.c++20,c++2aโ ๐ The 2020 ISO C++ standard plus amendments. C++20 modules support is still experimental and needs to be enabled with-fmodulesoption. The namec++2ais deprecated.gnu++20,gnu++2aโ ๐ฅ GNU dialect of-std=c++20. This is the default for C++ code. C++20 modules support is still experimental and needs to be enabled with-fmodulesoption. The namegnu++2ais deprecated.c++23,c++2bโ ๐งช The 2023 ISO C++ standard plus amendments (published in 2024). Support is experimental, and could change in incompatible ways in future releases. The namec++2bis deprecated.gnu++23,gnu++2bโ ๐งช GNU dialect of-std=c++23. Support is experimental, and could change in incompatible ways in future releases. The namegnu++2bis deprecated.c++2c,c++26โ ๐ฎ The next revision of the ISO C++ standard, planned for 2026. Support is highly experimental, and will almost certainly change in incompatible ways in future releases.gnu++2c,gnu++26โ ๐ฎ GNU dialect of-std=c++2c. Support is highly experimental, and will almost certainly change in incompatible ways in future releases.-aux-info filenameโ ๐ Dumps prototyped declarations for every function declared and/or defined in a translation unit, header files included, into the file you name. It's silently ignored in any language other than C.
Besides the declarations, the file leaves comments that tell you where each one came from (source file and line). The character right after the line number and colon tells you whether the declaration was implicit, prototyped or unprototyped: I for implicit, N for new or O for old. The character after that tells you whether it came from a declaration or a definition: C for declaration or F for definition. For function definitions, you also get a K&R-style list of arguments, followed by their declarations, all inside comments and placed after the declaration. ๐ซถ
-fno-asmโ ๐ โโ๏ธ Stopsasm,inlineandtypeoffrom being treated as keywords, so you can use those words as identifiers. You can use__asm__,__inline__and__typeof__instead. In C,-ansiimplies-fno-asm.
In C++, inline is a standard keyword and this switch doesn't touch it. You might want -fno-gnu-keywords instead, which turns off typeof but leaves asm and inline alone. In C99 mode (-std=c99 or -std=gnu99), this switch only affects asm and typeof, since inline is a standard keyword in ISO C99. In C23 mode (-std=c23 or -std=gnu23), this switch only affects asm, since typeof is a standard keyword in ISO C23. ๐
-fno-builtin,-fno-builtin-functionโ ๐ซ Don't recognize built-in functions that do not begin with__builtin_as prefix.
Normally GCC generates special code for certain built-in functions so they run more efficiently. For instance, calls to alloca can turn into single instructions that adjust the stack directly, and calls to memcpy can become inline copy loops. The result is often both smaller and faster, but the function calls don't show up as calls anymore. That means you can't set a breakpoint on them, and you can't change what the functions do by linking against a different library. ๐ Also, once a function is recognized as built-in, GCC may use what it knows about that function to warn you about problems with calls to it, or to generate more efficient code, even if the result still contains calls to that function. For example, you get warnings with -Wformat for bad calls to printf when printf is built in and strlen is known not to modify global memory.
With -fno-builtin-function, only the built-in function is disabled. function must not begin with __builtin_. If you name a function that isn't built-in in this version of GCC, this option is ignored. There is no corresponding -fbuiltin-function option. If you want to enable built-in functions selectively when using -fno-builtin or -ffreestanding, you can define macros like these:
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fcond-mismatchโ ๐คทโโ๏ธ Allows conditional expressions with mismatched types in the second and third arguments. The value of such an expression is void. This option is not supported for C++.-ffreestandingโ ๐ธ Asserts that compilation targets a freestanding environment. This implies-fno-builtin. A freestanding environment is one where the standard library may not exist, and program startup may not necessarily be atmain. The most obvious example is an OS kernel. This is equivalent to-fno-hosted.-fgimpleโ ๐ง Enables parsing of function definitions marked with__GIMPLE. It's an experimental feature that allows unit testing of GIMPLE passes.-fgnu-tmโ ๐งต When-fgnu-tmis specified, the compiler generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009). This is an experimental feature whose interface may change in future versions of GCC, as the official specification changes. Heads up: not all architectures are supported for this feature.
For more information on GCC's support for transactional memory,
โ ๏ธ The transactional memory feature is not supported with non-call exceptions (-fnon-call-exceptions).
-fgnu89-inlineโ ๐ฐ๏ธ Tells GCC to use the traditional GNU semantics forinlinefunctions when in C99 mode.
Using this option is roughly equivalent to adding the gnu_inline function attribute to all inline functions.
The option -fno-gnu89-inline explicitly tells GCC to use the C99 semantics for inline when in C99 or gnu99 mode (aka the default behavior). This option is not supported in -std=c90 or -std=gnu90 mode.
The preprocessor macros __GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__ can be used to check which semantics are in effect for inline functions. ๐
-fhostedโ ๐ Asserts that compilation targets a hosted environment. This implies-fbuiltin. A hosted environment is one where the entire standard library is available, and wheremainhas a return type ofint. Examples are nearly everything except a kernel. This is equivalent to-fno-freestanding.-flax-vector-conversionsโ ๐ซ Allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types. This option should not be used for new code. โ-fms-extensionsโ ๐ช Accepts some non-standard constructs used in Microsoft header files.
In C++ code, this lets member names in structures be similar to previous type declarations:
typedef int UOW;
struct ABC {
UOW UOW;
};
Some cases of unnamed fields in structures and unions are only accepted with this option.
Note that this option is off for all targets except for x86 targets using ms-abi.
-fpermitted-flt-eval-methods=styleโ ๐ฏ ISO/IEC TS 18661-3 defines new permissible values forFLT_EVAL_METHODthat indicate that operations and constants with a semantic type that is an interchange or extended format should be evaluated to the precision and range of that type. These new values are a superset of those permitted under C99/C11, which doesn't specify the meaning of other positive values ofFLT_EVAL_METHOD. So code that conforms to C11 may not have been written expecting the possibility of the new values.
-fpermitted-flt-eval-methods decides whether the compiler should allow only the values of FLT_EVAL_METHOD specified in C99/C11, or the extended set of values specified in ISO/IEC TS 18661-3.
style is either c11 or ts-18661-3, as appropriate.
The default in a standards compliant mode (-std=c11 or similar) is -fpermitted-flt-eval-methods=c11. The default in a GNU dialect (-std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3.
The -fdeps-* options are used to extract structured dependency information for a source. This involves figuring out what resources provided by other source files will be required to compile the source, as well as what resources the source itself provides. This information can be used to add required dependencies between compilation rules of dependent sources based on their contents, rather than requiring that such information be reflected within the build tools as well. ๐งฉ
-fdeps-file=fileโ ๐ Where to write structured dependency information.-fdeps-format=formatโ ๐ The format to use for structured dependency information.p1689r5is the only supported format right now. Note that when this argument is specified, the output of-MFis stripped of some information (namely C++ modules) so that it doesn't use extended makefile syntax that most tools don't understand.-fdeps-target=fileโ ๐ฏ Analogous to-MTbut for structured dependency information. This indicates the target that will ultimately need any required resources and provide any resources extracted from the source that may be required by other sources.-fplan9-extensionsโ ๐น Accepts some non-standard constructs used in Plan 9 code.
This enables -fms-extensions, permits passing pointers to structures with anonymous fields to functions that expect pointers to elements of the type of the field, and permits referring to anonymous fields declared using a typedef. This is only supported for C, not C++. ๐
-fsigned-bitfields,-funsigned-bitfields,-fno-signed-bitfields,-fno-unsigned-bitfieldsโ okay so these decide if a bit-field is signed or unsigned, but only when your declaration doesn't already saysignedorunsigned๐. By default a bit-field is signed, and honestly that's the consistent move because basic integer types likeintare signed too โจ.-fsigned-charโ letcharbe signed, just likesigned char๐. This is the same thing as-fno-unsigned-char, which is the negative form of-funsigned-char. And-fno-signed-charis the same as-funsigned-char๐ซถ.-funsigned-charโ flip it and letcharbe unsigned, likeunsigned char๐ฆ. Every machine has its own default for whatcharshould be: either likeunsigned charor likesigned char๐.- Ideally a portable program always uses
signed charorunsigned charwhenever it depends on the signedness of an object ๐ . - But a ton of programs were written with plain
charand expect it to be signed, or expect it to be unsigned, depending on the machines they were written for ๐ญ. This option, and its inverse, lets you make those programs work with the opposite default ๐. charis always a distinct type from each ofsigned charorunsigned char, even though it behaves exactly like one of those two ๐ง.
- Ideally a portable program always uses
-fstrict-flex-arrays(C and C++ only),-fstrict-flex-arrays=level(C and C++ only) โ this controls when the trailing array of a structure counts as a flexible array member when you're accessing its elements ๐ธ. The value oflevelsets how strict it is ๐.-fstrict-flex-arraysis the same as-fstrict-flex-arrays=3, which is the strictest ๐ฅ. A trailing array only counts as flexible when it's declared as a flexible array member per C99 and onwards ๐.- The negative form
-fno-strict-flex-arraysis the same as-fstrict-flex-arrays=0, which is the least strict ๐. In this case, all trailing arrays of structures are treated as flexible array members ๐. - Levels 1 and 2 live in between 0 and 3. They exist to support older code that uses the GCC zero-length array extension (
[0]) or one-element arrays ([1]) as flexible array members ๐. At level 1, the trailing array counts as flexible when it's declared as either[],[0], or[1]โญ. At level 2, it counts when it's declared as either[]or[0]๐ฆ. - You can control this for one specific trailing array field of a structure with the variable attribute "strict_flex_array" attribute ๐ .
- The
-fstrict_flex_arraysoption interacts with the-Wstrict-flex-arraysoption ๐ซถ.
-fsso-struct=endiannessโ sets the default scalar storage order of structures and unions to the endianness you choose ๐. The accepted values arebig-endian,little-endian, andnative, which is the native endianness of the target and the default ๐. This option is not supported for C++ ๐.
Warning: the -fsso-struct switch makes GCC generate code that is not binary compatible with code generated without it if the endianness you specified isn't the native endianness of the target ๐ญ๐จ.
โจ Options Controlling C++ Dialect โจ
This section is all about the command-line options that only matter for C++ programs ๐. Good news: you can use most of the GNU compiler options no matter what language your program is in ๐ธ. For example, you could compile a file firstClass.C like this ๐ง:
g++ -g -fstrict-enums -O -c firstClass.C
In this example, only -fstrict-enums is meant only for C++ programs ๐. You can use the other options with any language GCC supports ๐ซถ.
Some options for compiling C programs, like -std, are also relevant for C++ programs โญ.
Here's a list of options that are only for compiling C++ programs ๐:
--compile-std-moduleโ this one builds the compiled module interfaces for the<bits/stdc++.h>header unit and thestdandstd.compatmodules before compiling any source files you explicitly pass on the command line ๐ฆ. It's meant for building simple programs that useimport std;with a single command ๐ .-fabi-version=nโ use versionnof the C++ ABI ๐. The default is version 0 โจ.- Version 0 refers to the version that conforms most closely to the C++ ABI specification ๐ฅ. So the ABI you get with version 0 will change across G++ versions as ABI bugs get fixed ๐ญ.
- Version 1 is the version of the C++ ABI that first showed up in G++ 3.2 ๐ธ.
- Version 2 is the version that first showed up in G++ 3.4, and it was the default all the way through G++ 4.9 ๐.
- Version 3 fixes an error in mangling a constant address used as a template argument ๐.
- Version 4, first seen in G++ 4.5, implements a standard mangling for vector types ๐ง.
- Version 5, first seen in G++ 4.6, fixes the mangling of attribute
const/volatileon function pointer types,decltypeof a plain decl, and use of a function parameter in the declaration of another parameter ๐ . - Version 6, first seen in G++ 4.7, fixes the promotion behavior of C++11 scoped enums and the mangling of template argument packs,
const/static_cast, prefix++and--, and a class scope function used as a template argument ๐. - Version 7, first seen in G++ 4.8, treats
nullptr_tas a builtin type and fixes the mangling of lambdas in default argument scope ๐. - Version 8, first seen in G++ 4.9, fixes the substitution behavior of function types with function-cv-qualifiers ๐ซถ.
- Version 9, first seen in G++ 5.2, fixes the alignment of
nullptr_tโญ. - Version 10, first seen in G++ 6.1, adds mangling of attributes that affect type identity, like ia32 calling convention attributes (e.g.
stdcall) ๐ฆ. - Version 11, first seen in G++ 7, fixes the mangling of
sizeof...expressions and operator names ๐ฅ. For multiple entities with the same name within a function, declared in different scopes, the mangling now changes starting with the twelfth occurrence ๐ญ. It also implies-fnew-inheriting-ctors๐ธ. - Version 12, first seen in G++ 8, fixes the calling conventions for empty classes on the x86_64 target and for classes with only deleted copy/move constructors ๐. It accidentally changes the calling convention for classes with a deleted copy constructor and a trivial move constructor ๐.
- Version 13, first seen in G++ 8.2, fixes that accidental change from version 12 ๐.
- Version 14, first seen in G++ 10, fixes the mangling of the
nullptrexpression ๐ง. - Version 15, first seen in G++ 10.3, fixes the G++ 10 ABI tag regression ๐ .
- Version 16, first seen in G++ 11, changes the mangling of
__alignof__so it's distinct fromalignof, plus dependent operator names ๐. - Version 17, first seen in G++ 12, fixes the layout of classes that inherit from aggregate classes with default member initializers in C++14 and up ๐.
- Version 18, first seen in G++ 13, fixes manglings of lambdas that have additional context โจ.
- Version 19, first seen in G++ 14, fixes manglings of structured bindings to include ABI tags, handles cv-qualified
[[no_unique_address]]members, and adds mangling of C++20 constraints on function templates ๐ฅ. - Version 20, first seen in G++ 15, fixes manglings of lambdas in static data member initializers ๐ธ.
- Version 21, first seen in G++ 16, fixes unnecessary captures in
noexceptlambdas (c++/119764), the layout of a base class with all explicitly defaulted constructors (c++/120012), and the mangling of class and array objects with implicitly zero-initialized non-trailing subobjects (c++/121231) ๐. - See also
-Wabi๐ซถ.
-fabi-compat-version=nโ on targets that support strong aliases, G++ works around mangling changes by creating an alias with the correct mangled name whenever it defines a symbol with an incorrect mangled name ๐ฆ. This switch picks which ABI version to use for that alias ๐.- With
-fabi-version=0(the default), this defaults to 13 (GCC 8.2 compatibility) ๐ง. If another ABI version is explicitly selected, it defaults to 0 ๐ . - For compatibility with GCC versions 3.2 through 4.9, use
-fabi-compat-version=2๐. - If this option isn't provided but
-Wabi=nis, that version is used for compatibility aliases ๐. If this option is provided along with-Wabi(without the version), the version from this option is used for the warning โจ.
- With
-fno-access-controlโ turns off all access checking ๐ฅ. This switch is mainly useful for working around bugs in the access control code ๐.-faligned-new,-faligned-new=alignmentโ enables support for C++17newof types that need more alignment thanvoid* ::operator new(std::size_t)provides ๐ธ. A numeric argument like-faligned-new=32can specify how much alignment (in bytes) that function provides ๐. But honestly, few users will need to override the default ofalignof(std::max_align_t)๐ซถ.- This flag is enabled by default for
-std=c++17โญ.
- This flag is enabled by default for
โจ OPTIONS โจ (continued)
-fno-assume-sane-operators-newโ okay so, the C++ standard lets you swap out the globalnew,new[],delete, anddelete[]operators ๐ง, but ngl most programs don't bother and just use the built-in ones. The standard also lets the compiler skip those calls when they come fromnewordeleteexpressions (and by extension the same is assumed if__builtin_operator_newor__builtin_operator_deletefunctions are used). This option gives you control over some optimizations around calls to those operators. With-fassume-sane-operators-new-delete, GCC may assume that calls to the replaceable global operators from new or delete expressions, or from__builtin_operator_newor__builtin_operator_deletecalls, don't read or modify any global variables or variables whose address could escape to the operators (global state; except forerrnofor thenewandnew[]operators). This lets most optimizations happen across those calls, and it's something the implementation-provided operators satisfy unlessmallocimplementation details are observable in the code ormallochooks are used. It might not be satisfied if a program replaces those operators. This behavior is enabled by default ๐. With-fno-assume-sane-operators-new-delete, GCC must assume all these calls (whether from new or delete expressions or called directly) may read and write global state unless proven otherwise (e.g. when GCC compiles their implementation). Use this option if those operators are or may be replaced and your code needs to expect that behavior ๐ซถ.-fchar8_t,-fno-char8_tโ ooh, this one's giving C++20 realness ๐ธ. It enables support forchar8_t, including a brand newchar8_tfundamental type, changes to the types of UTF-8 string and character literals, new signatures for user-defined literals, associated standard library updates, and the new__cpp_char8_tand__cpp_lib_char8_tfeature test macros.
This option also lets you overload functions for ordinary strings and UTF-8 strings:
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
It also introduces new signatures for user-defined literals:
int operator""_udl1(char8_t);
int v3 = u8'x'_udl1;
int operator""_udl2(const char8_t*, std::size_t);
int v4 = u8"text"_udl2;
template<typename T, T...> int operator""_udl3();
int v5 = u8"text"_udl3;
โ ๏ธ bestie, heads up: the change to the types of UTF-8 string and character literals breaks things that were fine under ISO C++11 and later. The code below is well-formed under ISO C++11, but it's ill-formed when -fchar8_t is specified ๐ญ.
const char *cp = u8"xx";// error: invalid conversion from
// `const char8_t*' to `const char*'
int f(const char*);
auto v = f(u8"xx"); // error: invalid conversion from
// `const char8_t*' to `const char*'
std::string s{u8"xx"}; // error: no matching function for call to
// `std::basic_string<char>::basic_string()'
using namespace std::literals;
s = u8"xx"s; // error: conversion from
// `basic_string<char8_t>' to non-scalar
// type `basic_string<char>' requested
-fcheck-newโ the vibe here is double-checking ๐. It makes sure the pointer returned byoperator newis non-null before you try to modify the storage allocated. This check is normally unnecessary, because the C++ standard saysoperator newonly returns 0 if it is declaredthrow(). In that case the compiler always checks the return value, even without this option. In all other cases, whenoperator newhas a non-empty exception specification, memory exhaustion is signalled by throwingstd::bad_alloc. See alsonew (nothrow)โจ.-fconceptsโ concepts, the main character energy of templates ๐. This enables support for the C++ Concepts feature for constraining template arguments. With-std=c++20and above, Concepts are part of the language standard, so-fconceptsdefaults to on.
Some constructs that were allowed by the earlier C++ Extensions for Concepts Technical Specification, ISO 19217 (2015), but never made it into the standard, could additionally be enabled by -fconcepts-ts. The option -fconcepts-ts was deprecated in GCC 14 and removed in GCC 15 ๐. Users are expected to convert their code to C++20 concepts.
-fconcepts-diagnostics-depth=nโ this controls how deep the error replay goes when GCC recursively diagnoses a constraint satisfaction failure ๐ฆ. You set the maximum error replay depth withn. The default is1.-fconstexpr-depth=nโ this sets the maximum nested evaluation depth for C++11constexprfunctions ton. A limit is needed to detect endless recursion during constant expression evaluation. The minimum specified by the standard is512๐.-fconstexpr-cache-depth=nโ this sets the maximum level of nested evaluation depth for C++11constexprfunctions that will be cached ton. It's a heuristic that trades off compilation speed (when the cache avoids repeated calculations) against memory consumption (when the cache grows very large from highly recursive evaluations). The default is8. Very few users are likely to want to adjust it, but if your code does heavyconstexprcalculations, you might want to experiment to find which value works best for you ๐ง .-fconstexpr-fp-exceptโ Annex F of the C standard says IEC559 floating point exceptions hit at compile time should not stop compilation. C++ compilers have historically not followed this guidance and instead treat floating point division by zero as non-constant, even though it has a well-defined value. This flag tells the compiler to give Annex F priority over other rules saying a particular operation is undefined ๐ฅ.
constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
-fconstexpr-loop-limit=nโ this sets the maximum number of iterations for a loop in C++14constexprfunctions ton. A limit is needed to catch infinite loops during constant expression evaluation. The default is262144(1<<18) ๐.-fconstexpr-ops-limit=nโ this caps the maximum number of operations during a singleconstexprevaluation. Even when the number of iterations of a single loop is limited by the loop limit above, you can still get trouble. If there are several nested loops, each with lots of iterations that are still smaller than that limit, or if too many expressions need to be evaluated in the body of some loop (or even outside of a loop), theconstexprevaluation might take way too long ๐ฉ. The default is33554432(1<<25).-fcontractsโ enables support for the C++ Contracts feature, as specified in the C++26 working draft (N5003) ๐. On violation of an enforced or observed contract (see-fcontract-evaluation-semanticbelow), a violation handler gets called. The standard library provides a default handler that emits information about the contract that failed.
You can replace the default violation handler by defining:
void
handle_contract_violation (const std::contracts::contract_violation&);
-fcontract-evaluation-semantic=semanticโ sets the semantic that contracts get evaluated with tosemantic. The available evaluation modes are:"ignored"โ the contract checks get elided, with no checking added at either compile time or runtime ๐."observed"โ the contract checks are performed at runtime. If one fails, a handler is called that lets you do things like logging or emitting runtime warnings. When the handler returns, execution of the code continues. At compile time, the checks are performed forconstexprevaluations, and in that case a diagnostic is emitted if the check fails."enforce"โ the contract checks are performed and the handler is called if one fails. When the handler returns, execution of the code is terminated so it can't keep going past the failed case ๐. At compile time, the checks are applied toconstexpr, and if one fails, the program is ill-formed and an error is emitted."quick_enforce"โ the contract checks are performed at runtime and, if one fails, execution is terminated immediately, without calling any handler โก. At compile time there's no difference between this and the"enforce"case, since no handler is invoked at compile time.
-fcontracts-conservative-ipaโ this stops inter-procedural analysis from taking action when the body of an inline function is visible in a given translation unit. It allows for the case where contract evaluation conditions are permitted to differ between translation units, which means those actions could be potentially incorrect ๐ซ .-fcontract-checks-outlinedโ by default, the contract checks forpreandpostconditions are expanded in-line into function bodies. This option makes a small function instead (containing the checks), which then gets called at the relevant position. That lets different criteria apply to the compilation of the checks and to the rest of the function body ๐ .-fcontract-disable-optimized-checksโ whenpreandpostcondition checks are outlined (using-fcontract-checks-outlined), this option disables the optimization steps for those functions that can otherwise avoid unwanted elision of checking steps ๐ โโ๏ธ.-fcontracts-client-check=modeโ this option enables insertion of checks at call sites, which is called caller-side checking ๐. The value ofmodedecides which contract checks get made:"none"โ no caller or client side checking (this is the default)."pre"โ preconditions are checked at the caller or client side."all"โ both pre- and post-conditions are checked at the caller or client side.
-fcontracts-definition-check=modeโ this option lets you disable callee or definition-side checks, which are otherwise enabled by default whenever the contracts feature is active ๐ธ. The variablemodehas the values"on"and"off".
Okay bestie, this batch is where the C++ stuff gets spicy ๐ถ๏ธ Let's go ๐ง
-fcoroutinesโ turns on support for the C++ coroutines extension โจ. With-std=c++20and above, coroutines are literally part of the language standard, so-fcoroutinesdefaults to on ๐.-fdiagnostics-all-candidatesโ lets the C++ front end list every candidate during an overload resolution failure ๐. That includes the times when a deleted function is the one that got picked ๐.-fdump-lang-,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ this is the C++ debug dump squad ๐ฆ. It controls how C++-specific info gets dumped. The options and filename parts work the same way as in-fdump-tree. These switch values are the vibes you can pick:allโ turns on everything listed below ๐.classโ dumps the class hierarchy info ๐ธ. Virtual table info gets dumped too, unlessslimis specified.moduleโ dumps module info ๐งฉ. The optionslineno(locations),graph(reachability),blocks(clusters),uid(serialization),alias(mergeable),asmname(Elrond),eh(mapper) &vops(macros) can add extra details.rawโ dumps the raw internal tree data ๐.tinstโ dumps the sequence of template instantiations, indented so you can see how deep the recursion goes ๐ช. Thelinenooption adds the source location where the instantiation got triggered. Thedetailsoption also dumps the pre-instantiation substitutions, like the ones done during template argument deduction.
Lines in the .tinst dump start with I for an instantiation, S for another substitution, and R[IS] for the reopened context of a deferred instantiation ๐.
-fno-elide-constructorsโ the C++ standard lets the compiler skip making a temporary that only exists to initialize another object of the same type ๐. This flag turns that optimization OFF and makes G++ call the copy constructor every single time ๐ค. It also makes G++ call trivial member functions that would otherwise get expanded inline.
In C++17, the compiler is required to skip those temporaries, but this flag still affects trivial member functions ๐ .
-fno-enforce-eh-specsโ skips generating the run-time code that checks for exception specification violations ๐ โโ๏ธ. Heads up, this breaks the C++ standard ๐จ. It can still be handy for shrinking code size in production builds, kinda like definingNDEBUGโจ. It does NOT give your code permission to throw exceptions that break the exception specs ๐. The compiler still optimizes based on those specs, so if an unexpected exception gets thrown, you get undefined behavior at run time ๐.-fextern-tls-init,-fno-extern-tls-initโ okay this one is a lot ๐ซถ. The C++11 and OpenMP standards letthread_localandthreadprivatevariables have dynamic (run-time) initialization. To make that work, every use of one of these variables goes through a wrapper function that does any needed initialization. When the use and the definition live in the same translation unit, the compiler can optimize that overhead away ๐ช. But when the use is in a different translation unit, there's a big overhead even if the variable doesn't actually need dynamic initialization ๐ญ.
If you're sure that no use in a non-defining TU needs to trigger dynamic initialization (because the variable is statically initialized, or because a use in the defining TU runs before any uses in another TU), you can skip the overhead with -fno-extern-tls-init ๐ฆ.
On targets that support symbol aliases, the default is -fextern-tls-init. On targets that don't support symbol aliases, the default is -fno-extern-tls-init ๐.
-ffold-simple-inlines,-fno-fold-simple-inlinesโ lets the C++ front end fold calls tostd::move,std::forward,std::addressof,std::to_underlyingandstd::as_const๐งโโ๏ธ. Unlike inlining, folding means no debug info gets generated for those calls. Since nobody really needs to debug these, this flag is on by default unless-fno-inlineis active ๐ .-fno-gnu-keywordsโ stopstypeoffrom being treated as a keyword, so you can use the word as a regular identifier ๐. You can use__typeof__as the keyword instead โจ. This is implied by the strict ISO C++ dialects:-ansi,-std=c++98,-std=c++11, etc.-fno-immediate-escalationโ skips immediate function escalation, which is when certain functions get promoted toconsteval๐ช. This is specified in P2564R3. Check out this example:
consteval int id(int i) { return i; }
constexpr int f(auto t)
{
return t + id(t); // id causes f<int> to be promoted to consteval
}
void g(int i)
{
f (3);
}
This compiles in C++20 ๐. f is an immediate-escalating function (because of the auto it's a function template, and it's declared constexpr), and id(t) is an immediate-escalating expression, so f gets promoted to consteval ๐. That means the call to id(t) sits in an immediate context, so it doesn't have to produce a constant (that's the mechanism that allows consteval function composition) ๐งฉ. But with -fno-immediate-escalation, f does NOT get promoted to consteval. Since the call to the consteval function id(t) isn't a constant expression, the compiler rejects the code ๐
โโ๏ธ.
This option is turned on by default, and it only does anything in C++20 mode or later ๐.
-fimplicit-constexprโ makes inline functions implicitlyconstexprif they meet the requirements for aconstexprfunction โจ. You can use it in C++14 mode or later. This can change initialization from dynamic to static, plus other optimizations ๐.-fno-implicit-templatesโ never emits code for non-inline templates that get instantiated implicitly (aka by use) ๐. Only explicit instantiations get code emitted. If you use this flag, you HAVE to structure your code so it includes all the explicit instantiations you need, or you'll get undefined symbols at link time ๐ญ.-fno-implicit-inline-templatesโ don't emit code for implicit instantiations of inline templates either ๐ธ. By default, inlines get handled differently so that compiles with and without optimization need the same set of explicit instantiations ๐ซถ.-fno-implement-inlinesโ to save space, this skips emitting out-of-line copies of inline functions controlled by#pragma implementation๐ฆ. Heads up: this causes linker errors if those functions aren't inlined everywhere they get called ๐.-fmodules,-fno-modulesโ enables support for C++20 modules ๐ง.-fno-modulesis usually not needed, since that's the default ๐. Even though modules are a C++20 feature, selecting that standard version doesn't implicitly turn them on yet ๐ค.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ compiles a header file into an importable header unit ๐.-fmodule-implicit-inlineโ member functions defined inside their class definitions are NOT implicitly inline for modular code ๐. This is different from traditional C++ behavior, and there are good reasons for it ๐ง . It can still cause some trouble when porting code ๐ฌ. This option makes those function definitions implicitly inline. BUT it generates an ABI incompatibility, so you have to use it everywhere or nowhere ๐จ. (Definitions outside of a named module stay implicitly inline no matter what ๐.)-fno-module-lazyโ disables lazy module importing and module mapper creation ๐ค.-fmodule-mapper=[hostname]:port[?ident],-fmodule-mapper=|program[?ident] args...,-fmodule-mapper==socket[?ident],-fmodule-mapper=<>[inout][?ident],-fmodule-mapper=<in>out[?ident],-fmodule-mapper=file[?ident]โ this is an oracle that answers queries for module name to filename mappings ๐ฎ. If you don't specify one, theCXX_MODULE_MAPPERenvironment variable gets used. If that's unset too, an in-process default is provided ๐งโโ๏ธ.-fmodule-onlyโ only emits the Compiled Module Interface and skips any object file ๐.-fms-extensionsโ disablesWpedanticwarnings about constructs used in MFC, like implicitintand getting a pointer to a member function through non-standard syntax ๐.-fnew-inheriting-ctorsโ enables the P0136 change to the semantics of C++11 constructor inheritance ๐ฆ. It's part of C++17, but it's also considered a Defect Report against C++11 and C++14 ๐งพ. This flag is on by default unless-fabi-version=10or lower is specified.-fnew-ttp-matchingโ enables the P0522 resolution to Core issue 150, which covers template template parameters and default arguments ๐งฉ. This lets a template with default template arguments be used as an argument for a template template parameter that has fewer template parameters ๐ธ. This flag is on by default for-std=c++17๐.-fno-nonansi-builtinsโ disables built-in declarations of functions that aren't required by ANSI/ISO C ๐ โโ๏ธ. These includeffs,alloca,_exit,index,bzero,conjf, and other related functions ๐.-fnothrow-optโ treats athrow()exception specification as if it were anoexceptspecification ๐ช. This reduces or gets rid of the text size overhead compared to a function with no exception specification ๐. If the function has local variables with non-trivial destructors, the exception spec actually makes the function smaller, because the EH cleanups for those variables can be optimized away ๐คฏ.
The semantic effect is that an exception thrown out of a function with this kind of exception specification results in a call toterminateinstead ofunexpectedโ ๏ธ.
-fno-operator-namesโ stops the operator name keywordsand,bitand,bitor,compl,not,orandxorfrom being treated as synonyms for keywords ๐ โโ๏ธ.-fno-optional-diagsโ disables diagnostics that the standard says a compiler doesn't need to issue ๐ซ . Right now, the only one G++ issues like that is the one for a name that has multiple meanings within a class ๐.-fno-pretty-templatesโ ๐ When an error mentions a function template specialization, GCC normally prints the template signature along with the template arguments and any typedefs or typenames in it. So you get something likevoid f(T) [with T = int]instead ofvoid f(int), which makes it clear which template is involved โจ. For class template specializations, GCC leaves out any template arguments that match the defaults for that template. If either of these makes errors harder to read instead of easier ๐, use-fno-pretty-templatesto turn them off.-frange-for-ext-tempsโ ๐ This turns on lifetime extension for temporaries in C++ range-basedforloops. With-std=c++23and newer it's already part of the language standard, so the temporaries live until the end of the loop by default ๐. This flag lets you get that same behavior in earlier versions of the standard.-freflectionโ ๐งช Turns on experimental C++26 Reflection ๐ฆ.-fno-rttiโ ๐ชถ This disables generating the info for every class with virtual functions that C++ run-time type identification relies on (the stuff behinddynamic_castandtypeid). If you don't use those features, this can save you some space ๐. Exception handling uses the same info, but G++ only generates it when it's actually needed. Thedynamic_castoperator still works for casts that don't need run-time type information, which means casts tovoid *or to unambiguous base classes ๐ธ.
โ ๏ธ Mixing code compiled with-frttiand code compiled with-fno-rttimay not work. For example, your program might fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti๐ญ.
-fsized-deallocationโ ๐งน This turns on the built-in global declarations below, which were introduced in C++14:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
This is super useful for your own replacement deallocation functions, like ones that use the size of the object to make deallocation faster ๐. It's on by default under -std=c++14 and above. The -Wsized-deallocation flag warns you about spots that might want to add a definition ๐.
-fstrict-enumsโ ๐ฏ This lets the compiler optimize based on the assumption that a value of an enumerated type can only be one of the enumeration's values. Basically, it's a value that fits in the minimum number of bits needed to represent all the enumerators, as defined by the C++ standard ๐. This assumption might not hold if your program uses a cast to turn an arbitrary integer into the enumerated type, so be careful ๐. This option does nothing for an enumeration type with a fixed underlying type.-fstrong-eval-order,-fstrong-eval-order=kind โ ๐ This makes member access, array subscripting, and shift expressions evaluate left to right, while assignment evaluates right to left, just like it was adopted for C++17 ๐ซถ.-fstrong-eval-orderis the same as-fstrong-eval-order=all, and it's on by default with-std=c++17or later.
-fstrong-eval-order=some only turns on the ordering for member access and shift expressions, and it's the default for C++ dialects before C++17 ๐.
-fstrong-eval-order=none is the same as -fno-strong-eval-order ๐ง.
-ftemplate-backtrace-limit=n โ ๐ Sets the maximum number of template instantiation notes shown for a single warning or error to n. The default is 10 ๐.-ftemplate-depth=n โ ๐ Sets the maximum instantiation depth for template classes to n. You need a limit like this so that endless recursion during template class instantiation can be caught ๐. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than 17, which was changed to 1024 in C++11 ๐. The default is 900, because in some situations the compiler can run out of stack space before it ever hits 1024 ๐ฅฒ.-fno-threadsafe-staticsโ ๐งต Skips the extra code that uses the routines from the C++ ABI for thread-safe initialization of local statics. If your code doesn't need to be thread-safe, this can shave off a bit of code size โ๏ธ.-fuse-cxa-atexitโ ๐ช Registers destructors for objects with static storage duration using the__cxa_atexitfunction instead ofatexit. This is required for fully standards-compliant handling of static destructors, but it only works if your C library supports__cxa_atexit๐งพ.-fno-use-cxa-get-exception-ptrโ ๐ Stops the use of the__cxa_get_exception_ptrruntime routine. This makesstd::uncaught_exceptionincorrect, but you need it if that runtime routine isn't available on your system ๐ซ .-fvisibility-inlines-hiddenโ ๐ซฅ This switch tells GCC that you won't try to compare pointers to inline functions or methods when the two functions' addresses are taken in different shared objects ๐ค.
With this on, GCC may effectively mark inline methods with __attribute__ ((visibility ("hidden"))), so they don't show up in the export table of a DSO and don't need a PLT indirection when they're used inside that DSO ๐ฆ. This can make a huge difference to load and link times for a DSO, since it massively shrinks the dynamic export table when a library leans heavily on templates ๐.
This isn't exactly the same as marking methods as hidden directly, because it doesn't affect static variables local to the function, and it doesn't make the compiler decide the function is defined in only one shared object ๐ค.
You can give a method explicit visibility to cancel out the switch for that method. For example, if you do want to compare pointers to a particular inline method, mark it with default visibility ๐ . Marking the enclosing class with explicit visibility has no effect โจ. Explicitly instantiated inline methods aren't affected by this option, since their linkage might otherwise cross a shared library boundary ๐งฑ.
-fvisibility-ms-compatโ ๐ช This flag tries to use visibility settings to make GCC's C++ linkage model compatible with Microsoft Visual Studio's. It makes these changes to GCC's linkage model:- It sets the default visibility to
hidden, like-fvisibility=hidden๐. - Types are not hidden by default, but their members are ๐ซฃ.
- The One Definition Rule is relaxed for types without explicit visibility specifications that are defined in more than one shared object. Those declarations are allowed if they'd be allowed without this option ๐ท.
- It sets the default visibility to
In new code, it's better to use -fvisibility=hidden and export the classes you actually want to be externally visible ๐ง. Unfortunately, code might rely on the Visual Studio behavior, perhaps by accident ๐ฌ.
Some consequences of these changes: static data members of the same type, with the same name, defined in different shared objects are different, so changing one doesn't change the other ๐งฉ. Also, pointers to function members defined in different shared objects may not compare equal ๐. When this flag is given, defining types with the same name differently is a violation of the ODR. So don't do it, bestie ๐ซ.
-fno-weakโ ๐ธ๏ธ Don't use weak symbol support, even if the linker provides it. By default, G++ uses weak symbols when they're available. This option only exists for testing and shouldn't be used by end users, since it results in inferior code and has no benefits ๐ โโ๏ธ. It may be removed in a future release of G++ ๐ฅ.-fext-numeric-literals(C++ and Objective-C++ only) โ ๐ข Accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions. When this option is off, those suffixes are treated as C++11 user-defined literal numeric suffixes ๐ง . It's on by default for all pre-C++11 dialects and all GNU dialects:-std=c++98,-std=gnu++98,-std=gnu++11, and-std=gnu++14. It's off by default for ISO C++11 onwards (-std=c++11, ...) ๐.-nostdinc++โ ๐ซ Doesn't search for header files in the standard directories specific to C++, but it still searches the other standard directories ๐. (This option is used when building the C++ library ๐๏ธ.)-flang-info-include-translate,-flang-info-include-translate-not,-flang-info-include-translate=header โ ๐ฃ๏ธ These inform you about include translation events. The first one notes accepted include translations, and the second notes declined ones ๐ . The header form informs you about include translations relating to that specific header. If header is of the form"user"or"<system>", it gets resolved to a specific user or system header using the include path ๐บ๏ธ.-flang-info-module-cmi,-flang-info-module-cmi=module โ ๐ฆ These tell you about Compiled Module Interface pathnames. The first notes all CMI pathnames that get read โ . The module form notes when a specific module's CMI is read. module can be a named module or a header-unit, which is indicated by either being a pathname containing directory separators or being enclosed in"<>"or""๐ซง.-stdlib=libstdc++,libc++โ ๐ When G++ is configured to support this option, you can pick an alternate C++ runtime library ๐. There are two choices:libstdc++, which is the default and the native C++ runtime for G++, andlibc++, which is the C++ runtime installed on some operating systems (for example, Darwin versions from Darwin11 onwards ๐). This option switches G++ to use headers from the library you specify, and it emits-lstdc++or-lc++respectively when a C++ runtime is needed for linking ๐.
In addition, these warning options only have meanings for C++ programs ๐:
-Wabi-tag(C++ and Objective-C++ only) โ ๐ท๏ธ Warns when a type with an ABI tag is used in a context that doesn't have that ABI tag. Check out C++ Attributes for more info about ABI tags ๐.-Wno-abbreviated-auto-in-template-argโ ๐ Disables the error for anautoplaceholder type used within a template argument list to declare a C++20 abbreviated function template. For example:
void f(S<auto>);
Okay so this feature was proposed in the Concepts TS, but it did not make it into C++20 ๐
. In the actual standard, a placeholder in a parameter declaration has to show up as a decl-specifier, so anything else is an error ๐. If you need to chill, -fpermissive or -Wno-error=abbreviated-auto-in-template-arg can downgrade it to a warning ๐ซถ.
-Wcomma-subscript(C++ and Objective-C++ only) โ Warns about a comma expression sitting inside a subscript ๐. This was deprecated in C++20 and is getting removed in C++23, but a comma expression wrapped in( )is still totally fine โจ. Here's the vibe:
void f(int *a, int b, int c) {
a[b,c]; // deprecated in C++20, invalid in C++23
a[(b,c)]; // OK
}
In C++23 it's valid to have comma-separated expressions in a subscript when an overloaded subscript operator exists and supports the right number and types of arguments ๐. G++ will still accept the older syntax for code that's invalid in C++23 but used to be valid-yet-deprecated in C++20, and it gives you a pedantic warning you can turn off with -Wno-comma-subscript ๐ธ.
Enabled by default with -std=c++20 unless -Wno-deprecated, and after -std=c++23 regardless of -Wno-deprecated. Before -std=c++20, it's enabled with explicit -Wdeprecated ๐. This warning gets upgraded to an error by -pedantic-errors in C++23 mode or later ๐ญ.
-Wctad-maybe-unsupported(C++ and Objective-C++ only) โ Warns when you do class template argument deduction (CTAD) on a type that has no explicitly written deduction guides ๐. It's the "wait, did this succeed only because the compiler made up the guides?" warning, which might not be what you meant ๐. Some style guides only allow CTAD on types that specifically opt in, meaning types designed to support it ๐ฆ. You can suppress this with the following pattern:
struct allow_ctad_t; // any name works
template <typename T> struct S {
S(T) { }
};
// Guide with incomplete parameter type will never be considered.
S(allow_ctad_t) -> S<void>;
-Wctor-dtor-privacy(C++ and Objective-C++ only) โ Warns when a class seems totally unusable because all its constructors or destructors are private, and it has neither friends nor public static member functions ๐. It also warns if there are no non-private methods and there's at least one private member function that isn't a constructor or destructor ๐.
-Wdangling-reference(C++ and Objective-C++ only) โ Warns when a reference gets bound to a temporary whose lifetime has already ended ๐ญ. Here's a classic:
int n = 1;
const int& r = std::max(n - 1, n + 1); // r is dangling
In that example, two temporaries get created, one for each argument, and a reference to one of them is returned ๐. Both temporaries get destroyed at the end of the full expression, so the reference r is dangling ๐ฅ. This warning also catches dangling references in member initializer lists ๐:
const int& f(const int& i) { return i; }
struct S {
const int &r; // r is dangling
S() : r(f(10)) { }
};
Member functions get checked too, but only their object argument ๐ง:
struct S {
const S& self () { return *this; }
};
const S& s = S().self(); // s is dangling
Some functions are actually safe here, like std::use_facet. They take and return a reference but don't return one of their arguments, which can fool the warning ๐. You can exclude functions like that by wrapping them in a #pragma ๐:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdangling-reference"
const T& foo (const T&) { ... }
#pragma GCC diagnostic pop
The #pragma can also surround the class, and then the warning is disabled for all of its member functions โจ.
-Wdangling-reference also warns about code like this ๐:
auto p = std::minmax(1, 2);
Here std::minmax returns std::pair<const int&, const int&>, and both references dangle after the end of the full expression that contains the call to std::minmax ๐.
It does not warn for std::span-like classes ๐ซถ. We consider classes of this form:
template<typename T>
struct Span {
T* data_;
std::size len_;
};
as std::span-like, meaning the class is a non-union class that has a pointer data member and a trivial destructor ๐. The warning can be disabled with the gnu::no_dangling attribute ๐ฆ. This warning is enabled by -Wextra โญ.
-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ Warns whendeleteis used to destroy an instance of a class that has virtual functions but a non-virtual destructor ๐. It's unsafe to delete a derived-class instance through a base-class pointer if the base class doesn't have a virtual destructor ๐ฌ. This warning is enabled by-Wall๐.-Wdeprecated-copy(C++ and Objective-C++ only) โ Warns that the implicit declaration of a copy constructor or copy assignment operator is deprecated if the class has a user-provided copy constructor or copy assignment operator, in C++11 and up ๐. This warning is enabled by-Wextraโจ.-Wdeprecated-copy-dtor(C++ and Objective-C++ only) โ Basically the same deal as-Wdeprecated-copy, but it also deprecates the implicit copy operations if the class has a user-provided destructor ๐ .
-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only) โ Turns off the warning for when the usual arithmetic conversions get applied to operands where one is an enum and the other is a different enum ๐ โโ๏ธ. This conversion was deprecated in C++20 ๐ง. Example:
enum E1 { e };
enum E2 { f };
int k = f - e;
-Wdeprecated-enum-enum-conversion is enabled by default with -std=c++20 ๐ฅ. In pre-C++20 dialects, this warning can be enabled by -Wenum-conversion or -Wdeprecated ๐ธ.
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only) โ Turns off the warning for when the usual arithmetic conversions get applied to operands where one is an enum and the other is a floating-point type ๐. This conversion was deprecated in C++20 ๐ฅน. Example:
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7;
-Wdeprecated-enum-float-conversion is enabled by default with -std=c++20 ๐. In pre-C++20 dialects, this warning can be enabled by -Wenum-conversion or -Wdeprecated ๐.
-Wdeprecated-literal-operator(C++ and Objective-C++ only) โ Warns that declaring a user-defined literal operator with a space before the suffix is deprecated ๐. This warning is enabled by default in C++23, or with explicit-Wdeprecated๐. Look at the difference:
string operator "" _i18n(const char*, std::size_t); // deprecated
string operator ""_i18n(const char*, std::size_t); // preferred
-Wdeprecated-variadic-comma-omission(C++ and Objective-C++ only) โ Warns that leaving out the comma before the varargs...at the end of a function parameter list is deprecated ๐. This warning is enabled by default in C++26, or with explicit-Wdeprecated๐ฎ. Here's the breakdown:
void f1(int...); // deprecated
void f1(int, ...); // preferred
template <typename ...T>
void f2(T...); // ok
template <typename ...T>
void f3(T......); // deprecated
-Wno-elaborated-enum-baseโ For C++11 and above, this warns if an (invalid) additional enum-base gets used in an elaborated-type-specifier ๐งฉ. That means an enum with a given underlying type and no enumerator list, used in a declaration other than just a standalone declaration of the enum ๐ซ . It's enabled by default โ . This warning gets upgraded to an error with-pedantic-errors๐ญ.-Wno-init-list-lifetime(C++ and Objective-C++ only) โ Turns off the warning about uses ofstd::initializer_listthat are likely to end up with dangling pointers ๐ซฃ. The underlying array for aninitializer_listgets treated like a normal C++ temporary object, so it's super easy to accidentally keep a pointer to the array after its lifetime is over ๐. Here are the sneaky cases:- If a function returns a temporary
initializer_list, or a localinitializer_listvariable, the array's lifetime ends at the end of the return statement, so the value returned has a dangling pointer ๐ป. - If a new-expression creates an
initializer_list, the array only lives until the end of the enclosing full-expression, so theinitializer_liston the heap has a dangling pointer ๐ซฅ. - When an
initializer_listvariable is assigned from a brace-enclosed initializer list, the temporary array created for the right side of the assignment only lives until the end of the full-expression, so at the next statement theinitializer_listvariable has a dangling pointer ๐ต. - When a list constructor stores the
beginpointer from theinitializer_listargument, that doesn't extend the array's lifetime. So if a class variable gets constructed from a temporaryinitializer_list, the pointer is left dangling by the end of the variable declaration statement ๐.
- If a function returns a temporary
// li's initial underlying array lives as long as li
std::initializer_list<int> li = { 1,2,3 };
// assignment changes li to point to a temporary array
li = { 4, 5 };
// now the temporary is gone and li has a dangling pointer
int i = li.begin()[0] // undefined behavior
-Winvalid-constexprโ Warns when a function never produces a constant expression ๐ง. In C++20 and earlier, everyconstexprfunction and function template has to have at least one set of function arguments, in at least one instantiation, where an invocation could be an evaluated subexpression of a core constant expression ๐. C++23 removed this restriction, so it's now possible to have aconstexprfunction or function template where no invocation satisfies the requirements of a core constant expression ๐ธ.
This one's tricky in C++20 ๐. It's enabled as a pedantic warning by default in C++20 and earlier, but in C++23 you can turn on -Winvalid-constexpr and it becomes an ordinary warning โจ. Like this:
void f (int& i);
constexpr void
g (int& i)
{
// Warns by default in C++20, in C++23 only with -Winvalid-constexpr.
f(i);
}
โจ -Winvalid-imported-macros โจ
Okay so this one checks that every imported macro definition is still valid once compilation finishes ๐. It's not on by default, because figuring that out takes extra processing. It's super useful when you're putting together sets of header-units and want your macros to stay consistent across them ๐.
๐ -Wno-literal-suffix ๐ (C++ and Objective-C++ only)
Bestie, this one stops the warning when a string or character literal gets followed by a ud-suffix that doesn't start with an underscore ๐
โโ๏ธ. GCC treats those suffixes as separate preprocessing tokens, which is a conforming extension that keeps old code working, especially code that uses the formatting macros from <inttypes.h> ๐ง. Example:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
int main() {
int64_t i64 = 123;
printf("My int64: %" PRId64"\n", i64);
}
In this case, "PRId64" is treated as a separate preprocessing token ๐
.
This option also controls the warnings you get when a user-defined literal operator is declared with a literal suffix identifier that doesn't begin with an underscore. Those names are reserved for future standardization, so GCC is looking out for you ๐ซถ. These warnings are enabled by default โจ.
๐ -Wno-narrowing ๐ (C++ and Objective-C++ only)
For C++11 and later, narrowing conversions get diagnosed by default, because the standard says so ๐. A narrowing conversion from a constant is an error, and a narrowing conversion from a non-constant is a warning. -Wno-narrowing quiets that diagnostic ๐. Just know that it doesn't change the meaning of well-formed code, since narrowing is still ill-formed in SFINAE contexts โ ๏ธ.
With -Wnarrowing in C++98, you get a warning when a narrowing conversion that C++11 prohibits shows up inside { }. For example:
int i = { 2.2 }; // error: narrowing from double to int
This flag is included in -Wall and -Wc++11-compat ๐ธ.
๐ฆ -Wnoexcept ๐ฆ (C++ and Objective-C++ only)
This one warns when a noexcept-expression evaluates to false because of a call to a function that doesn't have a non-throwing exception specification (throw() or "noexcept"), even though the compiler knows that function never throws ๐ค.
๐ -Wnoexcept-type ๐ (C++ and Objective-C++ only)
It's giving C++17 plot twist ๐. This warns if the C++17 feature that makes noexcept part of a function type changes the mangled name of a symbol compared to C++14. It's enabled by -Wabi and -Wc++17-compat. Here's the example:
template <class T> void f(T t) { t(); };
void g() noexcept;
void h() { f(g); }
In C++14, "f" calls "f<void(*)()>", but in C++17 it calls "f<void(*)()noexcept>" โจ.
๐ง -Wclass-memaccess ๐ง (C++ and Objective-C++ only)
Okay, this one is a lot, but it's important ๐ญ. It warns when the destination of a call to a raw memory function like memset or memcpy is an object of class type. It also warns when writing into that object could bypass a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers. Messing with the representation of these objects can violate invariants that the class's member functions depend on ๐.
For example, the memset call below is undefined, because it modifies a non-trivial class object, so it gets diagnosed:
std::string str = "abc";
memset (&str, 0, sizeof str);
The safe way to initialize or clear the storage of these types is to use the right constructor or assignment operator, if one exists ๐ซถ.
-Wclass-memaccess is enabled by -Wall. If you explicitly cast the pointer to the class object to void *, or to a type that the raw memory function can safely access, the warning goes away ๐
.
๐ -Wnon-virtual-dtor ๐ (C++ and Objective-C++ only)
This warns when a class has virtual functions and an accessible non-virtual destructor, either on the class itself or on an accessible polymorphic base class. In that situation, deleting a derived instance through a pointer to the class or its base is possible but unsafe ๐ฌ. This warning is automatically enabled if -Weffc++ is specified.
Heads up: the -Wdelete-non-virtual-dtor option (enabled by -Wall) is the one you should reach for, because it warns about the unsafe cases without false positives ๐.
๐ธ -Wregister ๐ธ (C++ and Objective-C++ only)
This warns on uses of the "register" storage class specifier, except when it's part of the GNU Explicit Register Variables extension ๐. Using "register" as a storage class specifier was deprecated in C++11 and removed in C++17. It's enabled by default with -std=c++17 ๐.
๐ -Wreorder ๐ (C++ and Objective-C++ only)
This warns when the order of member initializers in your code doesn't match the order they actually get executed in ๐. For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler rearranges the member initializers for "i" and "j" to match the declaration order of the members, and it emits a warning about that ๐. This warning is enabled by -Wall โจ.
๐ฅ -Wno-pessimizing-move ๐ฅ (C++ and Objective-C++ only)
This one warns when a call to std::move prevents copy elision ๐ซ. The typical copy elision scenario is returning from a function with a class return type, where the returned expression is the name of a non-volatile automatic object that isn't a function parameter and has the same type as the function's return type. Like:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
But in this example, the std::move call is the thing that stops copy elision ๐ญ. This warning is enabled by -Wall ๐
.
๐ฆ -Wno-redundant-move ๐ฆ (C++ and Objective-C++ only)
This warns about redundant calls to std::move. In other words, it's when a move would have happened even without the std::move call ๐. That happens because the compiler is forced to treat the object as an rvalue in certain situations, like returning a local variable where copy elision doesn't apply. Consider:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant ๐. Since G++ implements Core Issue 1579, another example is:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this example, copy elision isn't applicable because the type of the returned expression and the function's return type differ. Even so, G++ treats the return value as if it were designated by an rvalue ๐คฏ. This warning is enabled by -Wextra ๐.
๐ -Wrange-loop-construct ๐ (C++ and Objective-C++ only)
This warns when a C++ range-based for-loop creates an unnecessary copy ๐ซง. That can happen when the range declaration isn't a reference but probably should be. For example:
struct S { char arr[128]; };
void fn () {
S arr[5];
for (const auto x : arr) { ... }
}
It won't warn when the copied type is trivially-copyable and smaller than 64 bytes ๐ง.
It also warns when a loop variable in a range-based for-loop gets initialized with a value of a different type, which results in a copy. For example:
void fn() {
int arr[10];
for (const double &x : arr) { ... }
}
In the example above, every iteration creates and destroys a temporary value of type "double", and the reference "const double &" is bound to it ๐ต. This warning is enabled by -Wall โจ.
๐ -Wredundant-tags ๐ (C++ and Objective-C++ only)
This warns about redundant class-key and enum-key in references to class types and enumerated types, in contexts where the key can be dropped without causing ambiguity ๐. For example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
In this example, there's no warning:
struct foo;
void foo (); // "hides" struct foo
void bar (struct foo&); // no warning, keyword struct is necessary
๐ธ -Wno-subobject-linkage ๐ธ (C++ and Objective-C++ only)
Don't warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐. If type A depends on type B with no linkage or internal linkage, defining A in multiple translation units is an ODR violation, because what B means is different in each one ๐ฌ. If A only shows up in a single translation unit, the best way to silence the warning is to give it internal linkage by putting it in an anonymous namespace too. The compiler doesn't give this warning for types defined in the main .C file, since those are unlikely to have multiple definitions ๐ซถ. -Wsubobject-linkage is enabled by default ๐
.
๐ฅ -Weffc++ ๐ฅ (C++ and Objective-C++ only)
This warns about violations of the following style guidelines from Scott Meyers' Effective C++ series of books. Literally every C++ girlie should know these ๐๐:
- Define a copy constructor and an assignment operator for classes with dynamically-allocated memory.
- Prefer initialization to assignment in constructors.
- Have
operator=return a reference to*this. - Don't try to return a reference when you must return an object.
- Distinguish between prefix and postfix forms of increment and decrement operators.
- Never overload
&&,||, or,.
This option also switches on -Wnon-virtual-dtor ๐
, which is one of the effective C++ recommendations, and the check gets extended to flag a missing virtual destructor in accessible non-polymorphic base classes too ๐โจ.
Heads up though ๐ the standard library headers don't follow all of these guidelines, so you'll get noise from them. Use grep -v to filter those warnings out ๐งน๐
-Wno-exceptions(C++ and Objective-C++ only) โ ๐ โโ๏ธ Turns off the warning for when one exception handler gets shadowed by another, which can be a sign your handlers are in the wrong order ๐-Wsfinae-incomplete(C++ and Objective-C++ only) โ ๐ Warns when a class is incomplete, or a function with an auto return type hasn't been deduced yet, in a spot where that causes substitution failure instead of an error, and then the class or function gets defined later in the translation unit. This is messy because template instantiations or concept checks could give different results depending on whether they happen before or after the definition ๐ญ. This warning is on by default ๐ธ.-Wsfinae-incomplete=2adds a warning at the point of substitution failure, so it's easier to track down the problems the default mode flags ๐.-Wstrict-null-sentinel(C++ and Objective-C++ only) โ ๐ง Warns about using an uncastedNULLas a sentinel. When you compile with only GCC, this counts as a valid sentinel, sinceNULLis defined to__null๐. It's a null pointer constant rather than a null pointer, but it's guaranteed to be the same size as a pointer. Just know this isn't portable across different compilers ๐.-Wno-non-c-typedef-for-linkage(C++ and Objective-C++ only) โ ๐ Disables the pedwarn for unnamed classes that have a typedef name for linkage purposes and contain C++-specific stuff: members, base classes, default member initializers, or lambda expressions, including those on nested member classes ๐ง
typedef struct {
int a; // non-static data members are ok
struct T { int b; }; // member classes too
enum E { E1, E2, E3 }; // member enumerations as well
int c = 42; // default member initializers are not ok
struct U : A { int c; }; // classes with base classes are not ok
typedef int V; // typedef is not ok
using W = int; // using declaration is not ok
decltype([](){}) x; // lambda expressions not ok
} S;
In all of these cases, you need to add the tag name S after the struct keyword ๐ซถ
-Wno-non-template-friend(C++ and Objective-C++ only) โ ๐ฆ Disables warnings for non-template friend functions declared inside a template. In super old GCC versions that came before the ISO standard was implemented, something likefriend int foo(int), where the friend's name is an unqualified-id, could get read as a specific specialization of a template function. This warning exists to catch those compatibility problems, and it's enabled by default ๐-Wold-style-cast(C++ and Objective-C++ only) โ ๐ Warns if you use an old-style (C-style) cast to a non-void type in a C++ program. The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are way less vulnerable to unintended effects and much easier to search for ๐โจ-Woverloaded-virtual,-Woverloaded-virtual=n(C++ and Objective-C++ only) โ ๐จ Warns when a function declaration hides virtual functions from a base class. For example:
struct A {
virtual void f();
};
struct B: public A {
void f(int); // does not override
};
So the A class version of f gets hidden in B, and code like this:
B* b;
b->f();
fails to compile ๐ญ
If the different signatures are on purpose and not an accident, the simplest fix is adding a using-declaration to the derived class to un-hide the base function, like using A::f; in B ๐ฆ
The optional level suffix controls what happens when all the declarations in the derived class override virtual functions in the base class, even if not every base function is overridden ๐ง
struct C {
virtual void f();
virtual void f(int);
};
struct D: public C {
void f(int); // does override
}
This pattern is less likely to be a mistake. If D is only ever used virtually, the user might have decided the base class semantics for some of the overloads are totally fine ๐
At level 1, this case doesn't warn. At level 2, it does. -Woverloaded-virtual by itself selects level 2, and level 1 is included in -Wall ๐
-Wno-pmf-conversions(C++ and Objective-C++ only) โ ๐ โโ๏ธ Disables the diagnostic for converting a bound pointer to member function into a plain pointer ๐ธ-Wsign-promo(C++ and Objective-C++ only) โ โ ๏ธ Warns when overload resolution picks a promotion from an unsigned or enumerated type to a signed type, instead of a conversion to an unsigned type of the same size. Older versions of G++ tried to keep the unsignedness, but the standard mandates the current behavior, so no cap, that's the rule now ๐-Wtemplates(C++ and Objective-C++ only) โ ๐ Warns when a primary template declaration shows up. Some coding rules ban templates, so this can help enforce that rule ๐ . The warning is inactive inside system header files like the STL, so you can still use the STL ๐ซถ. You can also still instantiate or specialize templates โจ-Wmismatched-new-delete(C++ and Objective-C++ only) โ ๐ Warns about mismatches between calls tooperator neworoperator deleteand the matching allocation or deallocation function. This coversoperator deletebeing called on pointers returned from mismatched forms ofoperator new, or from other functions that allocate objects whereoperator deleteisn't a suitable deallocator, plus calls to other deallocation functions on pointers returned fromoperator newwhere that deallocation function isn't suitable ๐ญ
For example, the delete expression in this function gets diagnosed because it doesn't match the array form of the new expression that the pointer came from. The call to free gets diagnosed too ๐งน
void f ()
{
int *a = new int[n];
delete a; // warning: mismatch in array forms of expressions
char *p = new char[n];
free (p); // warning: mismatch between new and free
}
The related option -Wmismatched-dealloc handles mismatches involving allocation and deallocation functions other than operator new and operator delete ๐ฆ. And -Wmismatched-new-delete is included in -Wall ๐
-Wmismatched-tags(C++ and Objective-C++ only) โ ๐ Warns about declarations of structs, classes, and class templates (plus their specializations) where the class-key doesn't match the definition, or the first declaration if no definition is given. In the example below, thestruct Objectin the argument list ofdrawsets it off. To avoid it, either remove the redundantstructclass-key or swap it forclassso it matches the definition ๐
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
To be clear, declaring a class with the class-key struct isn't wrong, as the example above shows ๐. -Wmismatched-tags is just there to help you keep a consistent style for class declarations ๐. In code meant to be portable to Windows-based compilers, the warning helps prevent unresolved references caused by different name mangling for symbols declared with different class-keys ๐ง. You can use this option on its own or together with -Wredundant-tags ๐ซถ
-Wmultiple-inheritance(C++ and Objective-C++ only) โ ๐ Warns when a class is defined with multiple direct base classes. Some coding rules disallow multiple inheritance, so this can help enforce that rule ๐. It's inactive inside system header files like the STL, so the STL is still fair game ๐ธ. You can still define classes that indirectly use multiple inheritance โจ-Wvirtual-inheritanceโ ๐ Warns when a class is defined with a virtual direct base class. Some coding rules disallow multiple inheritance, so this can enforce that rule ๐. Inactive inside system header files like the STL, so you can still use the STL ๐ซถ. You can also define classes that indirectly use virtual inheritance ๐-Wno-virtual-move-assign(C++ and Objective-C++ only) โ โ ๏ธ Suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator. This is dangerous ๐ญ because if the virtual base is reachable along more than one path, it gets moved multiple times, which can leave both objects in the moved-from state. If your move assignment operator is written to avoid moving from a moved-from object, you can disable this warning ๐-Wnamespacesโ ๐ Warns when a namespace definition is opened. Some coding rules disallow namespaces, so this can help enforce that rule ๐ . Inactive inside system header files like the STL, so you can still use the STL ๐ซถ. You can also use using directives and qualified names ๐ธ-Wno-template-body(C++ and Objective-C++ only) โ ๐ง Disables diagnosing errors when parsing a template. Instead, an error only gets issued when the template is instantiated ๐ฆ. This flag can also downgrade those errors into warnings with-Wno-error=or-fpermissiveโจ-Wno-template-id-cdtor(C++ and Objective-C++ only) โ ๐ Disables the warning about using a simple-template-id as the declarator-id of a constructor or destructor. That became invalid in C++20 via DR 2237 ๐ญ. For example:
template<typename T> struct S {
S<T>(); // should be S();
~S<T>(); // should be ~S();
};
-Wtemplate-id-cdtor is enabled by default with -std=c++20, and it's also enabled by -Wc++20-compat ๐๐
-Wtemplate-names-tu-localโ okay bestie, this one warns when a template body quietly ends up exposing a translation-unit-local entity ๐ซฃ Usually, pointing at a TU-local thing (like an internal linkage declaration) from inside something emitted into a module's CMI is an error โ. BUT inside a variable's initializer, or in the body of a non-inline function, it's not counted as an exposure, so no error pops up ๐คทโโ๏ธ
This can quietly make variable or function templates unusable ๐ if they reference such an entity, because other translation units that import the template will never be able to instantiate it. This warning tries to sniff out cases where that might happen ๐ต๏ธโโ๏ธ An explicit instantiation silences it ๐คซ
This flag is enabled by -Wextra โจ
-Wno-expose-global-module-tu-localโ an exposure of a TU-local entity from a module interface is invalid ๐ซ because it can cause ODR violations and show up as link errors or other unexpected behaviour. The annoying part is that lots of existing libraries declare TU-local entities in their interface, and dodging those exposures can be genuinely tricky ๐ฉ
As an extension, GCC lets you expose internal variables and functions that were declared in the global module fragment ๐ This warning tells you when that kind of invalid exposure happens, and you can silence it with diagnostic pragmas either right at the exposure site or at the point where the internal declaration is declared.
When combined with -Wtemplate-names-tu-local, GCC will also warn about non-exposure references to TU-local entities in template bodies ๐ฃ Those templates can still be instantiated in other TUs, but the exposure risks above still apply.
This warning is enabled by default, and gets upgraded to an error by -pedantic-errors ๐ฅ
-Wno-external-tu-localโ warn when naming a TU-local entity outside the translation unit it was declared in ๐ โโ๏ธ These declarations get ignored during name lookup. This can happen when doing ADL from a template declared in the same TU as the internal function:
export module M;
template <typename T> void foo(T t) {
bar(t);
}
struct S {} s;
static void bar(S) {} // internal linkage
// instantiating foo(s) from outside this TU can see ::bar,
// but naming it there is ill-formed.
Workaround alert ๐ง this can be fixed by making "bar" attached to the global module, using extern "C++".
This warning is enabled by default, and gets upgraded to an error by -pedantic-errors ๐
-Wno-terminate(C++ and Objective-C++ only) โ turns off the warning about a throw-expression that will immediately result in a call to "terminate" ๐-Wno-vexing-parse(C++ and Objective-C++ only) โ the most vexing parse ๐ญ This warns when a declaration looks like a variable definition, but C++ says it has to be read as a function declaration. Iconic behaviour, honestly:
void f(double a) {
int i(); // extern int i (void);
int n(int(a)); // extern int n (int);
}
Another example, because once is never enough ๐
struct S { S(int); };
void f(double a) {
S x(int(a)); // extern struct S x (int);
S y(int()); // extern struct S y (int (*) (void));
S z(); // extern struct S z (void);
}
The warning will suggest ways to deal with the ambiguity ๐ ๏ธ for example, it can suggest removing the parentheses or using braces instead.
This warning is enabled by default โ
-Wno-class-conversion(C++ and Objective-C++ only) โ don't warn when a conversion function converts an object to the same type, to a base class of that type, or to void ๐ซ Such a conversion function will never be called, so the warning is kinda pointless.-Wvolatile(C++ and Objective-C++ only) โ warns about deprecated uses of thevolatilequalifier ๐ฅ This covers a bunch of vibes:- postfix and prefix
++and--expressions onvolatile-qualified types - simple assignments where the left operand is a
volatile-qualified non-class type, for their value - compound assignments where the left operand is a
volatile-qualified non-class type - a
volatile-qualified function return type - a
volatile-qualified parameter type - structured bindings of a
volatile-qualified type
- postfix and prefix
This usage was deprecated in C++20, so it's giving "retire this habit" ๐
Enabled by default with -std=c++20. Before -std=c++20, it's enabled with an explicit -Wdeprecated ๐
-Waligned-new,-Waligned-new=[none|global|all]โ warn about a new-expression of a type that needs more alignment thanalignof(std::max_align_t), but uses an allocation function without an explicit alignment parameter ๐ This option is enabled by-Wall๐ธ
Normally this only warns about global allocation functions, but -Waligned-new=all also warns about class member allocation functions ๐
-Wno-placement-new,-Wplacement-new=nโ warn about placement new expressions with undefined behavior ๐จ For example, the placement new below gets diagnosed because it tries to construct an array of 64 integers in a buffer that's only 64 bytes large ๐
char buf [64];
new (buf) int[64];
This warning is enabled by default โจ
-Wplacement-new=1โ this is the default level ๐ง At this level, the warning skips some strictly undefined constructs that GCC allows as extensions for compatibility with legacy code. For example, thenewexpression below is not diagnosed here, even though it's undefined behaviour according to the C++ standard, because it writes past the end of the one-element array:
struct S { int n, a[1]; };
S *s = (S *)malloc (sizeof *s + 31 * sizeof s->a[0]);
new (s->a)int [32]();
-Wplacement-new=2โ this level diagnoses everything level 1 does, plus placement new expressions that construct an object in the last member of a structure, where that member is an array of a single element and its size is less than the size of the object being constructed ๐ The previous example gets flagged here, but the flexible member array extension below slides past the warning at level 2 ๐ฆ
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ warn about catch handlers that don't catch via reference ๐-Wcatch-value=1(or just-Wcatch-valuefor short) warns about polymorphic class types caught by value.-Wcatch-value=2warns about all class types caught by value.-Wcatch-value=3warns about all types that aren't caught by reference.-Wcatch-valueis enabled by-Wall๐ซถ-Wconditionally-supported(C++ and Objective-C++ only) โ warn for conditionally-supported (C++11 [intro.defs]) constructs ๐ง-Wno-defaulted-function-deleted(C++ and Objective-C++ only) โ warn when an explicitly defaulted function gets deleted by the compiler ๐ค That can happen when the function's declared type doesn't match the type of the function that would've been implicitly declared. This warning is enabled by default โ-Wno-delete-incomplete(C++ and Objective-C++ only) โ don't warn when deleting a pointer to an incomplete type, which may cause undefined behaviour at runtime ๐ซฃ This warning is enabled by default โ-Wextra-semi(C++, Objective-C++ only) โ warn about redundant semicolons ๐งต There are a few sneaky contexts where an extra semicolon can show up:- a semicolon after in-class function definitions. This is valid in all C++ dialects and is never a pedwarn ๐
struct S {
void foo () {};
};
- an extra semicolon at namespace scope. This has been allowed since C++11, so it's a pedwarn in C++98 ๐
struct S {
};
;
- an extra semicolon in class definitions. This has also been allowed since C++11, so it's a pedwarn in C++98 ๐
struct S {
int a;
;
};
-Wno-global-module(C++ and Objective-C++ only) โ disables the diagnostic for when the global module fragment of a module unit doesn't consist only of preprocessor directives ๐-Wno-inaccessible-base(C++, Objective-C++ only) โ controls warnings when a base class is inaccessible in a class derived from it due to ambiguity ๐ต๏ธ This warning is enabled by default. Note that the warning for ambiguous virtual bases is enabled by the-Wextraoption โจ
struct A { int a; };
struct B : A { };
struct C : B, A { };
-Wno-inherited-variadic-ctorโ suppresses warnings about the use of C++11 inheriting constructors when the base class being inherited from has a C variadic constructor ๐ฆ This warning is on by default, because the ellipsis is not inherited.-Wno-invalid-offsetof(C++ and Objective-C++ only) โ suppresses warnings from applying theoffsetofmacro to a non-POD type ๐ According to the 2014 ISO C++ standard, applyingoffsetofto a non-standard-layout type is undefined. In existing C++ implementations, though,offsetofusually gives meaningful results. This flag is for users who know they're writing nonportable code and who've deliberately chosen to ignore the warning about it ๐ง
The restrictions on offsetof may be relaxed in a future version of the C++ standard ๐ฎ
-Wsized-deallocation(C++ and Objective-C++ only) โ warns about a definition of an unsized deallocation function, like these:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
โฆthat shows up without a definition of the corresponding sized deallocation function ๐ฉ
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
...or vice versa ๐ This one's switched on by -Wextra along with -fsized-deallocation ๐
-Wsuggest-final-typesโ Okay so this one warns about types with virtual methods that would be way cleaner if they were declared with the C++11finalspecifier, or, if it's possible, declared in an anonymous namespace ๐ง It's giving devirtualization, because it lets GCC more aggressively devirtualize the polymorphic calls โจ It hits harder with link-time optimization, since the class hierarchy graph info is more complete there ๐-Wsuggest-final-methodsโ Warns about virtual methods that would glow up if they were declared withfinal, or, if possible, if their type were declared in an anonymous namespace or with thefinalspecifier ๐ธ Same deal as above: it's more effective with link-time optimization, where the class hierarchy graph is more complete. Bestie tip straight from the manual: consider the-Wsuggest-final-typessuggestions first, then rebuild with the new annotations ๐ซถ-Wsuggest-overrideโ Warns about overriding virtual functions that aren't marked with theoverridekeyword ๐ฆ-Wno-conversion-null(C++ and Objective-C++ only) โ Do not warn for conversions betweenNULLand non-pointer types. Just so you know,-Wconversion-nullis enabled by default ๐
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
(NOTE: This manual does not describe the Objective-C and Objective-C++ languages themselves.
This section is all about the command-line options that only matter for Objective-C and Objective-C++ programs ๐ You can still use most of the language-independent GNU compiler options too! For example, you might compile a file some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
In this example, -fgnu-runtime is an option meant only for Objective-C and Objective-C++ programs, but you can use the other options with any language GCC supports ๐
Note that since Objective-C is an extension of the C language, Objective-C compilations may also use options specific to the C front-end (e.g., -Wtraditional). Similarly, Objective-C++ compilations may use C++-specific options (e.g., -Wabi) ๐
Here is a list of options that are only for compiling Objective-C and Objective-C++ programs ๐
-fconstant-string-class=class-nameโ Use class-name as the name of the class to instantiate for each literal string written with the syntax"@"...""๐ง The default class name is"NXConstantString"if the GNU runtime is being used, and"NSConstantString"if the NeXT runtime is being used (see below). On Darwin / macOS platforms, the-fconstant-cfstringsoption, if also present, overrides the-fconstant-string-classsetting and causes"@"...""literals to be laid out as constant CoreFoundation strings. Note that-fconstant-cfstringsis an alias for the target-specific-mconstant-cfstringsequivalent ๐-fgnu-runtimeโ Generate object code compatible with the standard GNU Objective-C runtime. This is the default for most types of systems ๐ธ-fnext-runtimeโ Generate output compatible with the NeXT runtime. This is the default for NeXT-based systems, including Darwin / macOS ๐ The macro"__NEXT_RUNTIME__"is predefined if (and only if) this option is used.-fno-nil-receiversโ Assume that all Objective-C message dispatches ("[receiver message:arg]") in this translation unit make sure the receiver is not"nil". This lets the runtime use more efficient entry points ๐ This option is only available in conjunction with the NeXT runtime and ABI version 0 or 1.-fobjc-abi-version=nโ Use version n of the Objective-C ABI for the selected runtime. Right now this is only supported for the NeXT runtime ๐ In that case, Version 0 is the traditional (32-bit) ABI without support for properties and other Objective-C 2.0 additions. Version 1 is the traditional (32-bit) ABI with support for properties and other Objective-C 2.0 additions. Version 2 is the modern (64-bit) ABI. If nothing is specified, the default is Version 0 on 32-bit target machines, and Version 2 on 64-bit target machines.-fobjc-call-cxx-cdtorsโ Okay, this one's a whole vibe ๐ For each Objective-C class, it checks if any of its instance variables is a C++ object with a non-trivial default constructor. If so, it synthesizes a special"- (id) .cxx_construct"instance method, which runs non-trivial default constructors on any such instance variables, in order, and then returnsself. Similarly, it checks if any instance variable is a C++ object with a non-trivial destructor, and if so, it synthesizes a special"- (void) .cxx_destruct"method, which runs all such default destructors, in reverse order. The"- (id) .cxx_construct"and"- (void) .cxx_destruct"methods generated this way only operate on instance variables declared in the current Objective-C class, and not the ones inherited from superclasses. It's the responsibility of the Objective-C runtime to invoke all such methods in an object's inheritance hierarchy. The"- (id) .cxx_construct"methods are invoked by the runtime immediately after a new object instance is allocated, and the"- (void) .cxx_destruct"methods are invoked immediately before the runtime deallocates an object instance. As of this writing, only the NeXT runtime on Mac OS X 10.4 and later has support for invoking the"- (id) .cxx_construct"and"- (void) .cxx_destruct"methods ๐ญ-fobjc-direct-dispatchโ Allow fast jumps to the message dispatcher. On Darwin, this is accomplished via the comm page โก-fobjc-exceptionsโ Enable syntactic support for structured exception handling in Objective-C, similar to what C++ offers ๐ซถ This option is required to use the Objective-C keywords@try,@throw,@catch,@finallyand@synchronized. It's available with both the GNU runtime and the NeXT runtime (but not in conjunction with the NeXT runtime on Mac OS X 10.2 and earlier) ๐-fobjc-gcโ Enable garbage collection (GC) in Objective-C and Objective-C++ programs. This option is only available with the NeXT runtime. The GNU runtime has a different garbage collection implementation that doesn't require special compiler flags ๐งน-fobjc-nilcheckโ For the NeXT runtime with version 2 of the ABI, check for a nil receiver in method invocations before doing the actual method call. This is the default, and it can be disabled using-fno-objc-nilcheck. Class methods and super calls are never checked for nil in this way, no matter what this flag is set to. Currently this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is used ๐-fobjc-std=objc1โ Conform to the language syntax of Objective-C 1.0, the language recognized by GCC 4.0 ๐ฐ๏ธ This only affects the Objective-C additions to the C/C++ language. It does not affect conformance to C/C++ standards, which is controlled by the separate C/C++ dialect option flags. When this option is used with the Objective-C or Objective-C++ compiler, any Objective-C syntax that GCC 4.0 doesn't recognize is rejected. This is useful if you need to make sure your Objective-C code can be compiled with older versions of GCC ๐งธ-freplace-objc-classesโ Emit a special marker tellingld(1)not to statically link in the resulting object file, and allowdyld(1)to load it at run time instead ๐ฆ This is used with the Fix-and-Continue debugging mode, where the object file may be recompiled and dynamically reloaded during program execution, without restarting the program itself. Right now, Fix-and-Continue is only available with the NeXT runtime on Mac OS X 10.3 and later.-fzero-linkโ When compiling for the NeXT runtime, the compiler usually swaps calls toobjc_getClass("...")(when the class name is known at compile time) for static class references that get initialized at load time, which boosts run-time performance ๐ฅ Specifying-fzero-linksuppresses this and keeps the calls toobjc_getClass("..."). That's useful in Zero-Link debugging mode, since it lets you modify individual class implementations during program execution. The GNU runtime currently always retains calls toobjc_get_class("..."), regardless of command-line options ๐-fno-local-ivarsโ By default, instance variables in Objective-C can be accessed as if they were local variables from within the methods of the class they're declared in. This can cause shadowing between instance variables and other variables declared either locally inside a class method or globally with the same name ๐ต Specifying-fno-local-ivarsdisables this behavior, which avoids variable shadowing issues ๐-fivar-visibility=[public|protected|private|package]โ Sets the default instance variable visibility to the specified option, so that instance variables declared outside the scope of any access modifier directives default to that visibility ๐๏ธ-gen-declsโ Dumps interface declarations for all classes seen in the source file to a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ Warns whenever an Objective-C assignment is being intercepted by the garbage collector ๐จ-Wno-property-assign-default(Objective-C and Objective-C++ only) โ Don't warn if a property for an Objective-C object has no assign semantics specified ๐-Wno-protocol(Objective-C and Objective-C++ only) โ Okay, so if a class is declared to implement a protocol, a warning gets issued for every method in the protocol that the class doesn't implement. The default behavior is to warn for every method not explicitly implemented in the class, even if the method implementation is inherited from the superclass ๐ฅบ If you use-Wno-protocol, then methods inherited from the superclass are considered implemented, and no warning is issued for them ๐ท-Wobjc-root-class(Objective-C and Objective-C++ only) โ okay so this one yells if a class interface has no superclass ๐ Most classes inherit fromNSObject(orObject), for example. If you're making a class that's supposed to be a root class, you can silence the warning by marking its interface with__attribute__((objc_root_class))๐-Wselector(Objective-C and Objective-C++ only) โ this one flags when you've got multiple methods with different types sharing the same selector during compilation ๐ The check runs on the method list at the very end of compilation. It also checks every selector used in a@selector(...)expression, if a matching method was found during compilation. Because all of this only happens at the final stage, these warnings won't show up if that stage never gets reached, like when there's an error during compilation or when-fsyntax-onlyis in use ๐-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if a selector has multiple methods with different argument and/or return types when you try to send a message with it to a receiver of typeidorClass๐จ By default this flag is off, and in that case the compiler skips these warnings if the only differences are between types that share the same size and alignment. Sneaky, but chill ๐ฆ-Wundeclared-selector(Objective-C and Objective-C++ only) โ warns when you use a@selector(...)expression for a selector that was never declared ๐จ A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, either explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection. This option checks right away as soon as it spots a@selector(...)expression, while-Wselectoronly checks at the final stage of compilation. It also backs up the style rule that methods and selectors need to be declared before they get used ๐-print-objc-runtime-infoโ generates a C header describing the largest structure that gets passed by value, if there is one ๐ง
โจ Options Controlling OpenMP and OpenACC โจ
okay so GCC supports OpenMP extensions for C, C++, and Fortran with -fopenmp ๐ And OpenACC extensions work in all three languages with -fopenacc ๐
-foffload=disable,-foffload=default,-foffload=target-listโ this is how you choose which OpenMP and OpenACC offload targets get code generated for them ๐ฏ The default behavior, which is the same as-foffload=default, is to generate code for all supported offload targets.-foffload=disableonly generates code for the host fallback, and-foffload=target-listonly generates code for the comma-separated list of offload targets you give it ๐ซถ
Offload targets are written in GCC's internal target-triplet format. If you run the compiler with -v, it'll show you the list of configured offload targets under "OFFLOAD_TARGET_NAMES" ๐
-foffload-options=options,-foffload-options=target-triplet-list=optionsโ with-foffload-options=options, GCC passes your options to the compilers for every enabled offloading target ๐ If you want options that only apply to certain targets, use the-foffload-options=target-list=optionsform instead. The target-list is a comma-separated list in the same format as the-foffload=option.
Typical command lines look like this:
-foffload-options='-fno-math-errno -ffinite-math-only' \
-foffload-options=nvptx-none=-latomic
-foffload-options=amdgcn-amdhsa=-march=gfx906
-fopenaccโ turns on handling of OpenACC directives:#pragma accin C/C++, and!$accin free-form Fortran, plus!$acc,c$acc, and*$accin fixed-form Fortran ๐ Heads up, this option implies-pthread, so it's only supported on targets that actually support-pthreadโ ๏ธ-fopenacc-dim=geomโ sets default compute dimensions for parallel offload regions that don't specify their own ๐ The geom value is a triple of:-separated sizes, in the order gang, worker, and vector. You can leave a size out to use a target-specific default value โจ-fopenmpโ turns on handling of OpenMP directives like#pragma omp,[[omp::decl(...)]],[[omp::directive(...)]], and[[omp::sequence(...)]]in C/C++ ๐ In Fortran, it enables!$ompand the conditional compilation sentinel!$. In fixed source form Fortran, those sentinels can also start withcor*.
This option implies -pthread, so it's only supported on targets that have -pthread support ๐งต -fopenmp also implies -fopenmp-simd.
-fopenmp-simdโ enables handling of OpenMP's"simd","declare simd","declare reduction","assume","ordered","scan", and"loop"directives, plus combined or composite directives that have"simd"as a constituent ๐ธ This works with#pragma omp,[[omp::directive(...)]],[[omp::sequence(...)]], and[[omp::decl(...)]]in C/C++, and with!$ompin Fortran. It also turns on the!$conditional compilation sentinel in Fortran. In fixed source form Fortran, the sentinels can also start withcor*. Other OpenMP directives get ignored ๐ Unless-fopenmpis also specified, the"loop"region binds to the current task region, no matter what"bind"clause you wrote.-fopenmp-target-simd-clone,-fopenmp-target-simd-clone=device-typeโ on top of generating SIMD clones for functions marked with"declare simd", GCC also makes clones for functions marked with the OpenMP"declare target"directive that are good for vectorization when this option is on ๐ฆ The device-type can be one of"none","host","nohost", or"any". These match the keywords for the"device_type"clause of"declare target", and clones get generated for the intersection of the devices you specify.-fopenmp-target-simd-cloneis the same as-fopenmp-target-simd-clone=any, and-fno-openmp-target-simd-cloneis the same as-fopenmp-target-simd-clone=none.
At -O2 and higher (but not -Os or -Og), this optimization defaults to -fopenmp-target-simd-clone=nohost. Otherwise it's disabled by default ๐
โจ Options to Control Diagnostic Messages Formatting โจ
traditionally, diagnostic messages got formatted without caring about the output device's aspect (like its width, and so on) ๐ You can use the options below to control the formatting algorithm, like how many characters go on a line, or how often source location info gets reported. Heads up that some language front ends might not honor these options ๐
-fmessage-length=nโ tries to format error messages so they fit on lines about n characters long ๐ If n is zero, no line-wrapping happens, and each error message shows up on a single line. This is the default for all front ends.
Note: this option also affects the display of the #error and #warning preprocessor directives, and the deprecated function/type/variable attribute. It does not affect the pragma GCC warning and pragma GCC error pragmas โ ๏ธ
-fdiagnostics-plain-outputโ makes diagnostic output look as plain as possible ๐งผ This is handy when you're running dejagnu or other utilities that parse diagnostics output and need it to stay stable over time.-fdiagnostics-plain-outputis currently the same as these options:
-fno-diagnostics-show-caret
-fno-diagnostics-show-line-numbers
-fdiagnostics-color=never
-fdiagnostics-urls=never
-fdiagnostics-path-format=separate-events
-fdiagnostics-text-art-charset=none
-fno-diagnostics-show-event-links
-fno-diagnostics-show-nesting
If GCC ever changes the default look of its diagnostics in the future, the matching option to turn off the new behavior will be added to this list ๐ฎ
-fdiagnostics-show-location=onceโ only matters in line-wrapping mode ๐ It tells the diagnostic reporter to emit source location info once. So if a message is too long for one physical line and has to wrap, the location won't keep getting stuck on as a prefix on every continuation line. This is the default behavior ๐-fdiagnostics-show-location=every-lineโ also only matters in line-wrapping mode ๐ This one tells the reporter to put the same source location info (as a prefix) on every physical line that comes out of breaking up a message that's too long to fit on one line ๐-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ uses color in diagnostics ๐จ WHEN can benever,always, orauto. The default depends on how the compiler was configured. It can be any of thoseWHENoptions, orneverif theGCC_COLORSenvironment variable isn't in the environment, andautootherwise.automakes GCC use color only when standard error is a terminal and it's not running in an emacs shell ๐ง The forms-fdiagnostics-colorand-fno-diagnostics-colorare aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively.
The colors get defined by the GCC_COLORS environment variable ๐ธ Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings. SGR commands get interpreted by the terminal or terminal emulator (check the section in your text terminal's documentation for the permitted values and what they mean as character attributes). These substring values are decimal integers and can be concatenated with semicolons. Common values to concatenate include 1 for bold, 4 for underline, 5 for blink, 7 for inverse, 39 for default foreground color, 30 to 37 for foreground colors, 90 to 97 for 16-color mode foreground colors, 38;5;0 to 38;5;255 for 88-color and 256-color modes foreground colors, 49 for default background color, 40 to 47 for background colors, 100 to 107 for 16-color mode background colors, and 48;5;0 to 48;5;255 for 88-color and 256-color modes background colors ๐ซง
The default GCC_COLORS is
error=01;31:warning=01;35:note=01;36:range1=32:range2=34:locus=01:\ quote=01:path=01;36:fixit-insert=32:fixit-delete=31:\ diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\ type-diff=01;32:fnname=01;32:targs=35:valid=01;31:invalid=01;32\ highlight-a=01;32:highlight-b=01;34
okay so here's your little decoder ring ๐
01;31 is bold red ๐ฅ, 01;35 is bold magenta ๐, 01;36 is bold cyan ๐ฆ, 32 is green ๐, 34 is blue ๐, 01 is bold, and 31 is red. Setting GCC_COLORS to the empty string turns colors off completely ๐
. These are the capabilities you can tweak, bestie โจ
error=โ the SGR color code forerror:markers ๐ฅwarning=โ the SGR color code forwarning:markers โ ๏ธnote=โ the SGR color code fornote:markers ๐path=โ colors the paths of control-flow events when they're printed via-fdiagnostics-path-format=, like the IDs of individual events and the lines showing interprocedural calls and returns ๐ค๏ธrange1=โ the first additional range ๐range2=โ the second additional range ๐locus=โ location info, likefile:lineorfile:line:columnetc. ๐quote=โ info printed within quotes ๐ฌfnname=โ names of C++ functions ๐งtargs=โ C++ function template parameter bindings ๐ธfixit-insert=โ fix-it hints suggesting text to be inserted or replaced โfixit-delete=โ fix-it hints suggesting text to be deleted โdiff-filename=โ filename headers within generated patches ๐diff-hunk=โ the starts of hunks within generated patches ๐งฉdiff-delete=โ deleted lines within generated patches โdiff-insert=โ inserted lines within generated patches โtype-diff=โ highlights mismatching types within template arguments in the C++ frontend ๐valid=โ highlights valid elements within text art diagrams ๐invalid=โ highlights invalid elements within text art diagrams ๐highlight-a=andhighlight-b=โ the SGR substrings for contrasting two different things within diagnostics, like a pair of mismatching types. See-fdiagnostics-show-highlight-colors๐จ
-fdiagnostics-urls[=WHEN]โ embeds URL escape sequences in diagnostics. For example, when-fdiagnostics-show-optionshows the command-line option controlling a diagnostic, it embeds a URL pointing to the docs for that option ๐WHENisnever,always, orauto.automakes GCC use URL escape sequences only when standard error is a terminal, and when it's not running in an emacs shell or any graphical terminal known to be incompatible with this feature (more on that below) ๐ซถ- The default depends on how the compiler was configured, and it can be any of the above
WHENoptions. - GCC can also be configured with
--with-diagnostics-urls=auto-if-envso the default is affected by environment variables. Under that setup, GCC defaults toautoif eitherGCC_URLSorTERM_URLSis present and non-empty in the compiler's environment, orneverif neither is. - Even with
-fdiagnostics-urls=always, the behavior still depends on those environment variables:- If
GCC_URLSis set to empty orno, URLs are not embedded in diagnostics. - If set to
st, URLs use ST escape sequences. - If set to
bel, which is the default, URLs use BEL escape sequences. - Any other non-empty value enables the feature.
- If
GCC_URLSis not set,TERM_URLSis used as a fallback.
- If
- Note: ST is an ANSI escape sequence with the string terminator
ESC \. BEL is an ASCII character, CTRL-G, that usually sounds like a beep ๐ - GCC tries to detect a few terminals that don't implement the URL feature, or that had bugs in versions still in use, where URL escapes are likely to misbehave. That list is currently xfce4-terminal, certain known buggy gnome-terminal versions, the linux console, and mingw. This check can be skipped with
-fdiagnostics-urls=always.
bestie, on those glitchy terminals the URL escapes can print garbage all over the screen ๐ญ that's why GCC tries to dodge them!
-fno-diagnostics-show-optionโ by default, each diagnostic includes text showing the command-line option that directly controls it (if that option is known to the diagnostic machinery). This flag suppresses that behavior ๐-fno-diagnostics-show-caretโ by default, each diagnostic includes the original source line and a caret^pointing at the column. This option suppresses that info ๐ . The source line is truncated toncharacters if the-fmessage-length=noption is given. When the output goes to the terminal, the width is limited to the width given by theCOLUMNSenvironment variable or, if that isn't set, the terminal width ๐-fno-diagnostics-show-labelsโ by default, when source code is printed (via-fdiagnostics-show-caret), diagnostics can label ranges of source code with pertinent info, like the types of expressions. Here's the vibe:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses the labels, so in the example above, the vertical bars and the "char *" and "long int" text are gone ๐
-fno-diagnostics-show-event-linksโ by default, when execution paths are printed (via-fdiagnostics-path-format=inline-events), GCC prints lines connecting related events, like the line connecting events 1 and 2 in this example:
3 | if (p)
| ^
| |
| (1) following `false' branch (when `p' is NULL)... ->-+
| |
| |
|+------------------------------------------------------------+
4 || return 0;
5 || return *p;
|| ~
|| |
|+-------->(2) ...to here
| (3) dereference of NULL `p'
This option suppresses those connector lines ๐งต
-fno-diagnostics-show-cweโ diagnostic messages can optionally have an associated CWE ("https://cwe.mitre.org/index.html") identifier. GCC itself only provides this metadata for some of the-fanalyzerdiagnostics, and GCC plugins may also provide diagnostics with it. By default, if this info is present, it gets printed with the diagnostic. This option suppresses that metadata ๐ก๏ธ-fno-diagnostics-show-rulesโ diagnostic messages can optionally have rules attached, like ones from a coding standard or a specification. GCC itself doesn't do this for any of its diagnostics, but plugins may. By default, if the info is present, it gets printed with the diagnostic. This option suppresses that metadata ๐-fno-diagnostics-show-highlight-colorsโ GCC can use color for emphasis and contrast when printing diagnostic messages and quoting your source. For example, in this message:
demo.c: In function `test_bad_format_string_args':
../../src/demo.c:25:18: warning: format `%i' expects argument of type `int', but argument 2 has type `const char *' [-Wformat=]
25 | printf("hello %i", msg);
| ~^ ~~~
| | |
| int const char *
| %s
- the
%iand "int" in the message, plus the "int" in the quoted source, are colored usinghighlight-a(bold green by default) โ - the "const char *" in the message and in the quoted source are both colored using
highlight-b(bold blue by default) ๐
The vibe is to draw your eyes to how the different parts of the message and the source relate, using color to group related stuff and distinguish mismatched stuff ๐ This extra colorization is enabled by default if color printing is on (per -fdiagnostics-color=), but you can turn it off separately with -fno-diagnostics-show-highlight-colors ๐จ
-fno-diagnostics-show-line-numbersโ by default, when source code is printed (via-fdiagnostics-show-caret), a left margin showing line numbers is printed. This option suppresses that left margin ๐ข-fdiagnostics-minimum-margin-width=widthโ controls the minimum width of the left margin printed by-fdiagnostics-show-line-numbers. It defaults to6๐-fdiagnostics-show-context[=depth]and-fno-diagnostics-show-contextโ with this option, the compiler might print the interesting control-flow chain that guards the basic block of the statement with the warning.depthis the maximum depth of that chain. The warning options currently affected are-Warray-bounds,-Wstringop-overflow,-Wstringop-overread,-Wstringop-truncation, and-Wrestrict. More warning options might join the list in future releases ๐ The forms-fdiagnostics-show-contextand-fno-diagnostics-show-contextare aliases for-fdiagnostics-show-context=1and-fdiagnostics-show-context=0, respectively-fdiagnostics-parseable-fixitsโ emits fix-it hints in a machine-parseable format that IDEs can gobble up ๐ค For each fix-it, a line gets printed after the relevant diagnostic, starting with the stringfix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
the location is a half-open range ๐ counted in bytes, and byte counting starts at 1 for the initial column (very precise, no notes). In the example below, bytes 3 through 20 of line 45 of "test.c" get swapped out for the new string ๐ฆ:
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape a backslash as "\\", a tab as "\t", a newline as "\n", a double quote as "\"", and non-printable characters as octal, so a vertical tab shows up as "\013" ๐
An empty replacement string means the range gets deleted ๐๏ธ, and an empty range like "45:3-45:3" means the string gets inserted right at that spot โจ
โจ -fdiagnostics-generate-patch โจ
Prints the fix-it hints to stderr in unified diff format, after all the diagnostics have been printed ๐ธ Here's what that looks like:
--- test.c
+++ test.c
@ -42,5 +42,5 @
void show_cb(GtkDialog *dlg)
{
- gtk_widget_showall(dlg);
+ gtk_widget_show_all(dlg);
}
The diff may or may not be colorized ๐, and it follows the same rules as regular diagnostics (see -fdiagnostics-color).
โจ -fdiagnostics-show-template-tree โจ
This one is for the C++ frontend ๐ When diagnostics show mismatching template types, like this:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
passing -fdiagnostics-show-template-tree turns on a tree-like structure that shows the common and differing parts of the types, like this:
map<
[...],
vector<
[double != float]>>
The parts that differ get highlighted with color, which is "double" and "float" in this case ๐ฅ
โจ -fno-elide-type โจ
By default, when the C++ frontend prints mismatching template types, the common parts get squished down to [...] so the error message stays short and sweet ๐ For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Adding -fno-elide-type turns that squishing off ๐
โโ๏ธ This flag also affects the output of -fdiagnostics-show-template-tree.
โจ -fdiagnostics-path-format=KIND โจ
This one decides how the control-flow event paths get printed for diagnostics that have one attached ๐ฆ
KIND can be none, separate-events, or inline-events, and the default is inline-events ๐
noneโ no diagnostic paths get printed at all ๐separate-eventsโ each event in the diagnostic gets its own "note" diagnostic. For example:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-eventsโ the events get printed "inline" right inside the source code ๐ง It tries to group the events into runs of close-together events and prints them as labelled ranges in the source. For example, those same events might look like this:
'test': events 1-3
25 | list = PyList_New(0);
| ^~~~~~~~~~~~~
| |
| (1) when 'PyList_New' fails, returning NULL
26 |
27 | for (i = 0; i < count; i++) {
| ~~~
| |
| (2) when 'i < count'
28 | item = PyLong_FromLong(random());
29 | PyList_Append(list, item);
| ~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
Interprocedural control flow gets shown by grouping the events by stack frame, with indentation showing how stack frames are nested, pushed, and popped ๐ For example:
'test': events 1-2
|
| 133 | {
| | ^
| | |
| | (1) entering 'test'
| 134 | boxed_int *obj = make_boxed_int (i);
| | ~~~~~~~~~~~~~~~~~~
| | |
| | (2) calling 'make_boxed_int'
|
+--> 'make_boxed_int': events 3-4
|
| 120 | {
| | ^
| | |
| | (3) entering 'make_boxed_int'
| 121 | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (4) calling 'wrapped_malloc'
|
+--> 'wrapped_malloc': events 5-6
|
| 7 | {
| | ^
| | |
| | (5) entering 'wrapped_malloc'
| 8 | return malloc (size);
| | ~~~~~~~~~~~~~
| | |
| | (6) calling 'malloc'
|
<-------------+
|
'test': event 7
|
| 138 | free_boxed_int (obj);
| | ^~~~~~~~~~~~~~~~~~~~
| | |
| | (7) calling 'free_boxed_int'
|
(etc)
โจ -fdiagnostics-show-path-depths โจ
This option adds extra info when printing the control-flow paths attached to a diagnostic ๐
If you pass it, the stack depth gets printed for each run of events within -fdiagnostics-path-format=inline-events. If you pass it together with -fdiagnostics-path-format=separate-events, then the stack depth and function declaration get tacked onto the end of each event ๐
This one is intended for GCC developers and plugin developers ๐งโ๐ป who are debugging diagnostics that report interprocedural control flow.
โจ -fno-show-column โจ
Don't print column numbers in diagnostics ๐ โโ๏ธ This might be necessary if your diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu.
โจ -fdiagnostics-column-unit=UNIT โจ
Picks the units used for the column number ๐ This affects traditional diagnostics (unless you've also passed -fno-show-column).
UNIT can be:
displayโ the default ๐ It counts the number of display columns each character takes up. That can be more than the bytes needed to encode the character (tabs, for example) or fewer (multibyte characters, for example). For instance,GREEK SMALL LETTER PI (U+03C0)takes up one display column but needs two bytes in UTF-8, andSLIGHTLY SMILING FACE (U+1F642)takes up two display columns but needs four bytes in UTF-8.byteโ the column number becomes the raw byte count in every case, which is how GCC used to output it before version 11.1.0 ๐ฐ๏ธ
โจ -fdiagnostics-column-origin=ORIGIN โจ
Picks the origin for column numbers, meaning the column number given to the very first column ๐ฏ The default value of 1 matches traditional GCC behavior and the GNU style guide. Some utilities may work better with an origin of 0, and any non-negative value is allowed.
โจ -fdiagnostics-escape-format=FORMAT โจ
When GCC prints the relevant source lines for a diagnostic, it normally tries to print the source bytes straight up ๐ But some diagnostics are about encoding problems in the source file, like malformed UTF-8 or issues with Unicode normalization. Those diagnostics get flagged so GCC escapes any bytes that aren't printable ASCII when it prints their source lines.
This option controls how those bytes get escaped ๐ซถ
FORMAT can be:
unicodeโ the default โจ Unicode characters that aren't printable ASCII show up as<U+XXXX>, and bytes that don't form a validly UTF-8-encoded Unicode character show up as hexadecimal in the form<XX>.
For example, say a source line contains before, then the Unicode character U+03C0 (GREEK SMALL LETTER PI, which is UTF-8 encoded as 0xCF 0x80), then the stray UTF-8 trailing byte 0xBF, then after. With the default, that diagnostic prints as:
before<U+03C0><BF>after
bytesโ shows every non-printable-ASCII byte as<XX>, so you can see the underlying encoding of non-ASCII Unicode characters ๐ For the example above, this prints:
before<CF><80><BF>after
โจ -fdiagnostics-text-art-charset=CHARSET โจ
Some diagnostics can include "text art" diagrams ๐จ: visualizations made out of text and meant to be viewed in a monospaced font.
This option picks which characters get used to print those diagrams, if any ๐ผ๏ธ CHARSET can be none, ascii, unicode, or emoji.
noneโ suppresses the printing of these diagrams entirely ๐asciiโ makes sure the diagrams are pure ASCII ("ASCII art") ๐งธunicodeโ allows conservative use of Unicode drawing characters, like box-drawing characters ๐ฆemojiโ adds the option of emoji too, such as emitting U+26A0WARNING SIGNfollowed by U+FE0FVARIATION SELECTOR-16to pick the emoji version of the character โ ๏ธ
The default is emoji, except when the environment variable LANG is set to C, in which case the default is ascii ๐ธ
-fno-diagnostics-show-nestingโ okay so some diagnostics are nested, like a little tree ๐ณ of sub-diagnostics, and it's usually when C++ templates get instantiated ๐. By default GCC makes these look cute with indentation and bullet points โจ, moves the location info onto its own lines so the structure is easier to read, and cuts out repeated info ๐งน. Passing-fno-diagnostics-show-nestingturns off all that indenting, reformatting, and eliding and brings back the older "look" of the diagnostics ๐ฐ๏ธ.-fno-diagnostics-show-nesting-locationsโ whenfdiagnostics-show-nestingis on, file names and line and column numbers get their own lines apart from the messages ๐. You can hide that location info completely with-fno-diagnostics-show-nesting-locations. This one is for the GCC devs writing DejaGnu test cases ๐งช, so it's not really for us, bestie ๐ซถ.-fdiagnostics-show-nesting-levelsโ whenfdiagnostics-show-nestingis on, this also prints numbers showing how deep each nesting level goes ๐ข. It's a debugging thing for GCC devs who are digging into nested diagnostics, but plugin authors might find it useful too ๐ง.-fdiagnostics-format=FORMATโ pick a different way to print diagnostics ๐.FORMATcan betext,sarif-stderr, orsarif-file. Using this replaces any extra "output sinks" added by-fdiagnostics-add-output=or set by-fdiagnostics-set-output=๐ โโ๏ธ. The default istext๐. Bothsarif-stderrandsarif-filespit out diagnostics in SARIF Version 2.1.0 format ๐ฆ, either to stderr or to a file calledsource.sarif, respectively.-fdiagnostics-add-output=DIAGNOSTICS-OUTPUT-SPECโ add an extra "output sink" for diagnostics ๐ฐ. The spec starts with a scheme, optionally followed by:and one or moreKEY=VALUEpairs, looking like this:
<SCHEME>
<SCHEME>:<KEY>=<VALUE>
<SCHEME>:<KEY>=<VALUE>,<KEY2>=<VALUE2>
etc. โจ
Heads up ๐จ: schemes, keys, or values with a name starting with "experimental" might change or get removed without notice ๐. Keys can belong to one specific scheme or be GCC-wide ๐. Here are the schemes you can use:
๐ฅ๏ธ text
Emits diagnostics to stderr using GCC's classic text output format ๐. These keys are supported for text:
color=[yes|no]โ overrides the colour settings from-fdiagnostics-colorfor this text output ๐จ.show-nesting=[yes|no]โ turns on a mode that shows the hierarchy within diagnostics, same as-fdiagnostics-show-nesting๐ณ. Defaults to "yes".show-nesting-locations=[yes|no]โ ifshow-nesting=yes, locations are shown by default ๐. Set this to "no" to hide them. Again, this is for GCC devs writing DejaGnu test cases ๐งช.show-nesting-levels=[yes|no]โ a debugging option that works withshow-nesting=yes๐. Set it to "yes" to print explicit nesting levels in the output. Also GCC-dev territory ๐ฉโ๐ป.
๐ฆ sarif
Emits diagnostics to a file in SARIF format ๐๏ธ. These keys are supported for sarif:
file=FILENAMEโ the name of the file the SARIF output gets written to, which can include a leading absolute or relative path ๐. If you don't specify it, it defaults tosource.sarif๐ .serialization=[json]โ the serialization format for writing the SARIF out ๐งพ. Right now it can only be "json", but it's there as an extension point for trying out other serializations ๐ง.version=[2.1|2.2-prerelease]โ the SARIF version for the output ๐ท๏ธ. If you don't pick one, it defaults to 2.1. "2.2-prerelease" uses an unofficial draft of the future SARIF 2.2 spec, so it should only be used for experimenting in this release ๐งช.
There's also this key meant for GCC devs, not end-users, and it can change or disappear without notice ๐:
state-graphs=[yes|no]โ a debugging feature that defaults to "no" ๐. If you set "yes", GCC tries to capture detailed state info from-fanalyzerin the generated SARIF ๐ฌ.
๐ experimental-html
Emits diagnostics to a file in HTML format ๐ป. This scheme is experimental and may go away in future GCC releases ๐ซฃ. The keys and output details can change too. These keys are supported for experimental-html:
css=[yes|no]โ adds an embedded<style>to the generated HTML ๐ . Defaults to yes.file=FILENAMEโ the name of the file the HTML output gets written to, which can include a leading absolute or relative path ๐. If you don't specify it, it defaults tosource.html๐ธ.javascript=[yes|no]โ adds an embedded<script>to the generated HTML, giving you a barebones UI for viewing results ๐ฑ๏ธ. Defaults to yes.
These keys are also for GCC devs and not end-users, and they can change or be removed without notice ๐:
show-state-diagrams=[yes|no]โ a debugging feature that defaults to "no" ๐. If you set "yes", GCC tries to usedotto make SVG diagrams in the HTML, showing the state at each event in a diagnostic path ๐บ๏ธ. You view them by pressing "j" and "k" to step forward and backward through events โฌ๏ธโฌ๏ธ. Turning this on will slow down HTML generation ๐.show-graph-dot-src=[yes|no]โ another debugging feature that defaults to "no" ๐ฌ. If you setshow-graph-dot-src=yesandshow-state-diagrams=yes, the state diagrams also show the.dotsource input to GraphViz used for the diagram ๐.show-graph-sarif=[yes|no]โ a debugging feature that defaults to "no" ๐ง . If you setshow-graph-sarif=yesandshow-state-diagrams=yes, the state diagrams also show a SARIF representation of the state ๐งฉ.
Besides the scheme-specific keys, this GCC-related key works on sinks of any scheme ๐:
cfgs=[yes|no]โ if you setcfgs=yesfor a sink, GCC tries to send info about the control flow graphs for the functions it's compiling ๐ธ๏ธ. Text sinks ignore this info. SARIF sinks add the graphs withintheRun.graphs๐. HTML sinks generate SVG showing the graphs ๐ผ๏ธ. The exact form of the info can change without notice โ ๏ธ.
Here's a cute example ๐:
-fdiagnostics-add-output=sarif:version=2.1,file=foo.2.1.sarif
-fdiagnostics-add-output=sarif:version=2.2-prerelease,file=foo.2.2.sarif
This adds a pair of outputs, each writing to a different file, using versions 2.1 and 2.2 of the SARIF standard respectively ๐ฏโโ๏ธ.
And here's the EBNF, for the nerds ๐ค:
<diagnostics-output-specifier> = <diagnostics-output-name>
| <diagnostics-output-name>, ":", <key-value-pairs>;
<diagnostics-output-name> = "text" | "sarif" | "experimental-html";
<key-value-pairs> = <key-value-pair>
| <key-value-pair> "," <key-value-pairs>;
<key-value-pair> = <key> "=" <value>;
<key> = ? string without a '=' ? ;
<value> = ? string without a ',' ? ;
-fdiagnostics-set-output=DIAGNOSTICS-OUTPUT-SPECโ this works like-fdiagnostics-add-output=, except instead of adding an extra sink ๐, it replaces all the existing output sinks ๐ฅ. That includes sinks from-fdiagnostics-format=,-fdiagnostics-add-output=, or a previous-fdiagnostics-set-output=call ๐งน.-fno-diagnostics-json-formattingโ by default, when JSON is emitted for diagnostics (via-fdiagnostics-format=sarif-stderror-fdiagnostics-format=sarif-file), GCC adds newlines and indentation so the JSON structure is easier to see ๐. Use-fno-diagnostics-json-formattingto suppress that whitespace ๐ซง. It must be passed before the option it's supposed to affect โ ๏ธ. This is meant for compatibility with tools that don't expect newlines in the output, like the output from older GCC releases ๐ฐ๏ธ.
โจ Options to Request or Suppress Warnings โจ
Warnings are diagnostic messages that report constructions that aren't inherently wrong but are risky or suggest there might have been an error โ ๏ธ. The language-independent options below don't turn on specific warnings ๐ โโ๏ธ. Instead, they control the kinds of diagnostics GCC produces ๐๏ธ.
-fsyntax-onlyโ checks the code for syntax errors and doesn't do anything beyond that ๐.-fmax-errors=nโ limits the maximum number of error messages ton๐งฑ. Once it hits that number, GCC bails out instead of trying to keep processing the source code ๐โโ๏ธ. Ifnis 0 (the default), there's no limit on how many error messages get produced โพ๏ธ. If-Wfatal-errorsis also specified,-Wfatal-errorstakes precedence over this option ๐.-w,--no-warningsโ inhibits all warning messages ๐.-Werrorโ turns all warnings into errors ๐ฅ.-Werror=โ turns the specified warning into an error ๐ฏ. You append the warning's specifier, so for example-Werror=switchturns the warnings controlled by-Wswitchinto errors ๐จ. This switch also has a negative form, which negates-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐ซถ.
The warning message for each controllable warning includes the option that controls it ๐ท๏ธ. You can then use that option with -Werror= and -Wno-error= like described above ๐. (Printing the option in the warning message can be disabled with the -fno-diagnostics-show-option flag ๐.)
Note that specifying-Werror=fooautomatically implies-Wfoo๐ . However,-Wno-error=foodoes not imply anything ๐ โโ๏ธ.
-Wfatal-errorsโ okay bestie, this one is a whole mood ๐ It makes the compiler stop dead at the very first error it finds, instead of pushing on and spamming you with more error messages.
You can ask for loads of specific warnings with options that start with -W, like -Wunused-variable to get warnings about declarations of variables that never get used ๐ Every one of these also has a negative form starting with -Wno- that turns the warning off, so -Wno-unused-variable is the opposite. This manual only lists one of the two forms, whichever one isn't the default ๐ธ For more language-specific stuff, check out C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. Extra warnings can also come from turning on the static analyzer;
Some options, like -Wall and -Wextra, switch on other options, like -Wunused, which might switch on even more, like -Wunused-variable. Positive and negative forms combine so that more specific options beat less specific ones, no matter where they sit on the command line. For options that are equally specific, the last one wins โจ Options turned on or off with pragmas act as if they were at the very end of the command line ๐ง
When you request an unrecognized warning (e.g., -Wunknown-warning), GCC throws an error saying the option isn't recognized. The -Wno- form is chiller, though: no diagnostic gets produced for -Wno-unknown-warning unless other diagnostics are being produced anyway. That lets you use new -Wno- options with old compilers, but if something goes sideways, the compiler warns that an unrecognized option is present ๐
The effectiveness of some warnings depends on optimizations also being enabled. For example, -Wsuggest-final-types is more effective with link-time optimization. Some other warnings won't be issued at all unless optimization is on. Optimization in general makes warnings about control and data-flow problems better, but in some cases it can also cause false positives ๐ซถ
-Wpedantic,-pedantic,--pedanticโ issue all the warnings strict ISO C and ISO C++ demand, diagnose every program that uses forbidden extensions, and some other programs that don't follow ISO C and ISO C++ either. This follows whichever version of the ISO C or C++ standard you pick with any-stdoption ๐
Valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few need -ansi or a -std option naming the version of the standard). Without this option, certain GNU extensions and traditional C and C++ features are supported too. With this option, they get diagnosed (or rejected with -pedantic-errors).
-Wpedantic doesn't cause warnings for use of the alternate keywords whose names begin and end with __. That alternate format can also disable warnings for non-ISO __intN types, i.e. __intN__. Pedantic warnings are also disabled in the expression that follows __extension__. However, only system header files should use these escape routes; application programs should avoid them ๐ซ
Some warnings about non-conforming programs are controlled by options other than -Wpedantic. In many cases they're implied by -Wpedantic but can be disabled separately by their specific option, e.g. -Wpedantic -Wno-pointer-sign.
Where the standard given with -std is a GNU extended dialect of C, such as gnu90 or gnu99, there's a corresponding base standard: the version of ISO C that the GNU extended dialect is based on. Warnings from -Wpedantic are given where the base standard requires them. (It wouldn't make sense for these warnings to only cover features outside the specified GNU C dialect, since by definition the GNU dialects include every feature the compiler supports with the given option, so there'd be nothing to warn about ๐คท)
-pedantic-errors,--pedantic-errorsโ give an error whenever the base standard (see-Wpedantic) requires a diagnostic, in some cases where there's undefined behavior at compile time, and in some other cases that don't prevent compilation of programs that are valid according to the standard. ๐จ
This is not equivalent to -Werror=pedantic: the latter is unlikely to be useful, because it only turns errors of the diagnostics controlled by -Wpedantic into errors. This option also affects required diagnostics that are always enabled or controlled by options other than -Wpedantic.
If you want the required diagnostics that are warnings by default to be errors instead, but don't also want to enable the -Wpedantic diagnostics, you can specify -pedantic-errors -Wno-pedantic (or -pedantic-errors -Wno-error=pedantic to enable them but only as warnings).
Some required diagnostics are errors by default, but can be reduced to warnings using -fpermissive or their specific warning option, e.g. -Wno-error=narrowing.
Some diagnostics for non-ISO practices are controlled by specific warning options other than -Wpedantic, but are also made errors by -pedantic-errors. For instance: -Wattributes (for standard attributes), -Wchanges-meaning (C++), -Wcomma-subscript (C++23 or later), -Wdeclaration-after-statement (C90 or earlier), -Welaborated-enum-base (C++11 or later), -Wimplicit-int (C99 or later), -Wimplicit-function-declaration (C99 or later), -Wincompatible-pointer-types, -Wint-conversion, -Wlong-long (C90 or earlier), -Wmain, -Wnarrowing (C++11 or later), -Wpointer-arith, -Wpointer-sign, -Wincompatible-pointer-types, -Wregister (C++17 or later), -Wvla (C90 or earlier), -Wwrite-strings (C++11 or later)
-fpermissiveโ downgrades some required diagnostics about nonconformant code from errors to warnings, so it lets some nonconforming code compile. ๐ Some C++ diagnostics are controlled only by this flag, but it also downgrades some C and C++ diagnostics that have their own flag:-Wabbreviated-auto-in-template-arg(C++ and Objective-C++ only),-Wdeclaration-missing-parameter-type(C and Objective-C only),-Wimplicit-function-declaration(C and Objective-C only),-Wimplicit-int(C and Objective-C only),-Wincompatible-pointer-types(C and Objective-C only),-Wint-conversion(C and Objective-C only),-Wnarrowing(C++ and Objective-C++ only),-Wreturn-mismatch(C and Objective-C only),-Wtemplate-body(C++ and Objective-C++ only)
The -fpermissive option is the default for the historic C language modes (-std=c89, -std=gnu89, -std=c90, -std=gnu90) ๐ฆ
-Wall,--all-warningsโ this enables all the warnings about constructions that some users consider questionable and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. It also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options ๐
-Wall turns on the following warning flags:
-Waddress -Waligned-new (C++ and Objective-C++ only) -Warray-bounds=1 (only with -O2) -Warray-compare -Warray-parameter=2 -Wbool-compare -Wbool-operation -Wc++11-compat -Wc++14-compat -Wc++17compat -Wc++20compat -Wcatch-value (C++ and Objective-C++ only) -Wchar-subscripts -Wclass-memaccess (C++ and Objective-C++ only) -Wcomment -Wdangling-else -Wdangling-pointer=2 -Wdelete-non-virtual-dtor (C++ and Objective-C++ only) -Wduplicate-decl-specifier (C and Objective-C only) -Wenum-compare (in C/ObjC; this is on by default in C++) -Wenum-int-mismatch (C and Objective-C only) -Wformat=1 -Wformat-contains-nul -Wformat-diag -Wformat-extra-args -Wformat-overflow=1 -Wformat-truncation=1 -Wformat-zero-length -Wframe-address -Wimplicit (C and Objective-C only) -Wimplicit-function-declaration (C and Objective-C only) -Wimplicit-int (C and Objective-C only) -Winfinite-recursion -Winit-self (C++ and Objective-C++ only) -Wint-in-bool-context -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++) -Wmismatched-dealloc -Wmismatched-new-delete (C++ and Objective-C++ only) -Wmissing-attributes -Wmissing-braces (only for C/ObjC) -Wmultistatement-macros -Wnarrowing (C++ and Objective-C++ only) -Wnonnull -Wnonnull-compare -Wopenmp-simd (C and C++ only) -Woverloaded-virtual=1 (C++ and Objective-C++ only) -Wpacked-not-aligned -Wparentheses -Wpessimizing-move (C++ and Objective-C++ only) -Wpointer-sign (only for C/ObjC) -Wrange-loop-construct (C++ and Objective-C++ only) -Wreorder (C++ and Objective-C++ only) -Wrestrict -Wreturn-type -Wself-move (C++ and Objective-C++ only) -Wsequence-point -Wsign-compare (C++ and Objective-C++ only) -Wsizeof-array-div -Wsizeof-pointer-div -Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtautological-compare -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused -Wunused-but-set-variable -Wunused-const-variable=1 (only for C/ObjC) -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-value -Wunused-variable -Wuse-after-free=2 -Wvla-parameter -Wvolatile-register-var -Wzero-length-bounds
Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally don't consider questionable, but which you might occasionally want to check for. Others warn about constructions that are necessary or hard to avoid in some cases, and there's no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra, but many must be enabled individually ๐ง
-Wextra,--extra-warningsโ enables some extra warning flags that aren't enabled by-Wall. (This option used to be called-W. The older name is still supported, but the newer name is more descriptive ๐)
okay so the warning squad is still coming in hot ๐ฅ here's the rest of the -W lineup, and yes, I'm obsessed ๐
-Wabsolute-value(only for C/ObjC) โจ-Walloc-size๐ธ-Wcalloc-transposed-args๐ฆ-Wcast-function-type๐-Wclobbered๐ง-Wdangling-reference(C++ only) ๐-Wdeprecated-copy(C++ and Objective-C++ only) ๐ซถ-Wempty-body๐-Wenum-conversion(only for C/ObjC) ๐-Wexpansion-to-definedโญ-Wignored-qualifiers(only for C/C++) ๐-Wimplicit-fallthrough=3๐ฅ-Wmaybe-uninitialized๐-Wmissing-field-initializers๐-Wmissing-parameter-name(C/ObjC only) ๐-Wmissing-parameter-type(C/ObjC only) โจ-Wold-style-declaration(C/ObjC only) ๐-Wmultiple-parameter-fwd-decl-lists(C/ObjC only) ๐-Woverride-init(C/ObjC only) ๐ฆ-Wredundant-move(C++ and Objective-C++ only) ๐-Wshift-negative-value(in C++11 to C++17 and in C99 and newer) ๐ง-Wsign-compare(C++ and Objective-C++ only) ๐-Wsized-deallocation(C++ and Objective-C++ only) ๐ซถ-Wstring-compare๐ธ-Wtype-limits๐-Wuninitializedโญ-Wunterminated-string-initialization(C/ObjC only) ๐ญ-Wunused-parameter(only with-Wunusedor-Wall) ๐-Wunused-but-set-parameter(only with-Wunusedor-Wall) ๐
ngl -Wextra gets a bonus round ๐ it also flags these cases:
- A pointer is compared against integer zero with
<,<=,>, or>=๐ - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression ๐
- (C++ only) Ambiguous virtual bases ๐
- (C++ only) Subscripting an array that has been declared
register๐ญ - (C++ only) Taking the address of a variable that has been declared
register๐ซถ - (C++ only) A base class is not initialized in the copy constructor of a derived class โจ
๐ -Wabi (C, Objective-C, C++ and Objective-C++ only)
okay so -Wabi is the one that yells when your code gets hit by ABI changes ๐ญ That includes code that might not be compatible with the vendor-neutral C++ ABI, plus the psABI for your particular target. The psABI warnings have their own switch, -Wpsabi, and -Wabi implies it ๐ซถ
Since G++ now defaults to updating the ABI with each major release, -Wabi usually only warns about C++ ABI compatibility problems when a check got added later in a release series for an ABI issue found after the initial release ๐
But if you pick an older ABI version with -fabi-version=n, -Wabi gets way more chatty ๐
You can also give -Wabi an explicit version number, like -Wabi=2, to check C++ ABI compatibility against a particular -fabi-version level. So -Wabi=2 warns about changes relative to -fabi-version=2 ๐ฆ
If you give an explicit version number and don't set -fabi-compat-version, that number is used for compatibility aliases. If you skip the number on this option but DO set -fabi-compat-version, that version is used for C++ ABI warnings instead ๐ธ
Real talk: they tried to catch every case ๐ฅบ but there are probably some sneaky ones that slip through even when G++ is generating incompatible code. And sometimes you'll get warnings even though the generated code is totally compatible. Not ideal, but that's life ๐
If you're worried that G++ output might not be binary compatible with code from other compilers, bestie, you should rewrite your code to dodge these warnings ๐
Known incompatibilities in -fabi-version=2 (the default from GCC 3.4 to 4.9) include:
- A template with a non-type template parameter of reference type was mangled incorrectly ๐ญ
extern int N;
template <int &> struct S {};
void n (S<N>) {2}
This was fixed in -fabi-version=3 โ
- SIMD vector types declared using
__attribute ((vector_size))were mangled in a non-standard way that does not allow for overloading of functions taking vectors of different sizes ๐
The mangling was changed in -fabi-version=4 โ
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration was folded away ๐
These mangling issues were fixed in -fabi-version=5 โ
- Scoped enumerators passed as arguments to a variadic function are promoted like unscoped enumerators, causing
va_argto complain. On most targets this does not actually affect the parameter passing ABI, as there is no way to pass an argument smaller thanint๐ค
Also, the ABI changed the mangling of template argument packs, const_cast, static_cast, prefix increment/decrement, and a class scope function used as a template argument.
These issues were corrected in -fabi-version=6 โ
- Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t๐
These issues were corrected in -fabi-version=7 โ
- When mangling a function type with function-cv-qualifiers, the un-qualified function type was incorrectly treated as a substitution candidate ๐คฏ
This was fixed in -fabi-version=8, the default for GCC 5.1 โ
decltype(nullptr)incorrectly had an alignment of 1, leading to unaligned accesses. Note that this did not affect the ABI of a function with anullptr_tparameter, as parameters have a minimum alignment ๐ซ
This was fixed in -fabi-version=9, the default for GCC 5.2 โ
- Target-specific attributes that affect the identity of a type, such as ia32 calling conventions on a function type (stdcall, regparm, etc.), did not affect the mangled name, leading to name collisions when function pointers were used as template arguments ๐ฅ
This was fixed in -fabi-version=10, the default for GCC 6.1 โ
๐ฆ -Wpsabi (C, Objective-C, C++ and Objective-C++ only)
-Wpsabi enables warnings about processor-specific ABI changes, like changes in alignment requirements or how function arguments get passed ๐ง On several targets, including AArch64, ARM, x86, MIPS, RS6000/PowerPC, and S/390, these details have changed between different GCC versions and/or different versions of the C or C++ language standards, in ways that affect binary compatibility of compiled code ๐ตโ๐ซ With -Wpsabi, GCC can detect potentially incompatible usages and warn you about them ๐
-Wpsabi is enabled by default, and is also implied by -Wabi โจ
๐ -Wno-changes-meaning (C++ and Objective-C++ only)
C++ requires that unqualified uses of a name within a class have the same meaning in the complete scope of the class, so declaring the name after using it is ill-formed ๐ โโ๏ธ
struct A;
struct B1 { A a; typedef A A; }; // warning, 'A' changes meaning
struct B2 { A a; struct A { }; }; // error, 'A' changes meaning
By default, the B1 case is only a warning because the two declarations have the same type, while the B2 case is an error. Both diagnostics can be disabled with -Wno-changes-meaning. Alternately, the error case can be reduced to a warning with -Wno-error=changes-meaning or -fpermissive ๐ง
Both diagnostics are also suppressed by -fms-extensions ๐ธ
๐ -Wchar-subscripts
This warns if an array subscript has type char ๐ญ It's a super common mistake because people forget that char is signed on some machines. This warning is enabled by -Wall โ
๐ -Wno-coverage-mismatch
This warns if feedback profiles don't match when you use the -fprofile-use option. If a source file gets changed between compiling with -fprofile-generate and with -fprofile-use, the files with the profile feedback can fail to match the source file, and then GCC can't use the profile feedback information ๐ฅบ By default, this warning is enabled and is treated as an error. -Wno-coverage-mismatch can disable the warning, or -Wno-error=coverage-mismatch can disable the error ๐
Disabling the error for this warning can result in poorly optimized code. It's only useful for very minor changes, like bug fixes to an existing code-base. Completely disabling the warning is not recommended ๐ซ
๐ -Wno-coverage-too-many-conditions
This warns if -fcondition-coverage is used and an expression has too many terms, so GCC gives up on coverage. Coverage gets given up when there are more terms in the conditional than there are bits in a gcov_type_unsigned ๐คฏ This warning is enabled by default โ
๐ง -Wno-coverage-too-many-paths
This warns if -fpath-coverage is used and a function has too many paths, so GCC gives up on coverage. Giving up is controlled by -fpath-coverage-limit. This warning is enabled by default โ
๐ -Wno-coverage-invalid-line-number
This warns in case a function ends earlier than it begins because of invalid linenum macros ๐ซ The warning is only emitted with --coverage enabled.
By default, this warning is enabled and is treated as an error. -Wno-coverage-invalid-line-number can disable the warning, or -Wno-error=coverage-invalid-line-number can disable the error ๐
๐ธ -Wno-cpp (C, Objective-C, C++, Objective-C++ and Fortran only)
This suppresses warning messages emitted by #warning directives ๐คซ
๐ -Wdouble-promotion (C, C++, Objective-C and Objective-C++ only)
Okay this one is so sneaky ๐ญ It gives a warning when a value of type float is implicitly promoted to double. CPUs with a 32-bit single-precision floating-point unit implement float in hardware, but emulate double in software. On a machine like that, doing computations with double values is much more expensive because of the overhead required for software emulation ๐ข
It's super easy to accidentally do computations with double, because floating-point literals are implicitly of type double. For example, in:
float area(float radius)
{
return 3.14159 * radius * radius;
}
the compiler performs the entire computation with double because the floating-point literal is a double ๐
๐ซถ -Wduplicate-decl-specifier (C and Objective-C only)
This warns if a declaration has a duplicate const, volatile, restrict or _Atomic specifier ๐ This warning is enabled by -Wall โจ
-Wformat,-Wformat=nโ okay so this one is the format police ๐ฎโโ๏ธโจ It checks your calls toprintfandscanf(and their crew) to make sure the arguments you pass actually match the types the format string asks for, and that the conversions in the format string make sense. That includes the standard functions plus anything tagged with format attributes, across theprintf,scanf,strftimeandstrfmon(an X/Open extension, not in the C standard) families, or other target-specific families. Which functions get checked without a format attribute depends on the standard version you picked, and those checks get turned off by-ffreestandingor-fno-builtin. ๐ซถ
The formats get checked against the format features supported by GNU libc version 2.2. That covers all ISO C90 and C99 features, plus stuff from the Single Unix Specification and some BSD and GNU extensions. Other library implementations might not support all of these, and GCC won't warn you about features that go beyond a particular library's limits. ๐คทโโ๏ธ BUT if you use -Wpedantic together with -Wformat, you'll get warnings about format features that aren't in the selected standard version (just not for strfmon formats, since those aren't in any version of the C standard).
-Wformat=1,-Wformatโ-Wformatis the same thing as-Wformat=1, and-Wno-formatis the same as-Wformat=0. ๐ Since-Wformatalso checks for null format arguments in several functions, it implies-Wnonnulltoo. Some bits of this level can be switched off with-Wno-format-contains-nul,-Wno-format-diag,-Wno-format-extra-args, and-Wno-format-zero-length. And yes,-Wformatis enabled by-Wall๐ธ-Wformat=2โ level up! โญ This turns on-Wformatplus additional format checks. Right now it's the same as-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k. Iconic behaviour, no notes.
-Wno-format-contains-nulโ if you've got-Wformaton, this tells GCC to chill and not warn about format strings that contain NUL bytes. ๐-Wno-format-diagโ if-Wformatis on, this stops GCC from warning about format strings that aren't suitable for GCC's own diagnostics. ๐ฆ-Wno-format-extra-argsโ if-Wformatis on, GCC won't yell about excess arguments to aprintforscanfformat function. The C standard says those extra arguments just get ignored, so it's not really a crime ๐
Where the unused arguments sit between used arguments that use $ operand number specifications, GCC will normally still warn you anyway. The reason is that the implementation can't know what type to hand to va_arg to skip the unused ones. HOWEVER, for scanf formats, this option does suppress the warning if the unused arguments are all pointers, because the Single Unix Specification says those unused pointer arguments are allowed. โจ
-Wformat-overflow,-Wformat-overflow=levelโ okay this one is giving buffer-safety vibes ๐ง It warns about calls to formatted I/O functions likesprintfandvsprintfthat might overflow the destination buffer. When GCC can't work out exactly how many bytes a format directive writes at compile time, it guesses using heuristics that depend on the level and on optimization. Turning on optimization usually makes the warning more accurate, but it can also cause false positives. ๐ญ-Wformat-overflow=1,-Wformat-overflowโ level 1 is enabled by-Wformatand is the cautious one. It only warns about calls that will most likely overflow the buffer. At this level, numeric arguments to format directives with unknown values are assumed to be one, and strings of unknown length are assumed to be empty. Numeric arguments known to be bounded to a subrange of their type, or string arguments whose output is bounded by the directive's precision or by a finite set of string literals, are assumed to take whatever value in that range produces the most output bytes. For example, thesprintfcall below gets diagnosed because even with bothaandbequal to zero, the terminating NUL character ('\0') that the function appends to the destination buffer gets written past its end. Making the buffer one byte bigger is enough to dodge the warning, though it might not be enough to dodge the actual overflow. ๐
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
-Wformat-overflow=2โ level 2 warns about calls that might overflow the destination buffer given an argument of sufficient length or magnitude. ๐ฅ At level 2, unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments that can't be assumed to be bounded by the directive's precision, by a finite set of string literals they might evaluate to, or by the character array they might point to, are assumed to be 1 character long. At this level, the example above gets diagnosed again, but this time because withaequal to a 32-bitINT_MIN, the first%idirective will write some of its digits past the end of the destination buffer. To make the call safe no matter what the two variables are, the destination buffer needs to be at least 34 bytes. GCC even includes the minimum buffer size in an informational note after the warning. Helpful, bestie ๐
An alternative to making the buffer bigger is to constrain the formatted values. You can bound the maximum length of string arguments by specifying the precision in the format directive. And when numeric arguments can be assumed to be bounded by less than the precision of their type, picking an appropriate length modifier for the specifier will shrink the required buffer size. For example, if a and b in the example above can be assumed to be within the precision of the short int type, then using either the %hi format directive or casting the argument to short brings the maximum required buffer size down to 24 bytes. โจ
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
-Wno-format-zero-lengthโ if-Wformatis specified, GCC won't warn about zero-length formats. The C standard says zero-length formats are allowed, so this one is valid, no cap ๐งธ-Wformat-nonliteralโ if-Wformatis specified, GCC will also warn if the format string isn't a string literal, since that means it can't be checked. The exception is when the format function takes its format arguments as ava_list. ๐-Wformat-securityโ if-Wformatis specified, this also warns about uses of format functions that could be security problems. Right now it warns about calls toprintfandscanffunctions where the format string isn't a string literal and there are no format arguments, likeprintf (foo);. That can be a security hole if the format string came from untrusted input and contains%n. ๐จ (This is currently a subset of what-Wformat-nonliteralwarns about, but future warnings might be added to-Wformat-securitythat aren't included in-Wformat-nonliteral.)-Wformat-signednessโ if-Wformatis specified, this also warns if the format string needs an unsigned argument and you pass a signed one, and vice versa. ๐ฆข-Wformat-truncation,-Wformat-truncation=levelโ this one is the truncation watcher ๐ It warns about calls to formatted I/O functions likesnprintfandvsnprintfthat might cut off the output. Same deal as-Wformat-overflow: if the exact byte count can't be known at compile time, GCC estimates it with heuristics that depend on the level and on optimization. Optimization usually helps accuracy, but might also cause false positives. Unless noted otherwise, it uses the same logic as-Wformat-overflow.-Wformat-truncation=1,-Wformat-truncationโ level 1 is enabled by-Wformatand is the careful version. It only warns about calls to bounded functions whose return value is unused and that will most likely result in truncated output. ๐-Wformat-truncation=2โ level 2 also warns about calls to bounded functions whose return value is used and that might truncate the output, given an argument of sufficient length or magnitude. ๐ธ
-Wformat-y2kโ if-Wformatis specified, this also warns aboutstrftimeformats that may only yield a two-digit year. Y2K energy, and not the good kind ๐-Wnonnullโ warns about passing a null pointer for arguments that thenonnullfunction attribute says must be non-null. ๐ โโ๏ธ-Wnonnullis included in-Walland-Wformat, and you can turn it off with-Wno-nonnull.-Wnonnull-compareโ warns when you compare an argument marked with thenonnullfunction attribute against null inside the function. ๐คจ-Wnonnull-compareis included in-Wall, and it can be disabled with-Wno-nonnull-compare.-Wnull-dereferenceโ warns if the compiler detects paths that trigger erroneous or undefined behavior because a null pointer gets dereferenced. โ ๏ธ This option only works when-fdelete-null-pointer-checksis active, which optimizations turn on for most targets. How precise the warnings are depends on the optimization options you use.-Wno-musttail-local-addrโ don't warn about passing a pointer (or, in C++, a reference) to a local variable or label as an argument to amusttailcall. Those variables go out of scope before the tail call instruction, so this is the "I know what I'm doing" switch ๐ฆ-Wmaybe-musttail-local-addrโ warns when the address of a local variable can escape to amusttailcall, unless the variable already goes out of scope before themusttailcall. Main-character warning for your pointers ๐
int foo (int *);
int
bar (int *x)
{
if (x[0] == 1)
{
int a = 42;
foo (&a);
/* Without the C<musttail> attribute this call would not
be tail called, because address of the C<a> variable escapes
and the second foo call could dereference it. With the attribute
the local variables are assumed to go out of scope immediately
before the tail call instruction and the compiler warns about
this. */
[[gnu::musttail]] return foo (nullptr);
}
else
{
{
int a = 42;
foo (&a);
}
/* The C<a> variable isn't already in scope, so even when it
escaped, even without C<musttail> attribute it would be
undefined behavior to dereference it and the compiler could
turn this into a tail call. No warning is diagnosed here. */
[[gnu::musttail]] return foo (nullptr);
}
}
This warning is enabled by -Wextra. โจ
๐ -Wnrvo (C++ and Objective-C++ only)
okay so this one is all about the Named Return Value Optimization (aka NRVO) ๐ It warns when the compiler doesn't skip copying a local variable into the return value, even though [class.copy.elision] says it's allowed to. The compiler could do it, it just didn't, and this flag lets you know. ๐ซถ
Here's the example. The compiler can't skip the copy from both v1 and v2, so it skips neither. ๐
std::vector<int> f()
{
std::vector<int> v1, v2;
// ...
if (cond) return v1;
else return v2; // warning: not eliding copy
}
๐ธ -Winfinite-recursion
Warns about infinitely recursive calls, and it's giving main character energy because it works at all optimization levels ๐ฅ Heads up though, catching infinite recursion between two or more functions needs optimization turned on. -Winfinite-recursion is included in -Wall. ๐
Compare this with -Wanalyzer-infinite-recursion, which gives a similar diagnostic but is implemented in a different way (as part of -fanalyzer). ๐ง
๐ฆ -Winit-self (C, C++, Objective-C and Objective-C++ only)
This one warns about uninitialized variables that get initialized with themselves ๐ Note that this option can only be used with the -Wuninitialized option.
GCC warns about "i" being uninitialized in the following snippet only when -Winit-self has been specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++. ๐
๐
-Wno-implicit-int (C and Objective-C only)
This option controls warnings when a declaration doesn't specify a type. It's enabled by default, as an error, in C99 and later dialects of C, and also by -Wall. You can downgrade the error to a warning with -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=implicit-int. ๐ซถ
This warning gets upgraded to an error by -pedantic-errors. ๐ญ
๐ -Wno-implicit-function-declaration (C and Objective-C only)
This option controls warnings when a function is used before it's declared. It's enabled by default, as an error, in C99 and later dialects of C, and also by -Wall. You can downgrade it to a warning with -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=implicit-function-declaration. ๐
Yep, -pedantic-errors upgrades this one to an error too. ๐
๐ -Wimplicit (C and Objective-C only)
Same as -Wimplicit-int and -Wimplicit-function-declaration. It's enabled by -Wall. โจ
๐ฅ -Whardened
This one warns when -fhardened didn't enable an option from its set (see -fhardened for the full lineup). For example, if you use -fhardened and -fstack-protector at the same time on the command line, -Whardened will warn, because -fstack-protector-strong won't be enabled by -fhardened. ๐ก๏ธ
It's enabled by default, and it only has an effect when -fhardened is enabled. ๐ธ
๐ง -Wimplicit-fallthrough
-Wimplicit-fallthrough is the same as -Wimplicit-fallthrough=3, and -Wno-implicit-fallthrough is the same as -Wimplicit-fallthrough=0. ๐ฆ
๐ซง -Wimplicit-fallthrough=n
okay so this warns when a switch case falls through ๐ For example:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
It does not warn when the last statement of a case can't fall through, like when there's a return statement or a call to a function declared with the noreturn attribute. ๐
This also takes control flow statements into account, such as ifs, and it only warns when it's appropriate. E.g.
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a case fall through is totally intentional, so GCC gives you an attribute, __attribute__ ((fallthrough)), to be used along with a null statement to suppress the warning that would normally happen:
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
In C++17 and C23 there's a standard way to do this using [[fallthrough]]; instead of the GNU attribute. In C++11 or C++14 you can use [[gnu::fallthrough]];, which is a GNU extension. โจ Instead of these attributes, you can also add a fallthrough comment to silence the warning. The whole body of the C or C++ style comment has to match the regular expressions listed below. The option argument n decides which kind of comments are accepted:
-Wimplicit-fallthrough=0disables the warning altogether. ๐ซ-Wimplicit-fallthrough=1matches".*"regular expression, so any comment counts as a fallthrough comment. ๐ฌ-Wimplicit-fallthrough=2case insensitively matches".*falls?[ \t-]*thr(ough|u).*"regular expression. ๐-Wimplicit-fallthrough=3case sensitively matches one of the following regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4case sensitively matches one of the following regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5doesn't recognize any comments as fallthrough comments, so only attributes disable the warning. ๐
The comment has to be followed, after optional whitespace and other comments, by a case or default keyword, or by a user label that comes right before some case or default label. ๐
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is enabled by -Wextra. ๐
๐ -Wno-if-not-aligned (C, C++, Objective-C and Objective-C++ only)
This controls whether warnings triggered by the warn_if_not_aligned attribute get issued. These warnings are enabled by default. ๐ซง
๐ -Wignored-qualifiers (C and C++ only)
Warns if a function's return type has a type qualifier such as const. In ISO C, that qualifier has no effect, since the value returned by a function isn't an lvalue. In C++, the warning is only emitted for scalar types or void. ISO C prohibits qualified void return types on function definitions, so those always get a warning, even without this option. ๐ญ
This warning is also enabled by -Wextra. โจ
๐ -Wno-ignored-attributes (C and C++ only)
This option controls warnings when an attribute is ignored. It's different from the -Wattributes option, because it warns whenever the compiler decides to drop an attribute, not when the attribute is unknown, used in the wrong place, and so on. This warning is enabled by default. ๐ธ
๐ -Wmain
Warns if the type of main is suspicious. main should be a function with external linkage, returning int, taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++, and it's also enabled by either -Wall or -Wpedantic. ๐
Upgraded to an error by -pedantic-errors. ๐
๐ง -Wmisleading-indentation (C and C++ only)
Warns when the indentation of the code doesn't match the block structure. Specifically, a warning is issued for if, else, while, and for clauses with a guarded statement that doesn't use braces, followed by an unguarded statement with the same indentation. ๐ซฃ
In the following example, the call to bar is misleadingly indented as if it were guarded by the if conditional:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
With mixed tabs and spaces, the warning uses the -ftabstop= option to figure out whether the statements line up (it defaults to 8). ๐
The warning is not issued for code involving multiline preprocessor logic, such as the following example:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
Okay so the warning is not issued after a #line directive ๐ That usually means the code was autogenerated, and nobody can assume anything about the layout of the file the directive points to. Respect the vibe.
This warning is enabled by -Wall in C and C++ โจ
-Wmissing-attributesโ bestie, this one flags a function declaration that's missing an attribute a related function was declared with, when that absence could hurt the correctness or efficiency of the generated code ๐ The classic example is an alias that uses attributes to ask for less strict stuff than its target. That's basically a potential optimization opportunity. The flip side is-Wattribute-alias=2, which warns when the alias is more restrictive than the target, and that one can lead to incorrect code generation ๐ญ The attributes it keeps an eye on are "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc", "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull", and "returns_twice".
In C++, it warns when an explicit specialization of a primary template is declared without one of these attributes: "alloc_align", "alloc_size", "assume_aligned", "format", "format_arg", "malloc", or "nonnull". The attributes "deprecated", "error", and "warning" suppress the warning.. ๐
You can use the "copy" attribute to slap the same set of attributes onto a declaration as another declaration has, without listing them all out. It works on declarations of functions, variables, or types. Peep Common Attributes too ๐
-Wmissing-attributes is enabled by -Wall.
Like, since the primary function template below uses both "malloc" and "alloc_size", the explicit specialization gets flagged because it's missing one of them ๐
template <class T> T* __attribute__ ((malloc, alloc_size (1))) allocate (size_t);
template <> void* __attribute__ ((malloc)) // missing alloc_size allocate<void> (size_t);
-Wmissing-bracesโ warns when an aggregate or union initializer isn't fully bracketed ๐ง In this example,ais not fully bracketed, butbis, and that's the whole difference ๐
int a[2][2] = { 0, 1, 2, 3 }; int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall.
-Wmissing-include-dirs(C, C++, Objective-C, Objective-C++ and Fortran only) โ warns if a user-supplied include directory doesn't exist ๐ It's off by default for C, C++, Objective-C and Objective-C++. For Fortran, it's partially on by default, but only for-Iand-J๐ธ-Wno-missing-profileโ this one is about feedback profiles going missing when you use-fprofile-useโจ It calls out cases where a new function or a new file got added between-fprofile-generateand-fprofile-usewithout regenerating the profiles. The profile feedback data files then have no info for that new function or file. Also, if profile count data (.gcda) files get deleted, GCC can't use any profile feedback info at all. In all these cases you get a warning telling you a profile generation step is due ๐ฅบ Ignoring it can leave you with poorly optimized code.
-Wno-missing-profile can turn the warning off, but that's not recommended ๐ซ Only do it when having non-existent profile data is actually justified.
-Wmismatched-deallocโ warns on calls to deallocation functions that get pointer arguments returned from allocation functions the former isn't a suitable deallocator for ๐ฅ You can pair up matching allocators and deallocators with themallocattribute. Unless-fno-builtinis in play, the standard "calloc", "malloc", "realloc", and "free" are implicitly paired up, same goes for C++ "operator new" and "operator delete" ๐ซถ In the example, "mydealloc" is the deallocator for pointers from "myalloc".
void mydealloc (void*);
__attribute__ ((malloc (mydealloc, 1))) void* myalloc (size_t);
void f (void) { void *p = myalloc (32); // ...use p... free (p); // warning: not a matching deallocator for myalloc mydealloc (p); // ok }
In C++, the related option -Wmismatched-new-delete catches mismatches involving either "operator new" or "operator delete" ๐
-Wmismatched-dealloc is included in -Wall.
-Wmultistatement-macrosโ warns about sketchy multiple statement macros that look guarded by something like "if", "else", "for", "switch", or "while", where only the first statement actually ends up guarded once the macro expands ๐
#define DOIT x++; y++ if (c) DOIT;
This will increment "y" unconditionally, not just when "c" holds ๐ฑ It can usually be fixed by wrapping the macro in a do-while loop:
#define DOIT do { x++; y++; } while (0) if (c) DOIT;
This warning is enabled by -Wall in C and C++.
-Wparenthesesโ warns when parentheses get left out in certain spots ๐ Like when there's an assignment where a truth value is expected, or when operators are nested in a way people often get mixed up about.
It also warns if you write something like x<=y<=z. That's equivalent to (x<=y ? 1 : 0) <= z, which is a totally different reading from normal math notation ๐คฏ
It warns for dangerous uses of the GNU extension to ?: with the middle operand omitted. When the condition in the ?: operator is a boolean expression, the omitted value is always 1. Programmers often expect it to be a value computed inside the conditional expression instead, so this is a major vibe check ๐ฉ
For C++, this also warns about some unnecessary parentheses in declarations, which can mean someone was trying to make a function call instead of a declaration:
{ // Declares a local variable called mymutex. std::unique_lock<std::mutex> (mymutex); // User meant std::unique_lock<std::mutex> lock (mymutex); }
This warning is enabled by -Wall.
-Wno-self-move(C++ and Objective-C++ only) โ this warns when a value is moved to itself with "std::move" ๐ฆ That kind of "std::move" typically does nothing at all.
struct T { ... }; void fn() { T t; ... t = std::move (t); }
This warning is enabled by -Wall.
-Wsequence-pointโ warns about code that might have undefined semantics because it breaks the sequence point rules in the C and C++ standards ๐ Okay this one is a lot, so bear with me ๐ซ
The standards define the order expressions get evaluated in using sequence points, which are a partial ordering between parts of the program: stuff executed before the sequence point, and stuff executed after it. They happen after a full expression is evaluated (one that isn't part of a larger expression), after the first operand of a "&&", "||", "? :" or "," (comma) operator is evaluated, before a function is called (but after its arguments and the expression naming the called function are evaluated), and in some other places too. Apart from what the sequence point rules say, the order subexpressions get evaluated in isn't specified. These rules only give a partial order, not a total one. For example, if two functions get called in one expression with no sequence point between them, the order of those calls isn't specified. However, the standards committee has ruled that function calls do not overlap ๐
It isn't specified when, between sequence points, changes to object values take effect. Programs that depend on that have undefined behavior. The C and C++ standards say that "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.". If a program breaks these rules, results on any given implementation are completely unpredictable ๐ต
Examples of undefined behavior are "a = a++;", "a[n] = b[n++]" and "a[i++] = i;". Some trickier cases don't get diagnosed by this option, and it might occasionally give a false positive. Still, it's been found pretty effective at catching this kind of problem in programs โจ
The C++17 standard defines the order of evaluation of operands in more cases. In particular, it requires the right-hand side of an assignment to be evaluated before the left-hand side, so the examples above are no longer undefined. But this option will still warn about them, so people avoid writing code that's undefined in C and earlier revisions of C++ ๐
The standard is worded confusingly, so there's some debate over the precise meaning of the sequence point rules in subtle cases. Links to discussions of the problem, including proposed formal definitions, can be found on the GCC readings page, at https://gcc.gnu.org/readings.html.
This warning is enabled by -Wall for C and C++.
-Wno-return-local-addrโ don't warn about returning a pointer (or, in C++, a reference) to a variable that goes out of scope after the function returns ๐ท Okay, you do you ๐ซถ-Wreturn-mismatchโ okay bestie, this one is all about return statements ๐ . It warns when a function that isn'tvoidhits areturnwith no expression ๐ญ. It also warns when avoidfunction tries toreturnan expression, unless that expression is alsovoid๐. As a GNU extension, that last case gets a free pass with no warning unless you've got-Wpedanticturned on ๐ง.
๐ Heads up: using the return value of a non-voidfunction (other thanmain) that runs off the end by reaching its closing curly brace is undefined behavior. Don't do it, babe ๐ซถ.
This warning is C-only and enabled by default โจ. In C99 and later dialects, it gets promoted to an error ๐ซ. You can soften it back into a regular warning with -fpermissive (which also softens other warnings) ๐ฆ, or just for this one with -Wno-error=return-mismatch ๐ธ.
-Wreturn-typeโ this one checks a few things ๐. It warns about a function defined with a return type that defaults toint(unless-Wimplicit-intis active, which takes priority ๐). It also warns if execution might reach the end of the function body, or if the function doesn't contain anyreturnstatement at all ๐.
๐ Same UB energy: using the return value of a non-voidfunction (other thanmain) that runs off the end by reaching its closing curly brace is undefined behavior.
Unlike in C, in C++, flowing off the end of a non-void function other than main is undefined behavior even when the function's value isn't used ๐ฌ. This warning is enabled by default in C++ and by -Wall otherwise ๐.
-Wno-shift-count-negativeโ controls the warnings for a negative shift count ๐. Heads up, this one is enabled by default.-Wno-shift-count-overflowโ controls the warnings for when a shift count is greater than or equal to the bit width of the type ๐งฎ. Enabled by default too.-Wshift-negative-valueโ warns if you left shift a negative value ๐. It's enabled by-Wextrain C99 (and newer) and C++11 to C++17 modes โจ.-Wno-shift-overflow,-Wshift-overflow=nโ these options control warnings about left shift overflows ๐.-Wshift-overflow=1โ this is the level you get from plain-Wshift-overflow, and it's enabled by default in C99 and C++11 modes (and newer) ๐. It doesn't warn about left-shifting1into the sign bit ๐. (In C, though, that overflow still gets rejected in contexts where an integer constant expression is required.) No warning shows up in C++20 mode (and newer), since signed left shifts always wrap there ๐ฆ.-Wshift-overflow=2โ this level also warns about left-shifting1into the sign bit ๐ค, unless C++14 mode (or newer) is active.
-Wswitchโ warns whenever aswitchhas an index of enumerated type and is missing acasefor one or more of that enum's named codes ๐. Adefaultlabel stops this warning from firing ๐.caselabels that don't match any enumerator also trigger warnings with this option, unless the enum is marked with theflag_enumattribute ๐ง. This is enabled by-Wallโจ.-Wswitch-defaultโ warns whenever aswitchdoesn't have adefaultcase ๐ซ .-Wswitch-enumโ warns about the same missing-casesituation as-Wswitch๐ . The only difference is that this one still warns about an omitted enumeration code even if there's adefaultlabel ๐ค. Like-Wswitch,caselabels that don't correspond to enumerators also get warnings, unless the enum is marked with theflag_enumattribute ๐.-Wno-switch-boolโ don't warn when aswitchhas an index of boolean type and the case values are outside the range of a boolean ๐ . You can suppress this warning by casting the controlling expression to a type other thanbool๐. For example:
switch ((int) (a == 4))
{
...
}
This warning is enabled by default for C and C++ programs ๐ธ.
-Wno-switch-outside-rangeโ controls warnings when aswitchcasehas a value outside the range of its type ๐. Enabled by default for C and C++ programs โจ.-Wno-switch-unreachableโ don't warn when aswitchhas statements between the controlling expression and the firstcaselabel, since those statements will never be executed ๐โโ๏ธ. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
-Wswitch-unreachable doesn't warn if the statement between the controlling expression and the first case label is just a declaration ๐. For example:
switch (cond)
{
int i;
...
case 5:
i = 5;
...
}
This warning is enabled by default for C and C++ programs ๐.
-Wsync-nand(C and C++ only) โ warns when the__sync_fetch_and_nandand__sync_nand_and_fetchbuilt-in functions get used ๐จ. Heads up, these functions changed semantics in GCC 4.4 ๐ฌ.-Wtrivial-auto-var-initโ warns when-ftrivial-auto-var-initcan't initialize an automatic variable ๐ซฅ. A super common case is an automatic variable declared between the controlling expression and the firstcaselabel of aswitch๐.-Wunused-but-set-parameterโ this is the same as-Wunused-but-set-parameter=3, and-Wno-unused-but-set-parameteris the same as-Wunused-but-set-parameter=0๐.-Wunused-but-set-parameter=nโ warns whenever a function parameter gets assigned to but is otherwise unused (aside from its declaration) ๐. To shush it, use theunusedattribute ๐คซ.-Wunused-but-set-parameter=0disables the warning ๐ .-Wunused-but-set-parameter=1means all uses except initialization and a left hand side of assignment that isn't used further will disable the warning ๐ .-Wunused-but-set-parameter=2means that, additionally, uses of the parameter in++and--operators don't count as uses ๐.-Wunused-but-set-parameter=3means that, additionally, uses in parm@=rhs outside of rhs don't count as uses ๐งพ. See-Wunused-but-set-variable=nfor examples ๐.
This -Wunused-but-set-parameter=3 warning is also enabled by -Wunused together with -Wextra โจ.
-Wunused-but-set-variableโ this is the same as-Wunused-but-set-variable=3, and-Wno-unused-but-set-variableis the same as-Wunused-but-set-variable=0๐ง .-Wunused-but-set-variable=nโ warns whenever a local variable gets assigned to but is otherwise unused (aside from its declaration) ๐ซฃ. This-Wunused-but-set-variable=3warning is enabled by-Wallโจ. To suppress it, use theunusedattribute ๐คซ.-Wunused-but-set-variable=0disables the warning ๐ .-Wunused-but-set-variable=1means all uses except initialization and a left hand side of assignment that isn't used further will disable the warning ๐ .-Wunused-but-set-variable=2means that, additionally, uses of the variable in++and--operators don't count as uses ๐.-Wunused-but-set-variable=3means that, additionally, uses in parm@=rhs outside of rhs don't count as uses ๐งพ.
This -Wunused-but-set-variable=3 warning is also enabled by -Wunused, which is enabled by -Wall ๐. Check out this example:
void foo (void)
{
int a = 1; // B<-Wunused-variable> warning
int b = 0; // Warning for <n> >= 1
b = 1; b = 2;
int c = 0; // Warning for <n> >= 2
++c; c--; --c; c++;
int d = 0; // Warning for <n> >= 3
d += 4;
int e = 0; // No warning, cast to void
(void) e;
int f = 0; // No warning, f used
int g = f = 5;
(void) g;
int h = 0; // No warning, preincrement used
int i = ++h;
(void) i;
int j = 0; // No warning, postdecrement used
int k = j--;
(void) k;
int l = 0; // No warning, l used
int m = l |= 2;
(void) m;
}
-Wunused-functionโ warns whenever astaticfunction is declared but not defined, or when a non-inlinestaticfunction is unused ๐ต๏ธ. Enabled by-Wallโจ.-Wunused-labelโ warns whenever a label is declared but not used ๐ท๏ธ. Enabled by-Wall. To suppress it, use theunusedattribute ๐คซ.-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ warns when atypedefdefined locally inside a function isn't used ๐ง. Enabled by-Wall.-Wunused-parameterโ warns whenever a function parameter is unused (aside from its declaration) ๐ป. This option isn't enabled by-Wunusedunless-Wextrais also specified ๐ง. To suppress it, use theunusedattribute ๐คซ.-Wno-unused-resultโ don't warn if a caller of a function marked with thewarn_unused_resultattribute doesn't use its return value ๐ . The default is-Wunused-result๐ .-Wunused-variableโ warns whenever a local orstaticvariable is unused (aside from its declaration) ๐ซง. This option implies-Wunused-const-variable=1for C, but not for C++ ๐ธ. Enabled by-Wallโจ. To suppress it, use theunusedattribute ๐คซ.-Wunused-const-variable,-Wunused-const-variable=nโ warns whenever a constantstaticvariable is unused (aside from its declaration) ๐. To suppress it, use theunusedattribute ๐คซ.-Wunused-const-variable=1warns about unusedstatic constvariables defined in the main compilation unit ๐ฏ, but not aboutstatic constvariables declared in any included header ๐. It's enabled by either-Wunused-variableor-Wunusedfor C, but not for C++ ๐. In C this declares variable storage, but in C++ it isn't an error, sinceconstvariables take the place of#defines ๐ .
-Wunused-const-variable=2: okay so this level also warns about unused constant static variables in headers ๐, just not system headers ๐ โโ๏ธ. It's the same as the short form-Wunused-const-variable. You have to ask for it explicitly in both C and C++ ๐ because cleaning up every header you've included can be genuinely hard ๐ญ.-Wunused-value: ngl, this one is iconic ๐ฅ. It warns whenever a statement computes a result that's explicitly not used ๐. To shut it up, cast the unused expression to"void". That covers an expression-statement or the left-hand side of a comma expression that has no side effects. Sox[i,j]gets flagged, butx[(void)i,j]is totally fine ๐.- This warning is enabled by
-Wallโจ.
- This warning is enabled by
-Wunused: all the above-Wunusedoptions combined, except the ones that have to be specified explicitly ๐.- To get a warning about an unused function parameter, you must either specify
-Wextra -Wunused(note that-Wallimplies-Wunused), or separately specify-Wunused-parameterand/or-Wunused-but-set-parameter๐ง. -Wunusedonly enables-Wunused-const-variable=1instead of-Wunused-const-variable, and only for C, not C++ ๐ โโ๏ธ.
- To get a warning about an unused function parameter, you must either specify
-Wuse-after-free(C, Objective-C, C++ and Objective-C++ only) and-Wuse-after-free=n: this one warns about uses of pointers to dynamically allocated objects that were made indeterminate by a call to a deallocation function ๐ฆ. It's enabled at all optimization levels, but the results can be different with optimization than without โ ๏ธ.-Wuse-after-free=1: at level 1, the warning only tries to catch unconditional uses of pointers made indeterminate by a deallocation call or a successful call to"realloc", no matter whether that call actually reallocated memory ๐ธ. This includes double-"free"calls, plus uses in arithmetic and relational expressions. Uses of indeterminate pointers in equality (or inequality) expressions are undefined, but they aren't diagnosed at this level ๐ซถ.-Wuse-after-free=2: at level 2, on top of unconditional uses, it also diagnoses conditional uses of pointers made indeterminate by a deallocation call ๐. As at level 2, uses in equality (or inequality) expressions aren't diagnosed. Here's a sneaky example where the second"free"gets flagged at this level ๐:
struct A { int refcount; void *data; };
void release (struct A *p)
{
int refcount = --p->refcount;
free (p);
if (refcount == 0)
free (p->data); // warning: p may be used after free
}
-Wuse-after-free=3: at level 3, the warning also diagnoses uses of indeterminate pointers in equality expressions ๐ . Every use of an indeterminate pointer is undefined, but equality tests sometimes pop up after"realloc"calls as an attempt to figure out whether the object got moved to a new address ๐ง. They get their own level so legacy code can gradually move to safer alternatives ๐. Here's the equality test that gets flagged at this level:
void adjust_pointers (int**, int);
void grow (int **p, int n)
{
int **q = (int**)realloc (p, n *= 2);
if (q == p)
return;
adjust_pointers ((int**)q, n);
}
- To avoid the warning at this level, store offsets into allocated memory instead of pointers. That way you don't need to adjust the stored pointers after reallocation ๐.
-Wuse-after-free=2is included in-Wall๐.
-Wuseless-cast(C, Objective-C, C++ and Objective-C++ only): warns when an expression is cast to its own type ๐. It does not occur when a class object is converted to a non-reference type, because that's a legit way to make a temporary โจ:
struct S { };
void g (S&&);
void f (S&& arg)
{
g (S(arg)); // make arg prvalue so that it can bind to S&&
}
-Wuninitialized: warns if an object with automatic or allocated storage duration gets used without having been initialized ๐ฑ. In C++, it also warns if a non-static reference or non-static"const"member shows up in a class without constructors ๐.- Passing a pointer (or, in C++, a reference) to an uninitialized object into a
"const"-qualified argument of a built-in function known to read the object also gets diagnosed here ๐. (-Wmaybe-uninitializedhandles ordinary functions.) - If you want to warn about code that uses the uninitialized value of a variable in its own initializer, use the
-Winit-selfoption ๐ง . - These warnings cover individual uninitialized elements of structure, union or array variables, as well as variables that are uninitialized as a whole ๐งธ. They do not occur for variables or elements declared
"volatile". Since these warnings depend on optimization, exactly which variables or elements get warned about depends on the precise optimization options and the version of GCC you're using ๐. - There may be no warning about a variable that's only used to compute a value that itself is never used, because data flow analysis might delete those computations before the warnings get printed ๐๏ธ.
- In C++, this warning also catches using uninitialized objects in member-initializer-lists. GCC warns about
"b"being uninitialized in this snippet ๐:
- Passing a pointer (or, in C++, a reference) to an uninitialized object into a
struct A {
int a;
int b;
A() : a(b) { }
};
-Wno-invalid-memory-model: this option controls warnings for invocations of__atomicBuiltins,__syncBuiltins, and the C11 atomic generic functions with a memory consistency argument that is either invalid for the operation or outside the range of values in thememory_orderenumeration ๐งต. For example,__atomic_storeand__atomic_store_nare only defined for the relaxed, release, and sequentially consistent memory orders, so this code gets diagnosed ๐:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
-Winvalid-memory-modelis enabled by default ๐.
-Wmaybe-uninitialized: for an object with automatic or allocated storage duration, if there's a path from the function entry to a use of the object where it's initialized, but some other paths where it isn't, the compiler warns if it can't prove those uninitialized paths never run at runtime ๐.- Passing a pointer (or, in C++, a reference) to an uninitialized object into a
"const"-qualified function argument is also diagnosed by this warning ๐ซ . (-Wuninitializedis issued for built-in functions known to read the object.) Annotating the function with attributeaccess (none)says the argument isn't used to access the object, and that avoids the warning ๐. - These warnings are only possible in optimizing compilation, because otherwise GCC doesn't track the state of variables ๐ ๏ธ. On the flip side,
-Wmaybe-uninitializedis known to miss plenty of situations (false negatives) because optimizations like constant propagation take advantage of the undefinedness of uninitialized uses ๐คทโโ๏ธ. - These warnings are optional because GCC may not be able to tell when code is correct even though it looks like an error ๐ฅบ. Here's one example of how that happens:
- Passing a pointer (or, in C++, a reference) to an uninitialized object into a
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
- If the value of
"y"is always 1, 2 or 3, then"x"is always initialized, but GCC doesn't know that ๐ฅน. To suppress the warning, provide a default case withassert(0)or similar code ๐ . - This option also warns when a non-volatile automatic variable might be changed by a call to
"longjmp". The compiler only sees the calls to"setjmp". It can't know where"longjmp"will be called, since a signal handler could call it at any point in the code ๐ต. So you might get a warning even when there's actually no problem, because"longjmp"can't really be called at the place that would cause one. - Some spurious warnings can be avoided if you declare all the functions you use that never return as
"noreturn"๐ท. - This warning is enabled by
-Wallor-Wextra๐.
-Wunknown-pragmas: warns when a#pragmadirective shows up that GCC doesn't understand ๐งฉ. If this command-line option is used, warnings are even issued for unknown pragmas in system header files. That's not the case if the warnings are only enabled by the-Wallcommand-line option ๐ซ.-Wno-pragmas: don't warn about misuses of pragmas, like incorrect parameters, invalid syntax, or conflicts between pragmas ๐. See also-Wunknown-pragmas๐.-Wno-pragma-once-outside-header: don't warn when#pragma onceis used in a file that isn't a header file, such as a main file ๐ธ.-Wno-prio-ctor-dtor: don't warn if a priority from 0 to 100 is used for a constructor or destructor ๐. The constructor and destructor attributes let you assign a priority to control the order of execution beforemainis called or after it returns ๐๏ธ. The priority values must be greater than 100, because the compiler reserves priority values between 0--100 for the implementation ๐.-Wstrict-aliasing: this one is only active when-fstrict-aliasingis active ๐. It warns about code that might break the strict aliasing rules the compiler uses for optimization โจ. It doesn't catch every case, but it does try to catch the more common pitfalls ๐ซถ. It's included in-Wall, and it's equivalent to-Wstrict-aliasing=3๐.-Wstrict-aliasing=nโ ๐ okay bestie, this one only works when-fstrict-aliasingis turned on. It checks for code that might break the strict aliasing rules the compiler uses for optimization โจ. Higher levels are more accurate (fewer false positives), but they also take more effort, kinda like how-Oworks ๐ง.-Wstrict-aliasingis the same thing as-Wstrict-aliasing=3๐.- Level 1 is the most aggressive, quick, and least accurate option ๐
. It's useful when the higher levels don't warn but
-fstrict-aliasingstill breaks your code, since it has very few false negatives ๐ญ. The catch is it has many false positives. It warns for every pointer conversion between possibly incompatible types, even if the pointer is never dereferenced. It only runs in the front end ๐. - Level 2 is aggressive and quick but not super precise ๐ธ. It can still have a lot of false positives (just not as many as level 1), and few false negatives, though maybe more than level 1. Unlike level 1, it only warns when an address is taken. It also warns about incomplete types. It runs in the front end only ๐ซถ.
- Level 3 is the default for
-Wstrict-aliasing๐. It should have very few false positives and very few false negatives ๐ฅ. It's slightly slower than levels 1 or 2 when optimization is enabled. It handles the common pun+dereference pattern in the front end, like"*(int*)&some_float"๐ฆ. If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information ๐ง . It only warns when the converted pointer is dereferenced, and it does not warn about incomplete types โจ.
-Wstrict-overflow,-Wstrict-overflow=nโ ๐ this one is only active when signed overflow is undefined. It warns when the compiler optimizes based on the assumption that signed overflow never happens. Heads up, it doesn't catch every spot where your code might overflow ๐. It only warns where the compiler actually does some optimization, so this warning depends on your optimization level ๐ .- An optimization that assumes signed overflow doesn't happen is totally safe if the values never actually overflow ๐. That's why this warning can easily give a false positive, meaning a warning about code that isn't actually a problem ๐ญ. To help you focus on the important stuff, there are several warning levels ๐. No warnings are issued for undefined signed overflow when estimating how many iterations a loop needs, especially when figuring out whether a loop runs at all ๐ซถ.
-Wstrict-overflow=1warns about cases that are both questionable and easy to avoid ๐ธ. For example, the compiler simplifies"x + 1 > x"to 1. This level is enabled by-Wall. Higher levels aren't, so you have to ask for them explicitly ๐.-Wstrict-overflow=2also warns about other cases where a comparison gets simplified to a constant โจ. For example:"abs (x) >= 0". This can only be simplified when signed integer overflow is undefined, because"abs (INT_MIN)"overflows toINT_MIN, which is less than zero ๐ง. Plain-Wstrict-overflowwith no level is the same as-Wstrict-overflow=2๐.-Wstrict-overflow=3also warns about other comparisons that get simplified ๐ฆ. For example:"x + 1 > 1"gets simplified to"x > 0"๐ .-Wstrict-overflow=4also warns about other simplifications that aren't covered above ๐ฅ. For example:"(x * 10) / 5"gets simplified to"x * 2"๐.-Wstrict-overflow=5also warns about cases where the compiler reduces the magnitude of a constant in a comparison ๐ญ. For example:"x + 2 > y"gets simplified to"x + 1 >= y". This is only reported at the highest warning level ๐.
โ ๏ธ This simplification applies to so many comparisons that this level gives a very large number of false positives ๐.
-Wstring-compareโ ๐ this one warns for calls to"strcmp"and"strncmp"whose result is determined to be zero or non-zero in equality tests, because one argument's length is bigger than the size of the array the other argument is stored in (or the bound, for"strncmp") ๐. Those calls could be mistakes ๐. In the example below, the"strcmp"call gets flagged, since its result is necessarily non-zero no matter what's in the array"a"๐ .
extern char a[4];
void f (char *d)
{
strcpy (d, "string");
...
if (0 == strcmp (a, d)) // cannot be true
puts ("a and d are the same");
}
-Wstring-compare is enabled by -Wextra โจ.
-Wno-stringop-overflow,-Wstringop-overflow,-Wstringop-overflow=typeโ ๐จ this one warns about code that can be figured out at compile time to cause buffer overflows or memory overruns, like"memcpy"and"strcpy"calls that overflow the destination buffer ๐ญ. The optional argument is one greater than the type of Object Size Checking used to figure out the size of the destination ๐ง. It only matters for string functions that work on character arrays. Raw memory functions like"memcpy"always use type-zero Object Size Checking ๐ซถ.- It also warns for calls that specify a size bigger than the largest possible object, or at most
"SIZE_MAX / 2"bytes ๐. - This option gives the best results with optimization turned on ๐ฅ. Even without optimization, it can catch a small subset of simple buffer overflows in calls to GCC built-in functions like
"__builtin_memcpy"that match the standard functions ๐ธ. Either way, it only warns about a subset of the overflows caught by the matching overflow checking built-ins, like"__builtin___memcpy_chk". Those can do run-time checking when the access can't be proven safe at compile time ๐ฆ. - In the example below, this option warns about the
"strcpy"call because it copies at least 5 characters (the string"blue"plus the terminating NUL) into a buffer of size 4 ๐.
- It also warns for calls that specify a size bigger than the largest possible object, or at most
enum Color { blue, purple, yellow };
const char* f (enum Color clr)
{
static char buf [4];
const char *str;
switch (clr)
{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
}
return strcpy (buf, str); // warning here
}
This option isn't only for string or memory functions, either ๐. In the example below, a warning is issued because a 1-element array gets passed to a function that needs at least a 4-element array argument ๐ .
void f (int[static 4]);
void g (void)
{
int *p = (int *) malloc (1 * sizeof(int));
f (p); // warning here
}
-Wstringop-overflow=2 is enabled by default ๐.
-Wstringop-overflow,-Wstringop-overflow=1โ this one uses type-zero Object Size Checking to figure out the sizes of destination objects ๐. At this setting, it doesn't warn about writes past the end of subobjects of larger objects accessed through pointers, unless the size of the largest surrounding object is known ๐ง . When the destination could be one of several objects, it's assumed to be the largest one of them ๐ซถ. On Linux systems, when optimization is enabled at this setting, the option warns about the same code that gets flagged when the_FORTIFY_SOURCEmacro is defined to a non-zero value ๐ฆ.-Wstringop-overflow=2โ this one uses type-one Object Size Checking to figure out the sizes of destination objects โจ. At this setting, it warns about overflows when writing to members of the largest complete objects whose exact size is known ๐ธ. It doesn't warn about excessive writes to the same members of unknown objects referenced by pointers, since those pointers might point to arrays with unknown numbers of elements ๐. This is the default setting for this option ๐.-Wstringop-overflow=3โ this one uses type-two Object Size Checking to figure out the sizes of destination objects ๐ . At this setting, it warns about overflowing the smallest object or data member ๐ญ. This is the most restrictive setting that might warn about safe code too ๐.-Wstringop-overflow=4โ this one uses type-three Object Size Checking to figure out the sizes of destination objects ๐ฅ. At this setting, it warns about overflowing any data members. When the destination is one of several objects, it uses the size of the largest one to decide whether to warn ๐ง. Like-Wstringop-overflow=3, this setting may result in warnings for benign code ๐.
-Wno-stringop-overreadโ ๐ this one warns for calls to string manipulation functions like"memchr"or"strcpy"that are determined to read past the end of the source sequence ๐ซถ.-Wstringop-overreadis enabled by default โจ.-Wno-stringop-truncationโ ๐ โโ๏ธ this one stops the warning for calls to bounded string manipulation functions like"strncat","strncpy", and"stpncpy"that might truncate the copied string or leave the destination unchanged ๐. In the example below, the"strncat"call sets a bound that's less than the length of the source string. That means the copy gets truncated, so the call is flagged ๐ญ. To avoid the warning, use"bufsize - strlen (buf) - 1)"as the bound ๐ .
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
In another example, the "strncpy" call copies only the characters before the terminating NUL into "d", without adding the NUL to the end ๐ฆ. Assuming the result of "strncpy" is always a NUL-terminated string is a super common mistake, so this call gets flagged ๐. If the result isn't expected to be NUL-terminated, call "memcpy" instead to avoid the warning ๐ธ.
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
Okay so this is the sketchy one ๐ Next up is the safe version. Here the strncpy call uses the size of the destination buffer as its bound, and if the source string is equal to or longer than that size, the copy won't be NUL-terminated. So GCC diagnoses it too ๐ฉ To dodge the warning, use sizeof buf - 1 as the bound and set the last element of the buffer to NUL. Literally one tiny fix, no cap ๐
void copy (const char *s)
{
char buf[80];
strncpy (buf, s, sizeof buf);
...
}
Now, sometimes a character array is supposed to hold a run of bytes with no terminating NUL, and that's valid! For those, you can slap the nonstring attribute on the array so this warning chills out ๐ง BUT bestie, these arrays are not it for functions that expect NUL-terminated strings. To catch accidental misuse, GCC warns on them unless it can prove the use is safe ๐ซถ
-Wstrict-flex-arrays(C and C++ only) โ this one checks for sus usage of flexible array members. It goes by the level in thestrict_flex_array (level)attribute on the trailing array field of a struct, if that's available. If not, it goes by-fstrict-flex-arrays=levelinstead. It's only effective when level is greater than0โจ- At level 1, you get warnings for a trailing array reference in a struct that has 2 or more elements, if that trailing array is referenced as a flexible array member ๐ธ
- At level 2, you get everything from level 1, plus warnings for a trailing one-element array reference in a struct if it's used as a flexible array member ๐ฆ
- At level 3, you get everything from level 2, plus warnings for a trailing zero-length array reference in a struct if it's used as a flexible array member ๐
- This option hits harder with
-ftree-vrpon (the default for-O2and above), but some warnings can still show up even without optimization ๐
-Wsuggest-attribute=attribute-nameโ warns when adding an attribute might be a glow-up ๐ The attribute names supported right now are:-Wsuggest-attribute=pure-Wsuggest-attribute=const-Wsuggest-attribute=noreturn-Wmissing-noreturn-Wsuggest-attribute=malloc-Wsuggest-attribute=returns_nonnull
These all warn about functions that might be candidates for the pure, const, noreturn, malloc, or returns_nonnull attributes. GCC only warns for functions visible in other compilation units, or (for pure and const) if it can't prove the function returns normally. A function returns normally if it doesn't have an infinite loop and doesn't return abnormally by throwing, calling abort, or trapping ๐ง This analysis needs -fipa-pure-const, which is on by default at -O and higher. Higher optimization levels make the analysis more accurate โจ
-Wsuggest-attribute=formatand-Wmissing-format-attributeโ these warn about function pointers that might be candidates forformatattributes. Heads up, these are only possible candidates, not guaranteed ones ๐ GCC assumes that function pointers withformatattributes, used in an assignment, initialization, parameter passing, or a return statement, should have a matchingformatattribute in the resulting type. So the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function should also have aformatattribute to avoid the warning.
GCC also warns about function definitions that might be format candidates, and again, that's just a maybe. GCC guesses format attributes might fit any function that calls something like vprintf or vscanf, but that's not always true, and some functions that do deserve format attributes might not get detected ๐
-Wsuggest-attribute=coldโ warns about functions that might be candidates for thecoldattribute ๐ง This is based on static detection, and it usually only warns about functions that always lead to a call to anothercoldfunction, like wrappers around C++throwor fatal error reporting functions that lead toabort.-Walloc-sizeโ warns about calls to allocation functions decorated with thealloc_sizeattribute that specify an insufficient size for the target type of the pointer the result is assigned to. This includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc๐-Walloc-zeroโ warns about calls to allocation functions decorated with thealloc_sizeattribute that specify zero bytes. This includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc. Behavior with a zero size differs between implementations (andreallocwith zero has been deprecated), so relying on it can cause subtle portability bugs. Bestie, just avoid it ๐ซ-Wcalloc-transposed-argsโ warns about calls to allocation functions decorated with thealloc_sizeattribute that have two arguments, where the earlier size argument uses thesizeofoperator and the later one doesn't. This is a coding style warning ๐ The first argument tocallocis documented as the number of elements in the array, and the second is the size of each element. Socalloc (n, sizeof (int))is preferred overcalloc (sizeof (int), n). If usingsizeofin the earlier argument but not the latter is on purpose, you can suppress the warning withcalloc (sizeof (struct S) + 0, n)orcalloc (1 * sizeof (struct S), 4), or by usingsizeofin the later argument as well.-Walloc-size-larger-than=byte-sizeโ warns about calls to functions decorated with thealloc_sizeattribute that try to allocate objects larger than the specified number of bytes. It also warns when the result of the size computation, done in an integer type with infinite precision, would exceed the value ofPTRDIFF_MAXon the target ๐ฅ-Walloc-size-larger-than=PTRDIFF_MAXis enabled by default. You can disable these warnings by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-alloc-size-larger-than.-Wno-alloc-size-larger-thanโ disables the-Walloc-size-larger-than=warnings. It's equivalent to-Walloc-size-larger-than=SIZE_MAXor larger ๐ธ-Wallocaโ warns on all uses ofallocain the source ๐-Wauto-profileโ outputs warnings about auto-profile inconsistencies ๐-Wcannot-profileโ warns when profiling instrumentation was requested but couldn't be applied to a certain function ๐ฅ-Walloca-larger-than=byte-sizeโ warns on calls toallocawith an integer argument whose value is either zero, or isn't bounded by a controlling predicate that limits it to at most byte-size. It also warns forallocacalls where the bound value is unknown. Arguments of non-integer types count as unbounded, even if they look like they're in the expected range ๐ง
Here's a bounded case of alloca:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
Passing -Walloca-larger-than=1000 won't warn here, since the alloca call is known to be at most 1000 bytes. But if you passed -Walloca-larger-than=500, the compiler would warn โ ๏ธ
Unbounded uses are alloca calls with no controlling predicate constraining the integer argument. For example:
void func ()
{
void *p = alloca (n);
f (p);
}
With -Walloca-larger-than=500, the above would trigger a warning, because there's no bounds checking ๐
Heads up, even seemingly correct code with signed integers can cause a warning:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
In the example above, n could be negative, which would cause a larger-than-expected argument to be implicitly cast into the alloca call ๐ญ
This option also warns when alloca is used in a loop ๐
-Walloca-larger-than=PTRDIFF_MAX is enabled by default, but it's usually only effective when -ftree-vrp is active (the default for -O2 and above). See also -Wvla-larger-than=byte-size ๐ฆ
-Wno-alloca-larger-thanโ disables the-Walloca-larger-than=warnings. It's equivalent to-Walloca-larger-than=SIZE_MAXor larger โจ-Warith-conversionโ warns about implicit conversions from arithmetic operations, even when converting the operands to the same type can't change their values. This affects warnings from-Wconversion,-Wfloat-conversion, and-Wsign-conversion๐ข Check the vibes:
void f (char c, int i)
{
c = c + i; // warns with -Wconversion
c = c + 1; // only warns with -Warith-conversion
}
-Warray-boundsand-Warray-bounds=nโ warn about out-of-bounds subscripts or offsets into arrays. This warning is enabled by-Wall๐ง It's more effective when-ftree-vrpis active (the default for-O2and above), but a subset of instances are issued even without optimization ๐
Okay so by default, the trailing array at the end of a struct gets treated as a flexible array member by -Warray-bounds or -Warray-bounds=n ๐
. That's true whether it's written as a C99 flexible array member ([]), a GCC zero-length array extension ([0]), or a one-element array ([1]) ๐ฆ. So out-of-bounds subscripts or offsets into zero-length arrays or one-element arrays are not warned about by default. Lowkey wild, but it's the vibe โจ
You can add -fstrict-flex-arrays or -fstrict-flex-arrays=level to control how this option treats a trailing struct array as a flexible array member ๐
level<=1โ no change to the default behavior ๐ธlevel=2โ extra warnings get issued for out-of-bounds subscripts or offsets into one-element arrays ๐ฅlevel=3โ in addition to level=2, extra warnings get issued for out-of-bounds subscripts or offsets into zero-length arrays ๐
-Warray-bounds=1โ this is the default warning level of-Warray-bounds, and it's enabled by-Wall๐. The higher levels aren't turned on by-Wall, so you have to ask for them explicitly ๐ซถ-Warray-bounds=2โ this level also warns about the intermediate results of pointer arithmetic that might come out as out-of-bounds values ๐. It can give you a bigger pile of false positives, so it's deactivated by default ๐
-Wunterminated-string-initialization (C and Objective-C only)
Okay, this one is about character arrays that get initialized as unterminated character sequences using a string literal ๐ญ. It warns about that unless the declaration being initialized has the nonstring attribute. Here's the tea:
char arr[3] = "foo"; /* Warning. */
char arr2[3] __attribute__((nonstring)) = "bar"; /* No warning. */
This warning is enabled by -Wextra ๐. If -Wc++-compat is enabled, the warning has slightly different wording, and it warns even if the declaration has the nonstring attribute. Why? Because in C++, those initializations are an error ๐
-Warray-compare
This one warns about equality and relational comparisons between two operands of array type ๐. Fun fact (not fun): that comparison got deprecated in C++20 ๐ฅ. Example:
int arr1[5];
int arr2[5];
bool same = arr1 == arr2;
-Warray-compare is enabled by -Wall โจ
-Warray-parameter and -Warray-parameter=n
Warn about redeclarations of functions that involve parameters of array or pointer types with inconsistent kinds or forms ๐ง. It also turns on detecting out-of-bounds accesses to those parameters through warnings like -Warray-bounds ๐.
If the first function declaration uses the array form for a parameter, the bound in the array is assumed to be the minimum number of elements expected in calls to the function, and the maximum number of elements it accesses ๐. Giving it arguments that are too small, or accessing more than that maximum, may get diagnosed by warnings like -Warray-bounds or -Wstringop-overflow ๐จ. At level 1, the warning diagnoses inconsistencies involving array parameters declared with the "T[static N]" form.
For example, the warning triggers on the second declaration of f, because the first one, with the keyword static, says the array argument must have at least four elements, while the second one allows an array of any size to be passed in ๐ค
void f (int[static 4]);
void f (int[]); // warning (inconsistent array form)
void g (void)
{
int *p = (int *)malloc (1 * sizeof (int));
f (p); // warning (array too small)
...
}
At level 2, the warning also triggers for redeclarations involving any other inconsistency in array or pointer argument forms that denote array sizes ๐ธ. Pointers and arrays of unspecified bound are considered equivalent, so they don't trigger a warning ๐ซถ
void g (int*);
void g (int[]); // no warning
void g (int[8]); // warning (inconsistent array bound)
-Warray-parameter=2 is included in -Wall ๐. The -Wvla-parameter option triggers warnings for similar inconsistencies involving Variable Length Array arguments ๐ฆ
- The short form,
-Warray-parameter, is equivalent to-Warray-parameter=2โจ - The negative form,
-Wno-array-parameter, is equivalent to-Warray-parameter=0๐
-Wattribute-alias=n and -Wno-attribute-alias
This warns about declarations that use the "alias" and similar attributes whose target is incompatible with the type of the alias ๐
-Wattribute-alias=1โ this is the default level ๐ . It diagnoses incompatibilities between the type of the alias declaration and the type of its target. These are usually signs of bugs ๐-Wattribute-alias=2โ at this level,-Wattribute-aliasalso diagnoses cases where the attributes of the alias declaration are more restrictive than the attributes on its target ๐ง. These mismatches can potentially lead to incorrect code generation ๐. Other times they're totally benign, and you can fix them just by adding the missing attribute to the target ๐ฉน. For comparison, check out-Wmissing-attributes, which controls diagnostics when the alias declaration is less restrictive than the target, rather than more restrictive ๐
Attributes considered at this level include "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc", "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull", and "returns_twice" ๐
-Wattribute-alias is equivalent to -Wattribute-alias=1, which is the default ๐. You can turn these warnings off with either -Wno-attribute-alias or -Wattribute-alias=0 ๐
โโ๏ธ
-Wbidi-chars=[none|unpaired|any|ucn]
Okay, this one is super important ๐ญ. It warns about possibly misleading UTF-8 bidirectional control characters in comments, string literals, character constants, and identifiers ๐. These characters can flip left-to-right writing direction into right-to-left (and vice versa), which can cause confusion between the logical order and the visual order ๐.
This can be genuinely dangerous ๐. For instance, a piece of code might look like it isn't commented out, when it actually is. Or the other way around!
GCC supports three levels of this warning ๐ฅ
-Wbidi-chars=unpairedโ this is the default, and it warns about improperly terminated bidi contexts ๐ฉท-Wbidi-chars=noneโ turns the warning off ๐-Wbidi-chars=anyโ warns about any use of bidirectional control characters ๐ฉ
By default, this warning does not warn about UCNs (universal character names). You can totally turn on that checking, though, with -Wbidi-chars=unpaired,ucn or -Wbidi-chars=any,ucn ๐ง. Using -Wbidi-chars=ucn is valid too, and it's equivalent to -Wbidi-chars=unpaired,ucn, as long as no previous -Wbidi-chars=any was specified ๐ซถ
NOTE: In Ubuntu 25.10 and later versions,-Wbidi-charsis enabled by default for C, C++, ObjC, and ObjC++, unless-Wno-bidi-charsor-Wbidi-chars=noneis found ๐ง
-Wbool-compare
This warns about a boolean expression being compared with an integer value that's different from "true"/"false" ๐ค. For instance, this comparison is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
This warning is enabled by -Wall ๐
-Wbool-operation
This warns about suspicious operations on expressions of a boolean type ๐. For example, bitwise negation of a boolean is very likely a bug in your program ๐. For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense ๐. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++17, and deprecated otherwise ๐ฅ.)
This warning is enabled by -Wall โจ
-Wduplicated-branches
This warns when an if-else has identical branches ๐ฏ. It detects cases like this one:
if (p != NULL)
return 0;
else
return 0;
It doesn't warn when both branches contain just a null statement ๐. This warning also warns for conditional operators, like this one:
int i = x ? *p : *p;
-Wduplicated-cond
This warns about duplicated conditions in an if-else-if chain ๐. For instance, it'll warn for code like this:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-address
This warns when __builtin_frame_address or __builtin_return_address is called with an argument greater than 0 ๐จ. Those calls may return indeterminate values or crash the program ๐. This warning is included in -Wall ๐
-Wno-discarded-qualifiers (C and Objective-C only)
Okay so this one turns off a warning ๐
. By default, the compiler warns if the type qualifiers on pointers are being discarded ๐. Typically, that's when a "const char *" variable gets passed to a function that takes a "char *" parameter. Use this option if you want to suppress that warning ๐ซถ
-Wno-discarded-array-qualifiers (C and Objective-C only)
Same energy, but for arrays that are pointer targets ๐
. Do not warn if the type qualifiers on those arrays are being discarded. Typically, the compiler warns if a "const int (*)[]" variable is passed to a function that takes an "int (*)[]" parameter. This option suppresses that warning ๐ธ
-Wno-incompatible-pointer-types (C and Objective-C only)
This tells GCC not to warn when there's a conversion between pointers that have incompatible types ๐. It covers cases not handled by -Wno-pointer-sign, which is the one for pointer argument passing or assignment with different signedness ๐ง
By default, in C99 and later dialects of C, GCC treats this issue as an error ๐ญ. You can downgrade it to a warning with -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=incompatible-pointer-types ๐ฉน. This warning gets upgraded to an error by -pedantic-errors ๐ฅ
-Wno-int-conversion (C and Objective-C only)
This tells GCC not to warn about incompatible integer-to-pointer and pointer-to-integer conversions ๐ง. This one is about implicit conversions. For explicit conversions, you can use -Wno-int-to-pointer-cast and -Wno-pointer-to-int-cast instead ๐
By default, in C99 and later dialects of C, GCC treats this issue as an error ๐. You can downgrade it to a warning with -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=int-conversion ๐
Heads up, bestie: this next one gets bumped up to an error if you use -pedantic-errors ๐จ
-Wzero-as-null-pointer-constantโ okay so this one yells whenever you use a literal0as a null pointer constant ๐-Wzero-length-boundsโ ngl this one is giving "watch your array bounds" energy โจ It warns about accesses to elements of zero-length array members that might overlap other members of the same object. Declaring interior zero-length arrays is discouraged, because accessing them is undefined.
โ ๏ธ Undefined behaviour alert: touching those interior zero-length arrays is undefined, so please don't go poking at them ๐ญ
Check out this example. The first two stores in function bad get flagged because those array elements overlap the next members b and c. The third store gets caught by -Warray-bounds instead, since it's past the end of the enclosing object ๐
struct X { int a[0]; int b, c; };
struct X x;
void bad (void)
{
x.a[0] = 0; // -Wzero-length-bounds
x.a[1] = 1; // -Wzero-length-bounds
x.a[2] = 2; // -Warray-bounds
}
Also, -Wzero-length-bounds is enabled by -Warray-bounds, so it tags along for the ride ๐
-Wno-div-by-zeroโ bestie, this turns off the warning for compile-time integer division by zero ๐ โโ๏ธ Floating-point division by zero doesn't get warned about either, because it can be a legit way to get infinities and NaNs ๐-Wsystem-headersโ this one tells GCC to print warnings for constructs found in system header files ๐ Normally those warnings are suppressed, on the assumption that they usually aren't real problems and would just make the compiler output harder to read. With this flag, GCC emits them as if they happened in user code ๐ Heads up though: using-Wallalongside this option does not warn about unknown pragmas in system headers. For that, you also need-Wunknown-pragmas๐ซถ-Wtautological-compareโ this one catches self-comparisons that always evaluate to true or false ๐ It detects mistakes like this:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always come out true or false. For example:
if ((a & 16) == 10) { ... }
That one will always be false, sis ๐ญ This warning is enabled by -Wall โจ
-Wtrailing-whitespace,-Wtrailing-whitespace=kindโ this one warns about trailing whitespace at the end of lines, including inside comments, but skips trailing whitespace in raw string literals ๐งน-Wtrailing-whitespaceis the same as-Wtrailing-whitespace=blanks, and it only warns about trailing spaces and horizontal tabs.-Wtrailing-whitespace=anyalso catches trailing form feed or vertical tab characters.-Wno-trailing-whitespaceor-Wtrailing-whitespace=noneturns it off, which is the default. This is a coding style warning, so it's more of a vibe thing than a bug thing ๐-Wleading-whitespace=kindโ this one checks for style issues in leading whitespace, but it doesn't care about how much you indent ๐ธ Some projects only use spaces, some only use tabs, and some use zero or more tabs (in multiples of-ftabstop=n) followed by zero or fewer than n spaces. No warning shows up on lines that are only whitespace (although a-Wtrailing-whitespace=warning might still pop up), and nothing gets flagged inside raw string literals. It does check leading whitespace inside multi-line comments, though ๐-Wleading-whitespace=spaceswarns about leading whitespace that isn't spaces, for projects that want to indent with just spaces ๐-Wleading-whitespace=tabswarns about leading whitespace that isn't horizontal tabs, for projects that want to indent with just horizontal tabs ๐ง-Wleading-whitespace=blankswarns about leading whitespace that isn't spaces or horizontal tabs. It also flags a horizontal tab after a space in the leading whitespace, or n or more consecutive spaces in leading whitespace, where n is the argument of-ftabstop=n(8 by default) ๐ฅ-Wleading-whitespace=noneturns the warning off, which is the default ๐
-Wtrampolinesโ this one warns about trampolines generated for pointers to nested functions ๐ฆ A trampoline is a little piece of data or code that gets created at run time on the stack when the address of a nested function is taken, and it's used to call that nested function indirectly. On some targets it's only data, so it needs no special treatment. On most targets, though, it's made of code, which means the stack has to be executable for the program to work properly.
โ ๏ธ Security vibes: making the stack executable is a big deal, so be careful with trampolines on those targets ๐
-Wfloat-equalโ this one warns if floating-point values are used in equality comparisons ๐ The idea is that sometimes it's convenient to treat floating-point values as approximations to infinitely precise real numbers. If you're doing that, you need to figure out the maximum (or likely maximum) error the computation introduces, and allow for it when you compare values (and when you produce output, but that's a different problem ๐ ). Instead of testing for equality, you should check whether the two values have overlapping ranges. You do that with the relational operators, so equality comparisons are probably a mistake ๐ซถ-Wtraditional(C and Objective-C only) โ this one warns about constructs that behave differently in traditional C and ISO C ๐ฐ๏ธ It also warns about ISO C constructs that have no traditional C equivalent, and about problematic constructs you should probably avoid. Here's what it catches:- Macro parameters that show up inside string literals in the macro body. Traditional C does macro replacement inside string literals, but ISO C doesn't ๐งต
- Preprocessor directives that traditional C didn't really have. Traditional preprocessors only treated a line as a directive if the
#was in column 1, so-Wtraditionalwarns about directives that traditional C understands but ignores because the#isn't the first character on the line. It also suggests hiding directives like#pragmathat traditional C doesn't understand by indenting them. Some traditional implementations don't recognize#elif, so this option suggests avoiding it altogether ๐ โโ๏ธ - A function-like macro that appears without arguments ๐
- The unary plus operator โ
- The
Uinteger constant suffix, or theForLfloating-point constant suffixes. (Traditional C does support theLsuffix on integer constants.) These suffixes show up in macros defined in the system headers of most modern systems, like the_MIN/_MAXmacros in<limits.h>. Using those macros in user code would normally lead to spurious warnings, but GCC's integrated preprocessor has enough context to avoid warning in these cases ๐ธ - A function declared external in one block and then used after the end of the block ๐งฉ
- A
switchstatement with an operand of typelong๐ - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this ๐ - The ISO type of an integer constant has a different width or signedness from its traditional type. This warning is only issued if the base of the constant is ten, so hexadecimal or octal values (which usually represent bit patterns) don't get warned about ๐ข
- ISO string concatenation usage ๐งถ
- Initialization of automatic aggregates ๐ฆ
- Identifier conflicts with labels. Traditional C doesn't have a separate namespace for labels ๐ท๏ธ
- Initialization of unions. If the initializer is zero, the warning is skipped. This assumes that a zero initializer in user code is conditioned on something like
__STDC__to avoid missing-initializer warnings, and that it relies on default initialization to zero in the traditional C case ๐ซ - Conversions by prototypes between fixed-point and floating-point values, and vice versa. Missing these prototypes when compiling with traditional C causes serious problems. This is a subset of the possible conversion warnings; for the full set, use
-Wtraditional-conversion๐จ - Use of ISO C style function definitions. This warning intentionally isn't issued for prototype declarations or variadic functions, because those ISO C features show up in your code when you use libiberty's traditional C compatibility macros,
PARAMSandVPARAMS. The warning is also skipped for nested functions, since that's already a GCC extension and isn't relevant to traditional C compatibility ๐ง
-Wtraditional-conversion(C and Objective-C only) โ this one warns if a prototype causes a type conversion that's different from what would happen to the same argument without a prototype ๐ That includes fixed-point to floating-point conversions and vice versa, and conversions that change the width or signedness of a fixed-point argument, except when it matches the default promotion ๐ฆ-Wdeclaration-after-statement(C and Objective-C only) โ this one warns when a declaration shows up after a statement in a block ๐ This construct comes from C++, was introduced with ISO C99, and is allowed by default in GCC. It isn't supported by ISO C90. This warning gets upgraded to an error by-pedantic-errors๐-Wshadowโ this one warns whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C), or whenever a built-in function gets shadowed ๐ป In C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows astruct/class/enum. If this warning is enabled, it also includes all instances of local shadowing. That means-Wno-shadow=localand-Wno-shadow=compatible-localare ignored when-Wshadowis used. It's the same as-Wshadow=global๐-Wno-shadow-ivar(Objective-C only) โ this one stops the warning for when a local variable shadows an instance variable in an Objective-C method ๐ โโ๏ธ-Wshadow=globalโ this warns for any shadowing at all, and it's the same as-Wshadow๐-Wshadow=localโ this warns when a local variable shadows another local variable or a parameter ๐-Wshadow=compatible-localโ okay so this one warns when a local variable shadows another local or a parameter whose type is compatible with its own. In C++, "compatible" means the shadowing variable can be converted to the shadowed variable's type. It exists alongside-Wshadow=localbecause when a local shadows one of incompatible type, it's usually on purpose and not a bug or typo. Check out this iterator situation ๐:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two i variables have incompatible types, turning on only -Wshadow=compatible-local gives no warning here. And if someone accidentally swaps one i for the other, type checking should catch it and throw an error or warning. Using this instead of -Wshadow=local can cut down on the noise from intentional shadowing. Heads up, though: shadowing const char *i with char *i also won't trigger a warning with this flag. This warning is also turned on by -Wshadow=local. ๐
-Wlarger-than=byte-sizeโ warns whenever you define an object bigger than byte-size. It's on by default with-Wlarger-than=PTRDIFF_MAX. You can silence these warnings by setting byte-size toSIZE_MAXor more, or by using-Wno-larger-than. It also warns about calls to bounded functions likememchrorstrnlenwhen the bound is bigger than the largest possible object, which isPTRDIFF_MAXbytes by default. Those particular warnings can only be turned off with-Wno-larger-than. ๐ง-Wno-larger-thanโ disables the-Wlarger-than=warnings. It's the same as-Wlarger-than=SIZE_MAXor larger. ๐ซถ-Wframe-larger-than=byte-sizeโ warns if a function's stack frame is bigger than byte-size. Fair warning: the math for the frame size is approximate and not conservative, so the real requirements might be a bit bigger than byte-size even when you get no warning at all. Also, the compiler doesn't count any space fromalloca, variable-length arrays, or similar stuff when it decides whether to warn. It's on by default with-Wframe-larger-than=PTRDIFF_MAX. You can disable these by setting byte-size toSIZE_MAXor more, or by using-Wno-frame-larger-than. ๐ธ-Wno-frame-larger-thanโ disables the-Wframe-larger-than=warnings. Same deal as-Wframe-larger-than=SIZE_MAXor larger. ๐ฆ-Wfree-nonheap-objectโ warns when you try to deallocate something that wasn't allocated on the heap, or when you use a pointer that didn't come back from the matching allocation call. The example below gets flagged becausestpcpyhands back a pointer to the terminating nul character instead of the start of the object, so thefreecall gets caught. It's included in-Wall. ๐ฅ
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wstack-usage=byte-sizeโ warns if a function's stack usage might go over byte-size. This one is conservative, so the compiler does count any space fromalloca, variable-length arrays, or related constructs. The message matches what-fstack-usageoutputs. Here's what you'll see depending on the situation:- If the stack usage is fully static but goes over the limit, you get:
warning: stack usage is 1120 bytes
- If the stack usage is (partly) dynamic but bounded, you get:
warning: stack usage might be 1648 bytes
- If the stack usage is (partly) dynamic and unbounded, you get:
warning: stack usage might be unbounded
It's on by default with -Wstack-usage=PTRDIFF_MAX. You can disable these by setting byte-size to SIZE_MAX or more, or by using -Wno-stack-usage. ๐
-Wno-stack-usageโ disables the-Wstack-usage=warnings. It's the same as-Wstack-usage=SIZE_MAXor larger. โจ-Wunsafe-loop-optimizationsโ warns if a loop can't be optimized because the compiler can't assume anything about the bounds of the loop indices. If you add-funsafe-loop-optimizations, it warns whenever the compiler does make those assumptions instead. ๐-Wno-pedantic-ms-format(MinGW targets only) โ when you combine it with-Wformatand-pedanticwithout GNU extensions, this turns off the warnings about the non-ISOprintf/scanfformat width specifiersI32,I64, andIthat get used on Windows targets. Those depend on the MS runtime, so they're not standard. ๐-Wpointer-arithโ warns about anything that depends on the "size of" a function type or ofvoid. GNU C gives these types a size of 1, which is handy for math withvoid *pointers and pointers to functions. In C++, it also warns when an arithmetic operation involvesNULL. This warning is turned on by-Wpedantic, and-pedantic-errorsupgrades it to an error. ๐ง-Wno-pointer-compareโ stops the warning for when a pointer gets compared with a zero character constant. That usually means you meant to dereference the pointer, so it's a useful catch. Like this:
const char *p = foo ();
if (p == '\0')
return 42;
Heads up that the code above is invalid in C++11. This warning is enabled by default. ๐
-Wno-tsanโ disables warnings about features that ThreadSanitizer doesn't support. Just so you know, ThreadSanitizer doesn't supportstd::atomic_thread_fenceand can report false positives with it. ๐งต-Wtype-limitsโ warns if a comparison is always true or always false because of the limited range of the data type. Constant expressions don't get flagged, though. For example, it'll warn if an unsigned variable gets compared against zero with<or>=. This warning is also turned on by-Wextra. ๐-Wabsolute-value(C and Objective-C only) โ warns when you call a standard function that computes an absolute value, but there's a more appropriate standard function you should be using. For instance, callingabs(3.14)triggers it, because the right function for a double isfabs. It also warns when the argument in one of those calls has an unsigned type. You can get rid of the warning with an explicit type cast, and it's also turned on by-Wextra. ๐-Wcomment,-Wcommentsโ warns whenever a comment-start sequence/*shows up inside a/* comment, or whenever a backslash-newline shows up in a//comment. This warning is turned on by-Wall. ๐-Wtrigraphsโ warns if any trigraphs get encountered that might change what the program means. Trigraphs inside comments don't get warned about, except for the ones that would form escaped newlines. This option is implied by-Wall. If you don't pass-Wall, it's still turned on, unless trigraphs are enabled. If you want trigraph conversion without the warnings but still want the other-Wallwarnings, use-trigraphs -Wall -Wno-trigraphs. ๐-Wundefโ warns if an undefined identifier gets evaluated in an#ifdirective. Those identifiers get replaced with zero. ๐-Wexpansion-to-definedโ warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective. That kind of usage isn't portable. This warning is also turned on by-Wpedanticand-Wextra. โญ-Wunused-macrosโ warns about macros defined in the main file that never get used. A macro counts as used if it gets expanded or tested for existence at least once. The preprocessor also warns if a macro hasn't been used by the time it gets redefined or undefined. Built-in macros, macros defined on the command line, and macros defined in include files don't get warned about.
Note: if a macro is only used inside skipped conditional blocks, the preprocessor still reports it as unused. To avoid that, you could improve the scope of the macro's definition by moving it into the first skipped block, for example. Or you can give it a dummy use with something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ stops the warning for when an#elseor an#endifgets followed by text. This pops up sometimes in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should be in comments. This warning is on by default. ๐ฆ
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a type that doesn't match. For example, it warns if a call to a function that returns an integer type gets cast to a pointer type. ๐ซง-Wc90-c99-compat(C and Objective-C only) โ warns about features that are in ISO C99 but not in ISO C90. Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. This option doesn't depend on the standards mode. Warnings get disabled in the expression that follows__extension__. ๐-Wc99-c11-compat(C and Objective-C only) โ warns about features that are in ISO C11 but not in ISO C99. That includes anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. This option is also independent of the standards mode, and warnings are disabled in the expression that follows__extension__. ๐ท
-Wc11-c23-compat, -Wc11-c2x-compat (C and Objective-C only) โ okay so this one's about stuff that's in ISO C23 but NOT in ISO C11 ๐ธ It'll warn you about things like leaving the string out of _Static_assert, using [[]] attribute syntax, or using decimal floating-point types. It works no matter which standards mode you're in ๐
Warnings get switched off inside the expression after __extension__. Also, heads up: the name -Wc11-c2x-compat is deprecated, so use the c23 one ๐ฅบ And when you're not compiling in C23 mode, -pedantic-errors turns these warnings into full-on errors ๐
-Wc23-c2y-compat (C and Objective-C only) โ same energy, but for stuff in ISO C2Y that isn't in ISO C23 ๐ฆ Example: a _Generic that picks by type name instead of by expression. Also independent of the standards mode, and disabled in the expression after __extension__. When you're not in C2Y mode, -pedantic-errors upgrades these to errors โจ
-Wc++-compat (C and Objective-C only) โ this one checks for ISO C code that steps outside the shared zone of ISO C and ISO C++ ๐ง Like asking for an implicit conversion from void * to a pointer to something that isn't void.
-Wc++11-compat (C++ and Objective-C++ only) โ flags C++ stuff whose meaning changed between ISO C++ 1998 and ISO C++ 2011 ๐ For example, identifiers that were fine in C++98 but are keywords in C++11. This one turns on -Wnarrowing and is enabled by -Wall ๐
-Wc++14-compat (C++ and Objective-C++ only) โ same vibe, but for the change from ISO C++ 2011 to ISO C++ 2014 ๐ Enabled by -Wall.
-Wc++17-compat (C++ and Objective-C++ only) โ checks for things whose meaning shifted from ISO C++ 2014 to ISO C++ 2017 โญ Enabled by -Wall.
-Wc++20-compat (C++ and Objective-C++ only) โ checks the glow-up from ISO C++ 2017 to ISO C++ 2020 ๐ Enabled by -Wall.
-Wc++26-compat (C++ and Objective-C++ only) โ checks for C++ constructs whose meaning differs between ISO C++ 2023 and the upcoming ISO C++ 2026 ๐ฅ Enabled by -Wall.
-Wno-c++11-extensions (C++ and Objective-C++ only) โ if you're compiling with an older C++ standard, this stops the warnings about C++11 constructs ๐ Heads up though: some C++11 constructs only get flagged when you use -Wpedantic, even without this option.
-Wno-c++14-extensions (C++ and Objective-C++ only) โ same deal, but for C++14 constructs in older-standard code ๐ Some of them only get diagnosed with -Wpedantic.
-Wno-c++17-extensions (C++ and Objective-C++ only) โ silences the C++17 construct warnings in older-standard code ๐ฆ Some C++17 constructs still only get flagged with -Wpedantic.
-Wno-c++20-extensions (C++ and Objective-C++ only) โ silences the C++20 construct warnings in older-standard code ๐ธ Some C++20 constructs still only get flagged with -Wpedantic.
-Wno-c++23-extensions (C++ and Objective-C++ only) โ silences the C++23 construct warnings in older-standard code โจ Some C++23 constructs still only get flagged with -Wpedantic.
-Wno-c++26-extensions (C++ and Objective-C++ only) โ silences the C++26 construct warnings in older-standard code ๐
Some C++26 constructs still only get flagged with -Wpedantic.
-Wcast-qual โ this one catches pointer casts that drop a type qualifier from the target type ๐ซถ Like casting a const char * to a plain char *. It also warns when a cast adds a qualifier in an unsafe way. Casting char ** to const char ** is the classic example, and it's not safe:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-align โ warns whenever a pointer cast makes the required alignment of the target bigger ๐ญ For example, casting a char * to an int * on machines where integers can only be accessed at two- or four-byte boundaries. There's also a version that warns about the same char * to int * cast no matter what target machine you're on ๐ฅ
-Wcast-function-type โ warns when a function pointer gets cast to an incompatible function pointer ๐ง For casts involving variadic function types, only the types of the initial arguments that are actually provided get checked. Any pointer-type parameter matches any other pointer-type. Harmless integral differences get ignored, like int vs. long on ILP32 targets, and type qualifiers get ignored too. The function type void (*) (void) is special and matches everything, so it can be used to suppress this warning. For pointer-to-member types, it warns whenever the cast changes the pointer-to-member type. This one's enabled by -Wextra ๐
-Wcast-user-defined โ warns when a cast to a reference type doesn't involve a user-defined conversion you'd probably expect to get called ๐ Like this:
struct A { operator const int&(); } a;
auto r = (int&)a; // warning
This warning is enabled by default ๐
-Wwrite-strings โ when you're compiling C, this gives string constants the type const char[length], so copying one's address into a non-const char * pointer gives you a warning ๐ It can catch code that tries to write into a string constant at compile time, but only if you've been super careful with const in your declarations and prototypes. Otherwise it's just a nuisance ๐ That's why -Wall doesn't ask for it.
When you're compiling C++, it warns about the deprecated conversion from string literals to char *. This is enabled by default for C++ programs, and -pedantic-errors upgrades it to an error in C++11 mode or later ๐
-Wclobbered โ warns about variables that might get changed by longjmp or vfork ๐ญ This one's also enabled by -Wextra.
-Wno-complain-wrong-lang โ normally, language front ends complain when a command-line option is valid but doesn't apply to that front end ๐ You can turn that off with -Wno-complain-wrong-lang. It's mostly handy when you invoke one compiler driver for multiple source files in different languages, like this:
$ g++ -fno-rtti a.cc b.f90
Here the g++ driver hands a.cc to the C++ front end and b.f90 to the Fortran front end. The Fortran one complains with f951: Warning: command-line option '-fno-rtti' is valid for C++/D/ObjC++ but not for Fortran, which may be disabled with -Wno-complain-wrong-lang. This option can also be used to disable warnings like cc1plus: note: CTF debug info requested, but not supported for 'GNU C++20' frontend produced by -gctf or -gsctf for unsupported languages. ๐ง
-Wcompare-distinct-pointer-types (C and Objective-C only) โ warns if pointers of distinct types get compared without a cast ๐ฆ This one's enabled by default.
-Wconversion โ warns about implicit conversions that might change a value ๐ That includes conversions between real and integer types, like abs (x) when x is a double. It also covers conversions between signed and unsigned, like unsigned ui = -1, and conversions to smaller types, like sqrtf (M_PI). It won't warn about explicit casts like abs ((int) x) and ui = (unsigned) -1, or about conversions that don't change the value, like abs (2.0). If the signed/unsigned warnings are too much, you can turn those off with -Wno-sign-conversion ๐ธ
In C++, it also warns about confusing overload resolution for user-defined conversions, plus conversions that never use a type conversion operator: conversions to void, to the same type, to a base class, or to a reference to any of those. The signed/unsigned conversion warnings are disabled by default in C++ unless you explicitly enable -Wsign-conversion ๐
And warnings about conversion from arithmetic on a small type back to that same type only show up with -Warith-conversion โจ
-Wdangling-else โ warns about code where it might be unclear which if an else branch belongs to ๐ Here's an example that's confusing:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C/C++, every else branch belongs to the innermost possible if statement, which in this example is if (b). That's often not what the programmer expected, even though the indentation suggests otherwise ๐ When there's potential for this confusion, GCC warns if you specify this flag. To get rid of the warning, add explicit braces around the innermost if statement, so the else can't possibly belong to the enclosing if. The fixed code looks like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses ๐
-Wdangling-pointer, -Wdangling-pointer=n โ warns about using pointers (or C++ references) to objects with automatic storage duration after their lifetime has ended ๐ป That includes local variables declared in nested blocks, compound literals, and other unnamed temporary objects. It also warns about storing the address of those objects in escaped pointers. This warning is enabled at all optimization levels, but it may give different results with optimization than without ๐ซ
-Wdangling-pointer=1โ at level 1, it only diagnoses unconditional uses of dangling pointers ๐ง
-Wdangling-pointer=2โ bestie, level 2 is the full drama ๐ญ It catches everything level 1 does, plus the conditional uses of dangling pointers too โจ
The short form -Wdangling-pointer is the same as -Wdangling-pointer=2. Meanwhile -Wno-dangling-pointer and -Wdangling-pointer=0 both switch the warnings off ๐
โโ๏ธ And -Wdangling-pointer=2 is already included in -Wall ๐
Okay, this example triggers the warning at level 1 ๐ฅ The address of the unnamed temporary gets referenced unconditionally outside of its scope, and that's a whole mess ๐ญ
char f (char c1, char c2, char c3)
{
char *p;
{
p = (char[]) { c1, c2, c3 };
}
// warning: using dangling pointer 'p' to an unnamed temporary
return *p;
}
In this next function, storing the address of the local variable "x" into the escaped pointer *p triggers the warning at level 1 ๐
void g (int **p)
{
int x = 7;
// warning: storing the address of local variable 'x' in '*p'
*p = &x;
}
Here the array a is out of scope by the time the pointer s gets used ๐ Since the code that sets "s" is conditional, this one only triggers at level 2 ๐ฆ
extern void frob (const char *);
void h (char *s)
{
if (!s)
{
char a[12] = "tmpname";
s = a;
}
// warning: dangling pointer 's' to 'a' may be used
frob (s);
}
-Wdate-timeโ warns when the macros__TIME__,__DATE__or__TIMESTAMP__show up ๐ฐ๏ธ They can make it impossible to get bitwise-identical reproducible compilations, so this one's a vibe check for your build ๐ง-Wempty-bodyโ flags an empty body in anif,elseordo whilestatement ๐ซฅ This warning is also turned on by-Wextraโจ-Wno-endif-labelsโ chill out and don't warn about stray tokens after#elseand#endif๐ธ-Wenum-compareโ warns about a comparison between values of different enumerated types ๐ In C++, enum mismatches in conditional expressions get diagnosed too, and this one's enabled by default there ๐ In C, it's turned on by-Wall๐ฅ-Wenum-conversionโ warns when a value of enumerated type gets implicitly converted into a different enumerated type ๐ฆ In C, this is enabled by-Wextra๐ซถ-Wenum-int-mismatch(C and Objective-C only) โ warns about mismatches between an enumerated type and an integer type in declarations ๐ง Like, this is the kind of messy situation I mean:
enum E { l = -1, z = 0, g = 1 };
int foo(void);
enum E foo(void);
In C, an enumerated type is compatible with char, a signed integer type, or an unsigned integer type ๐ But the underlying type of an enumerated type is implementation-defined, so these mismatches can cause portability issues ๐ญ In C++, though, they're an error โ In C, this warning is enabled by -Wall and -Wc++-compat ๐
-Wjump-misses-init(C, Objective-C only) โ warns if agotoor aswitchstatement jumps forward across the initialization of a variable, or jumps backward to a label after the variable has already been initialized ๐ It only cares about variables that are initialized when they're declared ๐ This one is only supported for C and Objective-C, because in C++ this kind of branch is an error anyway ๐
-Wjump-misses-init is included in -Wc++-compat โจ And it can be disabled with the -Wno-jump-misses-init option ๐ซง
-Wsign-compareโ warns when a comparison between signed and unsigned values could give an incorrect result, because the signed value gets converted to unsigned ๐ง In C++, it's also enabled by-Wall๐ In C, it's enabled by-Wextra๐ธ-Wsign-conversionโ warns about implicit conversions that might change the sign of an integer value ๐ Think assigning a signed integer expression to an unsigned integer variable ๐ An explicit cast silences it ๐ซถ In C, this option is also turned on by-Wconversionโจ-Wflex-array-member-not-at-end(C and C++ only) โ warns when a structure with a C99 flexible array member as its last field ends up not at the end of another structure ๐ฆ For example:
struct flex { int length; char data[]; };
struct mid_flex { int m; struct flex flex_data; int n; };
-Wfloat-conversionโ warns about implicit conversions that reduce the precision of a real value ๐ That includes real-to-integer conversions, and going from higher precision real values down to lower precision ones ๐ฅ This is also enabled by-Wconversion๐ซถ-Wno-scalar-storage-orderโ doesn't warn about suspicious constructs involving reverse scalar storage order ๐-Wsizeof-array-divโ warns about dividing twosizeofoperators when the first one is applied to an array and the divisor doesn't match the size of the array element ๐งฎ The computation won't give you the number of elements in the array, which is probably not what you meant ๐ญ For example, this function would get flagged:
int fn ()
{
int arr[10];
return sizeof (arr) / sizeof (short);
}
This warning is enabled by -Wall ๐
-Wsizeof-pointer-divโ warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size ๐ซ That's usually how you'd compute an array size, but it won't work right with pointers ๐ It warns e.g. aboutsizeof (ptr) / sizeof (ptr[0])whenptris a pointer and not an array ๐ This warning is enabled by-Wallโจ-Wsizeof-pointer-memaccessโ warns about suspicious length parameters passed to certain string and memory built-in functions when the argument usessizeof๐ง It triggers for things likememset (ptr, 0, sizeof (ptr));whenptris a pointer and not an array, and it'll even suggest a possible fix ๐ ๏ธ It also catches stuff likememcpy (&foo, ptr, sizeof (&foo));๐
It also warns about calls to bounded string copy functions like strncat or strncpy that use a sizeof expression of the source array as the bound ๐จ In the following function, the strncat call uses the size of the source string as its bound, which is almost certainly a mistake, so the call gets diagnosed ๐
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall ๐
-Wno-sizeof-array-argumentโ don't warn when thesizeofoperator gets applied to a parameter that's declared as an array in a function definition ๐ซถ This warning is enabled by default for C and C++ programs ๐-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function where the first argument references an array, and the third argument is a number equal to the number of elements but not equal to the size of the array in memory ๐ค That means you probably forgot to multiply by the element size ๐ This warning is enabled by-Wall๐ฆ-Wmemset-transposed-argsโ warns about suspicious calls tomemsetwhere the second argument isn't zero and the third argument is zero ๐ For example,memset (buf, sizeof buf, 0)gets diagnosed, becausememset (buf, 0, sizeof buf)was what was meant ๐ The diagnostic is only emitted if the third argument is a literal zero ๐ฏ If it's an expression that folds to zero, or a cast of zero to some type, the args are way less likely to be mixed up, so no warning shows up ๐ โโ๏ธ This warning is enabled by-Wall๐-Waddressโ warns about suspicious uses of address expressions ๐ These are the sus ones you'll want to know about:
Comparing the address of a function or a declared object to the null pointer constant, like this, is one of them ๐ง
void f (void);
void g (void)
{
if (!f) // warning: expression evaluates to false
abort ();
}
Comparing a pointer to a string literal is another, like this ๐
void f (const char *x)
{
if (x == "abc") // warning: expression evaluates to false
puts ("equal");
}
And testing the result of pointer addition or subtraction for equality to null is also on the list ๐
void f (const int *p, int i)
{
return p + i == NULL;
}
These uses usually mean the programmer made a mistake ๐ฉ The address of most functions and objects always evaluates to true (the exception is weak symbols), so putting them in a conditional might mean you're missing parentheses in a function call, or a dereference in an array expression ๐ญ
The object pointer part of this warning can be suppressed by casting the pointer operand to an integer type, such as intptr_t or uintptr_t ๐ง Comparisons against string literals result in unspecified behavior and aren't portable, and they usually suggest you meant to call strcmp ๐ธ The warning is suppressed if the suspicious expression comes out of a macro expansion ๐ซง -Waddress is enabled by -Wall ๐
-Wno-address-of-packed-memberโ don't warn when the address of a packed member of a struct or union is taken ๐ง That usually gives you an unaligned pointer value, but this is enabled by default, so you're already covered โจ-Wlogical-opโ warns about suspicious uses of logical operators in expressions ๐ง That includes using logical operators where a bitwise operator is probably what was expected ๐ It also warns when the operands of a logical operator are the same, like this:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns about a logical not used on the left hand side operand of a comparison ๐ It doesn't warn if the right operand is considered to be a boolean expression ๐ซถ Its whole purpose is to catch sus code like this:
int a;
...
if (!a > 1) { ... }
It is possible to suppress the warning by wrapping the LHS into parentheses, bestie ๐ซถ โจ
if ((!a) > 1) { ... }
This warning is enabled by -Wall ๐
-Waggregate-returnโ okay so this one warns if any functions that return structs or unions are defined or called ๐ In languages where you can return an array, this also triggers a warning ๐ธ-Wno-aggressive-loop-optimizationsโ this turns off the warning when the compiler spots undefined behavior inside a loop that has a constant number of iterations ๐ Heads up,-Waggressive-loop-optimizationsis already on by default โจ-Wno-attributesโ no warning if an unexpected__attribute__shows up, like unrecognized attributes or function attributes slapped onto variables, etc. ๐ฆ It won't stop errors for wrong use of attributes that are supported though ๐ญ Also, warnings about ill-formed uses of standard attributes get upgraded to errors by-pedantic-errorsโ
Next level: using -Wno-attributes= lets you silence warnings about unknown scoped attributes (in C++11 and C23) ๐ง For example, -Wno-attributes=vendor::attr disables the warning for this declaration:
[[vendor::attr]] void f();
Or if you want the whole namespace gone, -Wno-attributes=vendor:: stops the warnings for both of these:
[[vendor::safe]] void f();
[[vendor::unsafe]] void f2();
Lowkey important: -Wno-attributes= does not imply -Wno-attributes ๐
-Wno-builtin-declaration-mismatchโ this one warns if a built-in function gets declared with an incompatible signature or as a non-function ๐ฅ It also fires when a built-in function declared with a type that has no prototype gets called with arguments whose promoted types don't match what the function expects ๐ With-Wextra, it also warns when a built-in function that takes arguments is declared without a prototype ๐ The-Wbuiltin-declaration-mismatchwarning is on by default, but to dodge it, just include the right header so the built-in function prototypes are in scope ๐ซถ
Here's the drama: the memset call below gets caught because the function wants a size_t argument, but 32 is an int ๐ญ With -Wextra, the declaration itself gets flagged too ๐
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ don't warn if certain built-in macros get redefined ๐ This quiets warnings for redefining__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__๐-Wkeyword-macroโ warns if a keyword gets defined as a macro or undefined ๐ For C++, identifiers with special meaning or standard attribute identifiers get called out too โจ This one is enabled by default for C++26 if-Wpedanticis on, and it emits a pedwarn in that case ๐ฅ-Wfree-labels(C and Objective-C only) โ warns if a label is applied to a non-statement, or sits at the end of a compound statement ๐ฆ C23 and later allow these labels, and GCC offers them as an extension in every other dialect ๐ธ This warning is also turned on by-Wc11-c23-compat, and-pedantic-errorsturns it into an error if you're building for a C version before C23 ๐-Wheader-guardโ this warns if a valid multiple inclusion guard in a preprocessor header has a#defineright after the#ifndefor#if !defineddirective, and that#definedefines a different macro with a similar name ๐ The real guard macro also isn't defined at the matching#ifndefat the end of the header, and the#definemakes an object-like macro with an empty definition ๐ซ Usually that means it's just a misspelled guard name, either in the#ifndefor#if !definedline or in the#defineafter it ๐ญ This warning is enabled by-Wall๐-Wstrict-prototypes(C and Objective-C only) โ warns if a function is declared or defined without specifying the argument types ๐ธ An old-style function definition is allowed without a warning if it's preceded by a declaration that does specify the argument types ๐ง-Wold-style-declaration(C and Objective-C only) โ warns about obsolescent usages in a declaration, according to the C Standard ๐ For example, it warns if storage-class specifiers likestaticaren't the first things in a declaration ๐ This warning is also enabled by-Wextraโจ-Wold-style-definition(C and Objective-C only) โ warns if an old-style function definition is used ๐ฆ It warns even if there's already a previous prototype ๐ A definition using()isn't treated as old-style in C23 mode, since it's equivalent to(void)there, but it is treated as old-style for older standards ๐-Wmultiple-parameter-fwd-decl-lists(C and Objective-C only) โ warns if more than one list of forward declarations of parameters shows up in a function prototype ๐ This warning is also enabled by-Wextra๐ซถ-Wdeprecated-non-prototype(C and Objective-C only) โ warns if a function declared with an empty parameter list()gets called with one or more arguments, or if a function definition with one or more parameters shows up after such a declaration ๐ญ Both cases are errors in C23 and later dialects of C ๐ This warning is also enabled by-Wc11-c23-compatโจ-Wmissing-parameter-name(C and Objective-C only) โ warns if a function definition leaves out a parameter name and only gives its type ๐ง This can be handy for documenting that a parameter goes unused in the definition ๐ It's part of C23 and later dialects of C, and GCC offers it as an extension in all other dialects ๐ This warning is also enabled by-Wc11-c23-compat, and-pedantic-errorsmakes it an error if you're building for a C version before C23 ๐-Wmissing-parameter-type(C and Objective-C only) โ warns when a function parameter has no type specifier in K&R-style functions, like this ๐
void foo(bar) { }
This warning is also enabled by -Wextra ๐ฅ
-Wno-declaration-missing-parameter-type(C and Objective-C only) โ no warning if a function declaration has a parameter name without a type ๐ These declarations don't give you a function prototype, so they block most type checking in function calls ๐ This warning is on by default ๐ซ In C99 and later dialects of C, it's treated as an error ๐ญ You can downgrade it to a warning with-fpermissive(along with certain other errors), or for this error alone with-Wno-error=declaration-missing-parameter-type๐ซถ-pedantic-errorsupgrades this warning to an error ๐-Wmissing-prototypes(C and Objective-C only) โ warns if a global function gets defined without a previous prototype declaration ๐ฆ It warns even if the definition itself has a prototype ๐ Use this one to catch global functions that don't have a matching prototype declaration in a header file ๐ธ It isn't valid for C++, since all function declarations there provide prototypes, and a non-matching declaration declares an overload instead of conflicting with an earlier one ๐ง For missing declarations in C++, use-Wmissing-declarationsinstead ๐-Wmissing-variable-declarations(C and Objective-C only) โ warns if a global variable gets defined without a previous declaration ๐ Use it to find global variables that don't have a matchingexterndeclaration in a header file ๐-Wmissing-declarationsโ warns if a global function gets defined without a previous declaration, even if the definition itself has a prototype ๐ Use this to catch global functions that aren't declared in header files โจ In C, no warnings are issued for functions with previous non-prototype declarations, so use-Wmissing-prototypesfor those ๐ฆ In C++, no warnings are issued for function templates, inline functions, or functions in anonymous namespaces ๐-Wmissing-field-initializersโ warns if a struct's initializer is missing some fields ๐ซ In this example, the code triggers the warning becausex.his implicitly zero:
struct s { int f, g, h; };
struct s x = { 3, 4 };
In C, this option doesn't warn about designated initializers, so this one is fine:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, it also doesn't warn about the universal zero initializer { 0 }:
struct s { int f, g, h; };
struct s x = { 0 };
Likewise, in C++ this option doesn't warn about the empty { } initializer, for example:
struct s { int f, g, h; };
s x = { };
This warning is included in -Wextra ๐
If you want the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers ๐ธ
-Wno-missing-requiresโ by default, the compiler warns about a concept-id showing up as a C++20 simple-requirement ๐ Like here:
bool satisfied = requires { C<T> };
satisfied will be true if C<T> is a valid expression, which it is for all T ๐ซ Presumably the user meant to write this instead:
bool satisfied = requires { requires C<T> };
so satisfied is only true if concept C is satisfied for type T ๐ You can turn off this warning with -Wno-missing-requires ๐ง
-Wno-missing-template-keywordโ the member access tokens.,->and::need to be followed by thetemplatekeyword if the parent object is dependent and the member being named is a template ๐ฆ Here's the vibe check:
template <class X>
void DoStuff (X x)
{
x.template DoSomeOtherStuff<X>(); // Good.
x.DoMoreStuff<X>(); // Warning, x is dependent.
}
In rare cases you can get false positives ๐ To silence them, wrap the expression in parentheses ๐ซถ For example, the following is treated as a template, even where m and N are integers:
void NotATemplate (my_class t)
{
int N = 5;
bool test = t.m < N > (0); // Treated as a template.
test = (t.m < N) > (0); // Same meaning, but not treated as a template.
}
Psst, you can totally switch that one off with -Wno-missing-template-keyword if it's being extra. ๐
-Wno-multicharโ bestie, don't warn if a multicharacter constant like'FOOF'shows up. ngl these are usually a typo in your code ๐, since their values are implementation-defined and they shouldn't be in portable code anyway.-Wnormalized=[none|id|nfc|nfkc]โ okay so, in ISO C and ISO C++, two identifiers are different if they're different sequences of characters. BUT when you use characters outside basic ASCII, you can end up with two totally different sequences that look the same ๐ญ. The ISO 10646 standard has normalization rules that turn lookalikes into the same sequence, and GCC can warn you if your identifiers aren't normalized. This option controls that warning. There are four levels.- The default is
-Wnormalized=nfc, which warns about any identifier that isn't in the ISO 10646 "C" normalized form, NFC. NFC is the recommended form for most uses, and it's equivalent to-Wnormalized. โจ - Unfortunately, some characters that ISO C and C++ allow in identifiers stop being allowed once they're turned into NFC. So there's no way to use these symbols in portable ISO C or C++ and keep all your identifiers in NFC.
-Wnormalized=idsuppresses the warning for these characters. It's hoped that future versions of the standards will fix this, which is why it isn't the default. ๐ฅบ - You can switch the warning off for all characters with
-Wnormalized=noneor-Wno-normalized. Only do this if you're using some other normalization scheme (like "D"), because otherwise you can easily create bugs that are literally impossible to see. ๐ - Some ISO 10646 characters have distinct meanings but look identical in some fonts or display methods, especially once formatting is applied. For instance,
"\u207F", "SUPERSCRIPT LATIN SMALL LETTER N", displays just like a regular "n" that's been placed in a superscript. ISO 10646 defines the NFKC normalization scheme to convert all of these into a standard form too, and GCC warns if your code isn't in NFKC when you use-Wnormalized=nfkc. This is comparable to warning about every identifier that contains the letter O because it might be confused with the digit 0, so it isn't the default. It can still be a useful local coding convention if the programming environment can't be fixed to display these characters distinctly. ๐
- The default is
-Wno-attribute-warningโ no warnings about using functions declared with the "warning" attribute. This warning is enabled by default, but-Wno-attribute-warningcan turn it off, or-Wno-error=attribute-warningcan turn off the error when you compile with the-Werrorflag. ๐-Wno-deprecatedโ no warnings about using deprecated features.- In C++, explicitly specifying
-Wdeprecatedalso enables warnings about some features that are deprecated in later language standards, specifically-Wcomma-subscript,-Wvolatile,-Wdeprecated-enum-float-conversion,-Wdeprecated-enum-enum-conversion,-Wdeprecated-literal-operator, and-Wdeprecated-variadic-comma-omission.
- In C++, explicitly specifying
-Wno-deprecated-declarationsโ no warnings when you use functions, variables, or types marked as deprecated with the "deprecated" attribute. ๐-Wno-deprecated-openmpโ no warnings about deprecated OpenMP code.-Wno-overflowโ no warnings about compile-time overflow in constant expressions.-Wno-odrโ warns about One Definition Rule violations during link-time optimization. Enabled by default.
Heads up, bestie: the-Wno-in the name of-Wno-odrand-Wno-openmpdoesn't match what their descriptions say. Read the description, not just the name, or you'll be confused ๐.
-Wopenacc-parallelismโ warns about potentially suboptimal choices related to OpenACC parallelism. โญ-Wno-openmpโ warns about suspicious OpenMP code.-Wopenmp-simdโ warns if the vectorizer cost model overrides the OpenMP simd directive that the user set. The-fsimd-cost-model=unlimitedoption can be used to relax the cost model. ๐-Woverride-init(C and Objective-C only) โ warns if an initialized field without side effects is overridden when using designated initializers.- This warning is included in
-Wextra. To get the other-Wextrawarnings without this one, use-Wextra -Wno-override-init.
- This warning is included in
-Wno-override-init-side-effects(C and Objective-C only) โ no warning if an initialized field with side effects is overridden when using designated initializers. This warning is enabled by default.-Wpackedโ warns if a structure is given the packed attribute, but the packed attribute has no effect on the layout or size of the structure. Those structures can end up misaligned for little benefit. For instance, in this code, the variable "f.x" in "struct bar" is misaligned even though "struct bar" doesn't itself have the packed attribute:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wnopacked-bitfield-compatโ the 4.1, 4.2, and 4.3 series of GCC ignored the "packed" attribute on bit-fields of type "char". This got fixed in GCC 4.4, but the change can lead to differences in structure layout. GCC tells you when the offset of such a field has changed in GCC 4.4. For example, there's no longer a 4-bit padding between field "a" and "b" in this structure:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default. Use -Wno-packed-bitfield-compat to disable this warning. ๐ฆ
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ warns if a structure field with explicitly specified alignment in a packed struct or union is misaligned. For example, a warning will be issued on "struct S", like "warning: alignment 1 of 'struct S' is less than 8", in this code:
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall.
-Wpaddedโ warns if padding is included in a structure, either to align an element of the structure or to align the whole structure. Sometimes it's possible to rearrange the fields of the structure to reduce the padding and make it smaller. ๐ธ-Wredundant-declsโ warns if anything is declared more than once in the same scope, even in cases where multiple declarations are valid and change nothing.-Wrestrictโ warns when an object referenced by a "restrict"-qualified parameter (or, in C++, a "__restrict"-qualified parameter) is aliased by another argument, or when copies between such objects overlap. In the example below, thestrcpycall tries to truncate the string by replacing its initial characters with the last four. But because the call writes the terminating NUL into "a[4]", the copies overlap and the call gets diagnosed:
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
The -Wrestrict option detects some instances of simple overlap even without optimization, but it works best at -O2 and above. It's included in -Wall. ๐ฅ
-Wnested-externs(C and Objective-C only) โ warns if an "extern" declaration is encountered within a function.-Winlineโ warns if a function that is declared as inline cannot be inlined. Even with this option, the compiler does not warn about failures to inline functions declared in system headers.- The compiler uses a variety of heuristics to decide whether or not to inline a function. For example, it takes into account the size of the function being inlined and the amount of inlining that has already been done in the current function. So seemingly insignificant changes in the source program can make the
-Winlinewarnings appear or disappear. ๐
- The compiler uses a variety of heuristics to decide whether or not to inline a function. For example, it takes into account the size of the function being inlined and the amount of inlining that has already been done in the current function. So seemingly insignificant changes in the source program can make the
-Winterference-size,-Wno-interference-sizeโ warns about questionable uses of the C++17 "constexpr" variables "std::hardware_destructive_interference_size" and "std::hardware_constructive_interference_size". These variables are meant for controlling class layout, to avoid false sharing in concurrent code, like this:
struct independent_fields {
alignas(std::hardware_destructive_interference_size)
std::atomic<int> one;
alignas(std::hardware_destructive_interference_size)
std::atomic<int> two;
};
Here, "one" and "two" are intended to be far enough apart that stores to "one" won't require accesses to the other to reload the cache line. ๐ง
By default, these variables are given values based on the current -mtune option, typically the L1 cache line size for the particular target CPU, and sometimes a range if tuning for a generic target. So all translation units that depend on ABI compatibility for the use of these variables must be compiled with the same -mtune (or -mcpu).
If ABI stability is important, such as if the use is in a header for a library, you should probably not use the hardware interference size variables at all.
These warnings are enabled by default. If you're confident that your use of these variables does not affect ABI outside a single build of your project, you can turn off the warning with -Wno-interference-size.
-Wint-in-bool-contextโ warns about suspicious use of integer values where boolean values are expected. Examples include conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3), or left shifting of signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. It's likewise for all kinds of multiplications, regardless of the data type. This warning is enabled by-Wall. ๐-Wno-int-to-pointer-castโ suppresses warnings from casts to pointer type of an integer of a different size. In C++, casting to a pointer type of smaller size is an error.Wint-to-pointer-castis enabled by default. ๐ซถ-Wno-pointer-to-int-cast(C and Objective-C only) โ bestie, this one silences the warning for casting a pointer to an integer type of a different size ๐-Winvalid-pchโ ooh, this warns you if a precompiled header is sitting in the search path but GCC can't actually use it ๐ฆ-Winvalid-utf8โ flags any invalid UTF-8 character. It's on by default for C++23 when-finput-charset=UTF-8is used, and it becomes a full-on error with-pedantic-errors๐-Wno-unicodeโ skips complaining about invalid forms of delimited or named escape sequences that get treated as separate tokens. Heads up:-Wunicodeis already on by default โจ-Wlong-longโ warns when thelong longtype shows up. It's switched on by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. If you want it quiet, use-Wno-long-long๐ธ
This one gets promoted to an error by -pedantic-errors, so be careful, bestie ๐ญ
-Wvariadic-macrosโ warns if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode. It's enabled by either-Wpedanticor-Wtraditional, and you can shush it with-Wno-variadic-macros๐-Wno-varargsโ stops the warnings about questionable usage of the macros that handle variable arguments, likeva_start. These are on by default, so this is how you turn them off ๐ง-Wvector-operation-performanceโ warns if a vector operation isn't implemented through the architecture's SIMD capabilities. It's mainly for performance tuning, and the vibes are: a vector op can be done "piecewise", which means the scalar op runs on every vector element; "in parallel", which means the vector op uses scalars of a wider type (usually way more performance efficient); or "as a single scalar", which means the vector fits into a scalar type ๐ฅ-Wvlaโ warns if a variable-length array is used anywhere in the code.-Wno-vlastops the-Wpedanticwarning about variable-length arrays. This one gets upgraded to an error by-pedantic-errors๐-Wvla-larger-than=byte-sizeโ when you use this, the compiler warns about declarations of variable-length arrays whose size is either unbounded, or bounded by an argument that lets the array size go over byte-size bytes. It's kind of like how-Walloca-larger-than=byte-sizeworks, but for VLAs ๐
Real talk though: GCC may optimize small variable-length arrays with a known value into plain arrays, so this warning might not fire for those ones ๐
-Wvla-larger-than=PTRDIFF_MAX is on by default, but it's typically only effective when -ftree-vrp is active (which is the default for -O2 and above) โจ
See also -Walloca-larger-than=byte-size.
-Wno-vla-larger-thanโ turns off the-Wvla-larger-than=warnings. It's the same as-Wvla-larger-than=SIZE_MAXor larger ๐-Wvla-parameterโ warns about redeclarations of functions that have variable-length array arguments of inconsistent kinds or forms, and it also turns on detection of out-of-bounds accesses to those parameters through warnings like-Warray-bounds๐ฆ
If the first function declaration uses the VLA form, the bound in the array is assumed to be the minimum number of elements expected in calls to the function, and also the maximum number of elements it accesses. Not providing arguments of sufficient size, or accessing more than that max, may get diagnosed ๐ญ
Here's the example, exactly as written, so you can see the chaos in action:
void f (int n, int[n]);
// warning: argument 2 previously declared as a VLA
void f (int, int[]);
void g (int n)
{
if (n > 4)
return;
int a[n];
// warning: access to a by f may be out of bounds
f (sizeof a, a);
...
}
The warning triggers for these redeclarations because the first one lets an array of any size get passed to f, while the second one says the array argument has to have at least n elements. On top of that, calling f with the associated VLA bound parameter larger than the actual VLA bound also triggers a warning ๐
-Wvla-parameter is included in -Wall. For similar problems with ordinary array arguments, -Warray-parameter is the one that warns ๐
-Wvolatile-register-varโ warns if a register variable is declaredvolatile. Real tea: thevolatilemodifier doesn't stop every optimization that might eliminate reads and/or writes to register variables. This warning is enabled by-Wallโ-Wno-xor-used-as-pow(C, C++, Objective-C and Objective-C++ only) โ disables the warnings about uses of^, the exclusive or operator, when it looks like the code meant exponentiation. Specifically, it fires when the left-hand side is the decimal constant2or10and the right-hand side is also a decimal constant ๐ค
In C and C++, ^ means exclusive or, but in some other languages (like TeX and some versions of BASIC) it means exponentiation. Iykyk ๐ซถ
You can silence this warning by converting one of the operands to hexadecimal, and also by compiling with -Wno-xor-used-as-pow.
-Wdisabled-optimizationโ warns if a requested optimization pass is disabled. Don't panic, this doesn't usually mean your code is wrong ๐ธ It just means GCC's optimizers can't handle the code effectively. Often the problem is that your code is too big or too complex, and GCC refuses to optimize programs when the optimization would likely take inordinate amounts of time ๐ข-Wpointer-sign(C and Objective-C only) โ warns for pointer argument passing or assignment with different signedness. It's only supported for C and Objective-C. It's implied by-Walland by-Wpedantic, and you can disable it with-Wno-pointer-sign๐
This warning is upgraded to an error by -pedantic-errors.
-Wstack-protectorโ only active when-fstack-protectoris active. It warns about functions that aren't protected against stack smashing ๐ก๏ธ-Woverlength-stringsโ warns about string constants longer than the "minimum maximum" length the C standard specifies. Modern compilers usually allow way longer strings than the standard's minimum, but very portable programs should avoid them ๐งต
The limit applies after string constant concatenation, and it doesn't count the trailing NUL. In C90, the limit was 509 characters. In C99, it got raised to 4095. C++98 doesn't specify a normative minimum maximum, so GCC doesn't diagnose overlength strings in C++ ๐
This option is implied by -Wpedantic, and you can disable it with -Wno-overlength-strings.
-Wunsuffixed-float-constants(C and Objective-C only) โ warns about any floating constant that doesn't have a suffix. If you pair it with-Wsystem-headers, it also warns about those constants in system header files ๐ This is super useful when you're prepping code to use with theFLOAT_CONST_DECIMAL64pragma from the decimal floating-point extension to C99.-Wno-lto-type-mismatchโ during link-time optimization, this stops GCC from warning about type mismatches in global declarations from different compilation units. It requires-fltoto be enabled, and it's enabled by default โจ-Wno-designated-init(C and Objective-C only) โ suppresses warnings when a positional initializer is used to initialize a structure that's been marked with thedesignated_initattribute ๐
โจ Options That Control Static Analysis โจ
-fanalyzerโ okay, this one turns on a static analysis of program flow. It hunts for "interesting" interprocedural paths through the code and drops warnings for problems it finds on them ๐
Heads up, it's way more expensive than other GCC warnings ๐ธ
Technically speaking, it does coverage-guided symbolic execution of the code being compiled. It's neither sound nor complete, which means it can have false positives and false negatives. It's a bug-finding tool, not a tool for proving program correctness ๐ซ
The analyzer is only suitable for C code in this release.
Enabling this option effectively enables the following warnings:
-Wanalyzer-allocation-size -Wanalyzer-deref-before-check
-Wanalyzer-double-fclose -Wanalyzer-double-free
-Wanalyzer-exposure-through-output-file
-Wanalyzer-exposure-through-uninit-copy
-Wanalyzer-fd-access-mode-mismatch -Wanalyzer-fd-double-close
-Wanalyzer-fd-leak -Wanalyzer-fd-phase-mismatch
-Wanalyzer-fd-type-mismatch -Wanalyzer-fd-use-after-close
-Wanalyzer-fd-use-without-check -Wanalyzer-file-leak
-Wanalyzer-free-of-non-heap -Wanalyzer-imprecise-fp-arithmetic
-Wanalyzer-infinite-loop -Wanalyzer-infinite-recursion
-Wanalyzer-jump-through-null -Wanalyzer-malloc-leak
-Wanalyzer-mismatching-deallocation -Wanalyzer-null-argument
-Wanalyzer-null-dereference -Wanalyzer-out-of-bounds
-Wanalyzer-overlapping-buffers -Wanalyzer-possible-null-argument
-Wanalyzer-possible-null-dereference -Wanalyzer-putenv-of-auto-var
-Wanalyzer-shift-count-negative -Wanalyzer-shift-count-overflow
-Wanalyzer-stale-setjmp-buffer -Wanalyzer-tainted-allocation-size
-Wanalyzer-tainted-array-index -Wanalyzer-tainted-assertion
-Wanalyzer-tainted-divisor -Wanalyzer-tainted-offset
-Wanalyzer-tainted-size -Wanalyzer-throw-of-unexpected-type
-Wanalyzer-undefined-behavior-ptrdiff
-Wanalyzer-undefined-behavior-strtok
-Wanalyzer-unsafe-call-within-signal-handler
-Wanalyzer-use-after-free
-Wanalyzer-use-of-pointer-in-stale-stack-frame
-Wanalyzer-use-of-uninitialized-value
-Wanalyzer-va-arg-type-mismatch -Wanalyzer-va-list-exhausted
-Wanalyzer-va-list-leak -Wanalyzer-va-list-use-after-va-end
-Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal
This option is only available if GCC was configured with analyzer support enabled.
-Wanalyzer-symbol-too-complexโ if-fanalyzeris enabled, the analyzer uses various heuristics to try to track the state of memory. But sufficiently complicated code can defeat those heuristics ๐
By default, the analysis quietly gives up on tracking expression values once they blow past an internal limit ๐, and it falls back to an imprecise representation for them. The -Wanalyzer-symbol-too-complex option is the one that actually warns you when this happens ๐ซถ
-Wanalyzer-too-complexโ the analyzer's explorer brain getting overwhelmed ๐ง
If -fanalyzer is on, the analyzer uses a bunch of heuristics to poke around the control flow and data flow of your program โจ. But sufficiently complicated code can totally defeat them ๐.
By default, if the code is too complicated for the analyzer to fully explore and it hits an internal limit, the analysis just stops, no fuss. -Wanalyzer-too-complex makes it warn you instead ๐ข.
-Wno-analyzer-allocation-sizeโ flags buffer sizes that don't line up with the pointer type ๐
This warning requires -fanalyzer, which enables it; to disable it, use -Wno-analyzer-allocation-size.
This diagnostic warns for paths through the code where a pointer to a buffer gets assigned to point at a buffer whose size isn't a multiple of sizeof (*pointer).
๐ See CWE-131: Incorrect Calculation of Buffer Size (https://cwe.mitre.org/data/definitions/131.html).
-Wno-analyzer-deref-before-checkโ catchesNULLchecks that show up after the pointer was already dereferenced ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-deref-before-check to disable it.
This diagnostic warns for paths through the code where a pointer is checked for NULL after it has already been dereferenced, which suggests the pointer could have been NULL. Cases like this mean the NULL check is either redundant, or it needs to be moved to before the pointer is dereferenced.
This diagnostic also considers values passed to a function argument marked with __attribute__((nonnull)) as requiring a non-NULL value, so it'll complain if such values get checked for NULL after returning from that function call.
โ ๏ธ This diagnostic is unlikely to be reported when any level of optimization is enabled, because GCC's optimization logic typically considers those NULL checks redundant and optimizes them away before the analyzer "sees" them. So you should disable optimization when you're trying to trigger this one ๐
-Wno-analyzer-double-fcloseโ yells when aFILE *getsfclosed more than once ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-double-fclose to disable it.
This diagnostic warns for paths through the code where a FILE * can have fclose called on it more than once.
๐ See CWE-1341: Multiple Releases of Same Resource or Handle (https://cwe.mitre.org/data/definitions/1341.html).
-Wno-analyzer-double-freeโ spots pointers that get freed twice ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-double-free to disable it.
This diagnostic warns for paths through the code where a pointer can have a deallocator called on it more than once, either free, or a deallocator referenced by attribute malloc.
๐ See CWE-415: Double Free (https://cwe.mitre.org/data/definitions/415.html).
-Wno-analyzer-exposure-through-output-fileโ stops secrets from leaking into output files ๐คซ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-exposure-through-output-file to disable it.
This diagnostic warns for paths through the code where a security-sensitive value is written to an output file, like writing a password to a log file ๐ญ.
๐ See CWE-532: Information Exposure Through Log Files (https://cwe.mitre.org/data/definitions/532.html).
-Wanalyzer-exposure-through-uninit-copyโ warns about uninitialized data crossing a trust boundary ๐จ
This warning requires both -fanalyzer and the use of a plugin to specify a function that copies across a "trust boundary". Use -Wno-analyzer-exposure-through-uninit-copy to disable it.
This diagnostic warns for "infoleaks", which are paths through the code where uninitialized values get copied across a security boundary. A classic example is code inside an OS kernel that copies a partially-initialized struct on the stack out to user space ๐.
๐ See CWE-200: Exposure of Sensitive Information to an Unauthorized Actor (https://cwe.mitre.org/data/definitions/200.html).
-Wno-analyzer-fd-access-mode-mismatchโ yells when you read from a write-only fd, or write to a read-only one ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-access-mode-mismatch to disable it.
This diagnostic warns for paths through the code where a "read" is attempted on a write-only file descriptor, or vice versa.
This diagnostic also warns for code paths where a function with attribute fd_arg_read (N) is called with a file descriptor opened with O_WRONLY at referenced argument N, or where a function with attribute fd_arg_write (N) is called with a file descriptor opened with O_RDONLY at referenced argument N.
-Wno-analyzer-fd-double-closeโ catches fds that get closed more than once ๐ฆ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-double-close to disable it.
This diagnostic warns for paths through the code where a file descriptor can be closed more than once.
๐ See CWE-1341: Multiple Releases of Same Resource or Handle (https://cwe.mitre.org/data/definitions/1341.html).
-Wno-analyzer-fd-leakโ flags open fds that never get released ๐ธ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-leak to disable it.
This diagnostic warns for paths through the code where an open file descriptor is leaked.
๐ See CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime (https://cwe.mitre.org/data/definitions/775.html).
-Wno-analyzer-fd-phase-mismatchโ operations done at the wrong point in an fd's life ๐งฉ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-phase-mismatch to disable it.
This diagnostic warns for paths through the code where an operation is attempted in the wrong phase of a file descriptor's lifetime. For example, it'll warn on attempts to call accept on a stream socket that has not yet had listen successfully called on it.
๐ See CWE-666: Operation on Resource in Wrong Phase of Lifetime (https://cwe.mitre.org/data/definitions/666.html).
-Wno-analyzer-fd-type-mismatchโ wrong kind of fd for the operation you're doing ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-type-mismatch to disable it.
This diagnostic warns for paths through the code where an operation is attempted on the wrong type of file descriptor. For example, it'll warn on attempts to use socket operations on a file descriptor obtained via open, or when attempting to use a stream socket operation on a datagram socket.
-Wno-analyzer-fd-use-after-closeโ using an fd after it's already been closed โฐ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-use-after-close to disable it.
This diagnostic warns for paths through the code where a read or write is called on a closed file descriptor.
This diagnostic also warns for paths through the code where a function with attribute fd_arg (N) or fd_arg_read (N) or fd_arg_write (N) is called with a closed file descriptor at referenced argument N.
-Wno-analyzer-fd-use-without-checkโ using an fd without checking it's valid first ๐ซฃ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-fd-use-without-check to disable it.
This diagnostic warns for paths through the code where a file descriptor is used without being checked for validity.
This diagnostic also warns for paths through the code where a function with attribute fd_arg (N) or fd_arg_read (N) or fd_arg_write (N) is called with a file descriptor, at referenced argument N, without being checked for validity.
-Wno-analyzer-file-leakโFILE *streams that never get cleaned up ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-file-leak to disable it.
This diagnostic warns for paths through the code where a <stdio.h> FILE * stream object is leaked.
๐ See CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime (https://cwe.mitre.org/data/definitions/775.html).
-Wno-analyzer-free-of-non-heapโ callingfreeon something that was never on the heap ๐ชฆ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-free-of-non-heap to disable it.
This diagnostic warns for paths through the code where free is called on a non-heap pointer, like an on-stack buffer or a global.
๐ See CWE-590: Free of Memory not on the Heap (https://cwe.mitre.org/data/definitions/590.html).
-Wno-analyzer-imprecise-fp-arithmeticโ floating-point math where precision matters ๐งฎ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-imprecise-fp-arithmetic to disable it.
This diagnostic warns for paths through the code where floating-point arithmetic is used in locations where precise computation is needed. At the moment, it only warns on the use of floating-point operands inside the calculation of an allocation size.
-Wno-analyzer-infinite-loopโ loops that look like they'll never end ๐
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-infinite-loop to disable it.
This diagnostic warns for paths through the code which appear to lead to an infinite loop.
Specifically, the analyzer will issue this warning when it "sees" a loop in which:
- no externally-visible work could be being done within the loop
- there is no way to escape from the loop
- the analyzer is sufficiently confident about the program state throughout the loop to know that the above are true
One way for this warning to be emitted is when there is an execution path through a loop for which taking the path on one iteration implies that the same path will be taken on all subsequent iterations.
For example, consider:
while (1)
{
char opcode = *cpu_state.pc;
switch (opcode)
{
case OPCODE_FOO:
handle_opcode_foo (&cpu_state);
break;
case OPCODE_BAR:
handle_opcode_bar (&cpu_state);
break;
}
}
The analyzer will complain for the above case because if opcode ever matches none of the cases, the switch will follow the implicit default case, making the body of the loop be a no-op with cpu_state.pc unchanged, and thus using the same value of opcode on all subsequent iterations, leading to an infinite loop ๐.
๐ See CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop') (https://cwe.mitre.org/data/definitions/835.html).
-Wno-analyzer-infinite-recursionโ recursion that never bottoms out ๐ช
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-infinite-recursion to disable it.
Okay so this one is about infinite recursion ๐ It warns about paths in the code that look like they never stop calling themselves, which is giving "this function will never end" ๐
Here's how the analyzer sees it: whenever it spots a recursive call, it compares the state of memory at the entry of the new frame with the state at the entry of the previous frame of that same function on the stack ๐ง The warning only shows up if nothing in memory seems to be changing. If any parameters or globals look like they're changing, the analyzer assumes the recursion will end and quietly skips the warning ๐ซถ
Heads up though ๐ this diagnostic can miss infinite recursion that the optimizer already turned into iteration before the analyzer gets to look. So if you're trying to trigger it, disable optimization โจ
Compare with -Winfinite-recursion, which gives a similar diagnostic but is implemented a different way ๐
See CWE-674: Uncontrolled Recursion ("https://cwe.mitre.org/data/definitions/674.html").
-Wno-analyzer-jump-through-nullโ ๐ฆ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-jump-through-null. It warns about paths where a "NULL" function pointer gets called ๐-Wno-analyzer-malloc-leakโ ๐ธ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-malloc-leak. It warns about paths where a pointer from an allocator gets leaked. The allocator can be eithermalloc, or a function marked with attributemalloc๐ซ- See CWE-401: Missing Release of Memory after Effective Lifetime (
"https://cwe.mitre.org/data/definitions/401.html").
- See CWE-401: Missing Release of Memory after Effective Lifetime (
-Wno-analyzer-mismatching-deallocationโ ๐ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-mismatching-deallocation. It warns about paths where the wrong deallocation function gets called on a pointer, based on which function allocated it. It catches mismatches betweenfree, scalardelete, and vectordelete[], plus anything marked as an allocator/deallocator pair using attributemalloc๐ฅ- See CWE-762: Mismatched Memory Management Routines (
"https://cwe.mitre.org/data/definitions/762.html").
- See CWE-762: Mismatched Memory Management Routines (
-Wno-analyzer-out-of-boundsโ ๐ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-out-of-bounds. It warns about paths where a buffer is definitely read or written out of bounds. It works when the analyzer can figure out a constant offset, and for accesses past the end of a buffer with a constant capacity. It also does limited checking for accesses past the end when both the offset and the capacity are symbolic โจ- See CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer (
"https://cwe.mitre.org/data/definitions/119.html"). - When the analyzer can manage it, it draws a text art diagram ๐จ of the memory region it predicts will be accessed, next to the range that's actually valid. The diagram shows whether they overlap, touch, or sit close or far apart, which one comes first in memory, the relative sizes, whether the access is a read or a write, and sometimes the values of the data involved. You can hide this diagram with
-fdiagnostics-text-art-charset=none.
- See CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer (
-Wno-analyzer-overlapping-buffersโ ๐ซถ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-overlapping-buffers. It warns about paths where overlapping buffers get passed to an API where the behavior is undefined for that kind of input. Specifically, it looks at calls to these functions, but only when the buffers are known to overlap:*<"memcpy">*<"strcat">*<"strcpy">
-Wno-analyzer-possible-null-argumentโ ๐ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-possible-null-argument. It warns about paths where a possibly-NULL value gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULL value ๐- See CWE-690: Unchecked Return Value to NULL Pointer Dereference (
"https://cwe.mitre.org/data/definitions/690.html").
- See CWE-690: Unchecked Return Value to NULL Pointer Dereference (
-Wno-analyzer-possible-null-dereferenceโ โจ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-possible-null-dereference. It warns about paths where a possibly-NULL value gets dereferenced ๐- See CWE-690: Unchecked Return Value to NULL Pointer Dereference (
"https://cwe.mitre.org/data/definitions/690.html").
- See CWE-690: Unchecked Return Value to NULL Pointer Dereference (
-Wno-analyzer-null-argumentโ ๐ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-null-argument. It warns about paths where a value known to be NULL gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULL value ๐- See CWE-476: NULL Pointer Dereference (
"https://cwe.mitre.org/data/definitions/476.html").
- See CWE-476: NULL Pointer Dereference (
-Wno-analyzer-null-dereferenceโ ๐ง This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-null-dereference. It warns about paths where a value known to be NULL gets dereferenced ๐ญ- See CWE-476: NULL Pointer Dereference (
"https://cwe.mitre.org/data/definitions/476.html").
- See CWE-476: NULL Pointer Dereference (
-Wno-analyzer-putenv-of-auto-varโ ๐ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-putenv-of-auto-var. It warns about paths where a call to "putenv" gets passed a pointer to an automatic variable or an on-stack buffer ๐- See POS34-C. Do not call putenv() with a pointer to an automatic variable as the argument (
"https://wiki.sei.cmu.edu/confluence/x/6NYxBQ").
- See POS34-C. Do not call putenv() with a pointer to an automatic variable as the argument (
-Wno-analyzer-shift-count-negativeโ ๐ธ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-shift-count-negative. It warns about paths where a shift is attempted with a negative count. It's the analyzer's version of-Wshift-count-negative, which the C/C++ front ends do, but this one looks at interprocedural paths instead of just parsing the syntax tree. The analyzer doesn't prioritize finding these, so false negatives are more likely compared to other warnings ๐ซ-Wno-analyzer-shift-count-overflowโ ๐ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-shift-count-overflow. It warns about paths where a shift is attempted with a count greater than or equal to the precision of the operand's type. It's analogous to-Wshift-count-overflowin the C/C++ front ends, but it's based on analyzing interprocedural paths rather than just the syntax tree. Same catch as before: the analyzer doesn't prioritize these, so false negatives are more likely compared to other warnings ๐ซถ-Wno-analyzer-stale-setjmp-bufferโ ๐ญ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-stale-setjmp-buffer. It warns about paths where "longjmp" gets called to rewind to a "jmp_buf" tied to a "setjmp" call, in a function that has already returned โ ๏ธ- When "setjmp" is called on a "jmp_buf" to record a rewind location, it records the stack frame. That stack frame becomes invalid once the function containing the "setjmp" call returns. Trying to rewind to it with "longjmp" would reference a stack frame that no longer exists, and that's likely to crash (or worse) ๐
-Wno-analyzer-tainted-allocation-sizeโ ๐ฅ This one needs-fanalyzerwhich turns it on, and you can switch it off with-Wno-analyzer-tainted-allocation-size. It warns about paths where a value an attacker could control gets used as the size of an allocation without being sanitized first. That means an attacker could inject a huge allocation and maybe cause a denial of service attack ๐ โโ๏ธ- See CWE-789: Memory Allocation with Excessive Size Value (
"https://cwe.mitre.org/data/definitions/789.html").
- See CWE-789: Memory Allocation with Excessive Size Value (
-Wno-analyzer-tainted-assertionโ ๐ This one needs-fanalyzerwhich turns it on, and you can switch it off with-Wno-analyzer-tainted-assertion. It warns about paths where a value an attacker could control gets used as part of a condition without being sanitized first, and that condition guards a call to a function marked with attributenoreturn(like the function__builtin_unreachable). Those functions usually mean the program is terminating abnormally, like assertion failure handlers. For example:
assert (some_tainted_value < SOME_LIMIT);
In those cases:
- when assertion-checking is enabled, an attacker could trigger a denial of service by injecting an assertion failure
- when assertion-checking is disabled, such as by defining
NDEBUG, an attacker could inject data that subverts the process, since it presumably violates a precondition the code is assuming
Heads up ๐ when assertion-checking is disabled, the preprocessor usually removes the assertions before the analyzer gets a chance to "see" them. So this diagnostic can only generate warnings on builds where assertion-checking is enabled.
For this warning, any function marked with attribute noreturn counts as a possible assertion failure handler, including __builtin_unreachable. These functions are sometimes removed by the optimizer before the analyzer "sees" them, so disable optimization when you're trying to trigger this diagnostic ๐ง
- See CWE-617: Reachable Assertion (
"https://cwe.mitre.org/data/definitions/617.html").
The warning can also report problematic constructions such as
switch (some_tainted_value) {
case 0:
/* [...etc; various valid cases omitted...] */
break;
default:
__builtin_unreachable (); /* BUG: attacker can trigger this */
}
Okay so that default: branch is giving ๐ because the comment literally says an attacker can trigger it ๐ญ Despite the example above, it's not an assertion failure, strictly speaking ๐ but it's still a whole vibe check ๐ฅ
-Wno-analyzer-tainted-array-indexโ โจ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-tainted-array-indexto turn it off. It flags paths where a value an attacker could control gets used as an array index without being sanitized, so an attacker could sneak in an out-of-bounds access ๐- See CWE-129: Improper Validation of Array Index (
https://cwe.mitre.org/data/definitions/129.html).
- See CWE-129: Improper Validation of Array Index (
-Wno-analyzer-tainted-divisorโ ๐ฆ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-tainted-divisorto turn it off. It flags paths where an attacker-controllable value is used as the divisor in a division or modulus operation without being sanitized, so an attacker could inject a division-by-zero ๐- See CWE-369: Divide By Zero (
https://cwe.mitre.org/data/definitions/369.html).
- See CWE-369: Divide By Zero (
-Wno-analyzer-tainted-offsetโ ๐ธ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-tainted-offsetto turn it off. It flags paths where an attacker-controllable value is used as a pointer offset without being sanitized, so an attacker could inject an out-of-bounds access ๐- See CWE-823: Use of Out-of-range Pointer Offset (
https://cwe.mitre.org/data/definitions/823.html).
- See CWE-823: Use of Out-of-range Pointer Offset (
-Wno-analyzer-tainted-sizeโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-tainted-sizeto turn it off. It flags paths where an attacker-controllable value is used as the size of an operation such asmemsetwithout being sanitized, so an attacker could inject an out-of-bounds access ๐ญ- See CWE-129: Improper Validation of Array Index (
https://cwe.mitre.org/data/definitions/129.html).
- See CWE-129: Improper Validation of Array Index (
-Wno-analyzer-throw-of-unexpected-typeโ ๐ง This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-throw-of-unexpected-typeto turn it off. Heads up, dynamic exception specifications are only available in C++14 and earlier. It flags paths where an exception is thrown from a function with a dynamic exception specification and the exception doesn't comply with that specification ๐-Wno-analyzer-undefined-behavior-ptrdiffโ ๐ซถ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-undefined-behavior-ptrdiffto turn it off. It flags paths where a pointer subtraction happens between pointers that refer to different chunks of memory. That code relies on undefined behavior, because pointer subtraction is only defined when both pointers point within (or just after) the same array โ ๏ธ- See CWE-469: Use of Pointer Subtraction to Determine Size (
https://cwe.mitre.org/data/definitions/469.html).
- See CWE-469: Use of Pointer Subtraction to Determine Size (
-Wno-analyzer-undefined-behavior-strtokโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-undefined-behavior-strtokto turn it off. It flags paths where a call tostrtokhas undefined behavior. Specifically, passingNULLas the first parameter for the initial call tostrtokwithin a process is undefined behavior ๐-Wno-analyzer-unsafe-call-within-signal-handlerโ ๐ฅ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-unsafe-call-within-signal-handlerto turn it off. It flags paths where a function known to be async-signal-unsafe (such asfprintf) gets called from a signal handler ๐จ- See CWE-479: Signal Handler Use of a Non-reentrant Function (
https://cwe.mitre.org/data/definitions/479.html).
- See CWE-479: Signal Handler Use of a Non-reentrant Function (
-Wno-analyzer-use-after-freeโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-use-after-freeto turn it off. It flags paths where a pointer gets used after a deallocator has been called on it. That means eitherfree, or a deallocator referenced by attributemalloc๐ฅ- See CWE-416: Use After Free (
https://cwe.mitre.org/data/definitions/416.html).
- See CWE-416: Use After Free (
-Wno-analyzer-use-of-pointer-in-stale-stack-frameโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-use-of-pointer-in-stale-stack-frameto turn it off. It flags paths where a pointer gets dereferenced while pointing to a variable in a stale stack frame โญ-Wno-analyzer-va-arg-type-mismatchโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-va-arg-type-mismatchto turn it off. It flags interprocedural paths where the analyzer detects an attempt to useva_argto extract a value passed to a variadic call, but the type used doesn't match the expression passed to the call ๐ง- See CWE-686: Function Call With Incorrect Argument Type (
https://cwe.mitre.org/data/definitions/686.html).
- See CWE-686: Function Call With Incorrect Argument Type (
-Wno-analyzer-va-list-exhaustedโ โจ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-va-list-exhaustedto turn it off. It flags interprocedural paths where the analyzer detects an attempt to useva_argto access the next value passed to a variadic call, but every value in theva_listhas already been consumed ๐ซ- See CWE-685: Function Call With Incorrect Number of Arguments (
https://cwe.mitre.org/data/definitions/685.html).
- See CWE-685: Function Call With Incorrect Number of Arguments (
-Wno-analyzer-va-list-leakโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-va-list-leakto turn it off. It flags interprocedural paths where the analyzer detects thatva_startorva_copyhas been called on ava_listwithout a matching call tova_end๐-Wno-analyzer-va-list-use-after-va-endโ ๐ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-va-list-use-after-va-endto turn it off. It flags interprocedural paths where the analyzer detects an attempt to use ava_listafterva_endhas been called on it ๐-Wno-analyzer-write-to-constโ ๐ฆ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-write-to-constto turn it off. It flags paths where the analyzer detects an attempt to write through a pointer to aconstobject. Fair warning though, the analyzer doesn't prioritize catching these, so false negatives are more likely compared to other warnings ๐-Wno-analyzer-write-to-string-literalโ ๐ท This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-write-to-string-literalto turn it off. It flags paths where the analyzer detects an attempt to write through a pointer to a string literal. Same deal though, the analyzer doesn't prioritize these, so false negatives are more likely compared to other warnings ๐ซฃ-Wno-analyzer-use-of-uninitialized-valueโ ๐ญ This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-use-of-uninitialized-valueto turn it off. It flags paths where an uninitialized value gets used ๐ฅบ- See CWE-457: Use of Uninitialized Variable (
https://cwe.mitre.org/data/definitions/457.html).
- See CWE-457: Use of Uninitialized Variable (
Okay, so the analyzer has hardcoded knowledge about how these memory-management functions behave ๐ง โจ
alloca- The built-in functions
__builtin_alloc,__builtin_alloc_with_align,__builtin_calloc,__builtin_free,__builtin_malloc,__builtin_memcpy,__builtin_memcpy_chk,__builtin_memset,__builtin_memset_chk,__builtin_realloc,__builtin_stack_restore, and__builtin_stack_save callocfreemallocmemsetoperator deleteoperator delete []operator newoperator new []reallocstrdupstrndup
It also knows the behavior of these functions for working with file descriptors ๐
openclosecreatdup,dup2anddup3isattypipe, andpipe2readwritesocket,bind,listen,accept, andconnect
And these functions for working with <stdio.h> streams ๐
- The built-in functions
__builtin_fprintf,__builtin_fprintf_unlocked,__builtin_fputc,__builtin_fputc_unlocked,__builtin_fputs,__builtin_fputs_unlocked,__builtin_fwrite,__builtin_fwrite_unlocked,__builtin_printf,__builtin_printf_unlocked,__builtin_putc,__builtin_putchar,__builtin_putchar_unlocked,__builtin_putc_unlocked,__builtin_puts,__builtin_puts_unlocked,__builtin_vfprintf, and__builtin_vprintf fopenfcloseferrorfgetsfgets_unlockedfilenofreadgetcgetcharfprintfprintffwrite
And finally, these ones too ๐
- The built-in functions
__builtin_expect,__builtin_expect_with_probability,__builtin_strchr,__builtin_strcpy,__builtin_strcpy_chk,__builtin_strlen,__builtin_va_copy, and__builtin_va_start - The GNU extensions
erroranderror_at_line getpasslongjmpputenvsetjmpsiglongjmpsignalsigsetjmpstrcatstrchrstrlen
In addition, various functions with an __analyzer_ prefix have special meaning to the analyzer. These are described in the GCC Internals manual ๐ Various internal parameters, settable via --param, are used to control the exploration, and those are documented in the GCC Internals manual too ๐
The following options control the analyzer ๐
-fanalyzer-assume-nothrowโ okay so by default, if-fexceptionsis on, the analyzer assumes that calling any function without the "nothrow" attribute could throw an exception ๐ญ. This is amazing for catching paths that leak because exceptions skip the clean-up code, but it can lead to false positives when you're using headers where the author didn't add the "nothrow" attribute ๐.- If
-fanalyzer-assume-nothrowis enabled, the analyzer assumes external functions never throw exceptions โจ. This can reduce the "noise" when you turn on-fexceptionsfor C code, but it could hide real issues if something the C code calls can raise an exception ๐.
- If
-fanalyzer-call-summariesโ this one simplifies interprocedural analysis by computing the effect of certain calls instead of exploring every path through the function from the callsite to each possible return ๐ง . Only functions with more than one call site, and that are sufficiently complicated, get call summaries ๐ .-fanalyzer-checker=nameโ restricts the analyzer to run just the named checker, and enables it ๐ฏ.-fanalyzer-debug-text-art-headingsโ this is for analyzer developers only ๐ ๏ธ. If enabled, the analyzer adds extra annotations to any diagrams it generates ๐จ.-fno-analyzer-feasibilityโ this one's for analyzer developers too ๐งโ๐ป. By default, the analyzer checks that there's a feasible control flow path for each diagnostic it emits, meaning the conditions that hold aren't mutually exclusive. Diagnostics with no feasible path get rejected ๐ซ. This filtering can be suppressed with-fno-analyzer-feasibility, which is handy for debugging issues in this code ๐.-fanalyzer-fine-grainedโ does nothing ๐คทโโ๏ธ. It's only kept around for backward compatibility ๐ฐ๏ธ.-fanalyzer-show-duplicate-countโ another developer-only option ๐โโ๏ธ. If several diagnostics are detected as duplicates of each other, this emits a note when reporting the best diagnostic, giving the number of additional diagnostics the deduplication logic suppressed ๐ข.-fanalyzer-show-events-in-system-headersโ by default, the analyzer keeps simplified diagnostic paths tidy by hiding events fully located within a system header ๐งน. With-fanalyzer-show-events-in-system-headers, those events stop getting suppressed ๐.-fno-analyzer-simplify-supergraphโ developer-only vibes ๐งช. By default, the analyzer simplifies the program supergraph before analyzing it. With-fno-analyzer-simplify-supergraph, that simplification gets skipped, which is useful for debugging issues with it ๐.-fno-analyzer-state-mergeโ developer-only again ๐ป. By default, the analyzer merges sufficiently similar states at each program point while it builds its "exploded graph" ๐งฉ. With-fno-analyzer-state-merge, that merging is suppressed, handy for debugging state-handling issues ๐ง.-fno-analyzer-state-purgeโ for analyzer developers ๐ซถ. By default, the analyzer purges aspects of state at a program point that don't seem relevant anymore, like the values of locals that aren't accessed later in the function and aren't relevant to leak analysis ๐๏ธ. With-fno-analyzer-state-purge, that purging is suppressed, for debugging state-handling issues ๐ต๏ธโโ๏ธ.-fno-analyzer-suppress-followupsโ developer-only ๐. By default, the analyzer stops exploring an execution path after hitting certain diagnostics, so it doesn't spam you with a cascade of follow-up diagnostics ๐. The diagnostics that end analysis along a path are:-Wanalyzer-null-argument-Wanalyzer-null-dereference-Wanalyzer-use-after-free-Wanalyzer-use-of-pointer-in-stale-stack-frame-Wanalyzer-use-of-uninitialized-value
With -fno-analyzer-suppress-followups, the analyzer keeps exploring those paths even after such diagnostics ๐. That can be helpful for debugging the analyzer, or for microbenchmarks that detect undefined behavior ๐งซ.
-fanalyzer-transitivityโ this one enables transitivity of constraints within the analyzer ๐.-fno-analyzer-undo-inliningโ developer-only ๐งโ๐ฌ.-fanalyzerruns relatively late compared to other code analysis tools, so some optimizations have already been applied. In particular, function inlining may have happened, which means the interprocedural execution paths the analyzer emits can contain function frames that don't match the original source code ๐ตโ๐ซ. By default, the analyzer tries to reconstruct the original function frames and emit events showing the inlined calls โจ. With-fno-analyzer-undo-inlining, that reconstruction is disabled, which may help when debugging issues in the analyzer ๐ ๏ธ.-fanalyzer-verbose-edgesโ for analyzer developers ๐. It turns on more verbose, lower-level detail in the descriptions of control flow within diagnostic paths ๐.-fanalyzer-verbose-state-changesโ also for analyzer developers ๐งโ๐ป. It turns on more verbose, lower-level detail in the descriptions of events relating to state machines within diagnostic paths ๐ข.-fanalyzer-verbosity=levelโ this one controls how complex the control flow paths are that get emitted for analyzer diagnostics ๐. Thelevelcan be one of:0โ interprocedural call and return events are displayed, along with the most pertinent state-change events for a diagnostic ๐. For example, for a double-"free" diagnostic, both calls to "free" will show up ๐ฏ.1โ same as the previous level, but also shows events for the entry to each function ๐ช.2โ same as the previous level, but also shows control flow events that matter for triggering the issue, like "true path taken" at a conditional ๐. This is the default, so it's the main character level ๐.3โ same as the previous level, but shows all control flow events, not just the significant ones ๐.4โ for analyzer developers only ๐ค. It adds various other events meant for debugging the analyzer ๐.
-fdump-analyzerโ dumps internal details about what the analyzer is doing tofile.analyzer.txt๐.-fdump-analyzer-stderroverrides this option ๐ โโ๏ธ.-fdump-analyzer-stderrโ dumps internal details about what the analyzer is doing to stderr ๐ฃ. This option overrides-fdump-analyzer๐.-fdump-analyzer-callgraphโ dumps a representation of the call graph that's suitable for viewing with GraphViz, tofile.callgraph.dot๐บ๏ธ.-fdump-analyzer-exploded-graphโ dumps a representation of the "exploded graph" that's suitable for viewing with GraphViz, tofile.eg.dot๐จ. The nodes are color-coded based on state-machine states, so state changes really pop ๐.-fdump-analyzer-exploded-nodesโ emits diagnostics showing where nodes in the "exploded graph" sit in relation to the program source ๐.-fdump-analyzer-exploded-nodes-2โ dumps a textual representation of the "exploded graph" tofile.eg.txt๐.-fdump-analyzer-exploded-nodes-3โ dumps a textual representation of the "exploded graph" to one dump file per node, namedfile.eg-id.txt๐. Heads up, this is typically a large number of dump files ๐ญ.-fdump-analyzer-exploded-pathsโ dumps a textual representation of the "exploded path" for each diagnostic tofile.idx.kind.epath.txt๐งพ.-fdump-analyzer-feasibilityโ dumps internal details about the analyzer's search for feasible paths ๐. The details are written in a form suitable for GraphViz, to filenames likefile.*.fg.dot,file.*.tg.dot, andfile.*.fpath.txt๐ผ๏ธ.-fdump-analyzer-infinite-loopโ dumps internal details about the analyzer's search for infinite loops โพ๏ธ. The details are written in a form suitable for GraphViz, to filenames likefile.*.infinite-loop.dot๐.-fdump-analyzer-jsonโ dumps a compressed JSON representation of analyzer internals tofile.analyzer.json.gz๐๏ธ. Heads up, the precise format is subject to change โ ๏ธ.-fdump-analyzer-state-purgeโ same idea as-fdump-analyzer-supergraph, so it dumps a "supergraph" representation suitable for GraphViz ๐บ๏ธ. But this one annotates the graph with info on what state will be purged at each node ๐งน. The graph is written tofile.state-purge.dot๐.-fdump-analyzer-supergraphโ dumps representations of the "supergraph" suitable for GraphViz tofile.supergraph.index.kind.dot๐. These show all of the control flow graphs in the program at various stages of the analysis ๐. The precise set of dumps and what they show is subject to change ๐.-fdump-analyzer-untrackedโ emits custom warnings with internal details meant for analyzer developers ๐จ.
โจ Options for Debugging Your Program โจ
To get GCC to emit extra info for a debugger, you almost always just need to add -g to your other options ๐. Some debug formats can co-exist (like DWARF with CTF) when each one is explicitly enabled by adding its own command line option to your other options ๐ซถ.
GCC lets you use -g with -O ๐
. The shortcuts taken by optimized code can be a little surprising ๐ณ: some variables you declared may not exist at all, flow of control may briefly move somewhere you didn't expect, some statements may not execute because they compute constant results or their values are already at hand, and some statements may execute in different places because they've been moved out of loops ๐. Still, it's totally possible to debug optimized output, which makes it reasonable to use the optimizer for programs that might have bugs ๐.
If you're not using some other optimization option, consider using -Og with -g ๐ง. With no -O option at all, some compiler passes that collect info useful for debugging don't run, so -Og may give you a better debugging experience โจ.
-g,--debugโ produces debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF) ๐. GDB can work with this debugging information ๐ฆ.
On most systems that use stabs format, -g unlocks extra debugging info that only GDB can actually use ๐. It makes debugging in GDB way smoother, but it can make other debuggers crash or refuse to read the program ๐. If you want to be certain whether that extra info gets generated, use -gvms instead (more on that below) โจ.
-ggdbโ Asks for the most expressive debug format available, which is DWARF, then stabs, then the native format if neither of those is supported ๐ฆ. GDB extensions get included too, if at all possible ๐.-gdwarf,-gdwarf-versionโ Makes DWARF debug info, as long as the target supports it ๐. The version can be2,3,4or5. Most targets default to version 5, except VxWorks, TPF and Darwin / macOS (which default to version 2) and AIX (which defaults to version 4) ๐.- With DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables.
- Version 4 may need GDB 7.0 and
-fvar-tracking-assignmentsto get the full benefit. Version 5 needs GDB 8.0 or higher. - GCC no longer supports DWARF Version 1, which is very different from Version 2 and later. For historical reasons, some other DWARF-related options, such as
-fno-dwarf2-cfi-asm, still have Version 2 in their names, but they apply to every DWARF version that's currently supported ๐.
-gbtfโ Requests BTF debug info. BTF is the default debugging format for the eBPF target ๐ง. On other targets, like x86, BTF can be generated alongside DWARF if you turn on both formats explicitly with their own command-line options.-gprune-btf,-gno-prune-btfโ Prunes BTF info before it gets emitted โ๏ธ. When pruning, only type info for types used by global variables and file-scope functions gets emitted. If you're compiling for the BPF target with BPF CO-RE enabled, type info also gets emitted for types used in BPF CO-RE relocations. Struct and union types that are only referred to through pointers from members of other struct or union types get pruned and replaced withBTF_KIND_FWD, as though they were only forward declarations in the input.- This option shrinks the BTF output a ton, but you lose a lot of detailed type info ๐ญ. It's mainly useful for the BPF target, where it keeps the object small and drops BTF info that doesn't matter for loading the BPF program.
- It's turned on by default for the BPF target when BTF info is being generated.
-gctf,-gctflevelโ Requests CTF debug info, and the level decides how much gets made ๐. If you use-gctfwithout a level, the default is 2. CTF can be generated alongside DWARF if you turn on both formats explicitly with their own command-line options.- Level 0 produces no CTF debug info at all, so
-gctf0cancels out-gctf๐ . - Level 1 produces CTF info for tracebacks only. That includes callsite info but not type info.
- Level 2 produces type info only for entities (functions, data objects etc.) at file scope or global scope.
- Level 0 produces no CTF debug info at all, so
-gvmsโ Makes debug info in the Alpha/VMS debug format, if that's supported. It's the format DEBUG uses on Alpha/VMS systems ๐.-gcodeviewโ Makes debug info in the CodeView format, if that's supported. Microsoft Visual C++ uses this one on Windows ๐ช.-glevel,-ggdblevel,-gvmslevelโ Requests debug info and uses the level to set how much you get ๐. The default level is 2.- Level 0 produces no debug info at all, so
-g0cancels out-g. - Level 1 produces minimal info, enough for backtraces in parts of the program you don't plan to debug. That includes descriptions of functions and external variables, plus line number tables, but no info about local variables.
- Level 3 adds extra info, like all the macro definitions in the program. Some debuggers can do macro expansion when you use
-g3๐. - If you use several
-goptions, with or without level numbers, the last one wins ๐. -gdwarfdoesn't accept a concatenated debug level, so it won't get confused with-gdwarf-level. Use an extra-gleveloption to change the debug level for DWARF instead ๐ซถ.
- Level 0 produces no debug info at all, so
-fno-eliminate-unused-debug-symbolsโ By default, no debug info gets produced for symbols that aren't actually used. Use this if you want debug info for all symbols ๐.-femit-class-debug-alwaysโ Instead of emitting debug info for a C++ class in just one object file, this emits it in every object file that uses the class. Only use it with debuggers that can't handle the way GCC normally emits class debug info, because it can make the debug info up to twice as big ๐ฌ.-fno-merge-debug-stringsโ Tells the linker not to merge strings in the debug info that are identical across different object files. Not every assembler or linker supports merging. Merging makes the debug info in the output file smaller, but it costs more link time. Merging is enabled by default ๐งต.-fdebug-prefix-map=old=newโ When compiling files in directoryold, the debug info describes them as if they lived in directorynewinstead ๐บ๏ธ. You can use it to swap a build-time path for an install-time path in the debug info. You can also turn an absolute path into a relative one by using.fornew. That can give more reproducible builds, which don't depend on location, but you might need an extra command to tell GDB where to find the source files. See also-ffile-prefix-mapand-fcanon-prefix-map.-fvar-trackingโ Runs the variable tracking pass ๐ต๏ธโโ๏ธ. It works out where variables are stored at each position in the code, so better debug info gets generated (if the debug format supports that). It's enabled by default when you compile with optimization (-Os,-O,-O2, ...), with debug info (-g), and the debug info format supports it.-fvar-tracking-assignmentsโ Annotates assignments to user variables early in compilation and tries to carry those annotations all the way to the end, to improve debug info while optimizing โจ. Using-gdwarf-4alongside it is recommended.- It can be turned on even when var-tracking is off. In that case the annotations get created and maintained, then thrown away at the end.
- By default, this flag is enabled together with
-fvar-tracking, except when selective scheduling is enabled.
-fvar-tracking-uninit,-fno-var-tracking-uninitโ Does variable tracking and also marks uninitialized variables in the debug info ๐ท๏ธ. This flag is enabled by default by-fvar-tracking, and it also implies-fvar-tracking. To do variable tracking without marking uninitialized variables, use-fvar-tracking -fno-var-tracking-uninit.-gsplit-dwarfโ If DWARF debug info is enabled, it pulls out as much of that info as possible into a separate output file with the.dwoextension ๐ฆ. This lets your build system avoid linking files that have debug info. To be useful, you need a debugger that can read.dwofiles.-gdwarf32,-gdwarf64โ If DWARF debug info is enabled,-gdwarf32selects the 32-bit DWARF format and-gdwarf64selects the 64-bit one ๐ข. The default depends on the target, but on most targets it's-gdwarf32. The 32-bit format is smaller, but none of the DWARF debug info sections can go past 2GiB. The 64-bit format allows bigger debug info, though not every consumer supports it well yet.-gdescribe-diesโ Adds description attributes to some DWARF DIEs that have no name attribute, like artificial variables, external references and call site parameter DIEs ๐ท๏ธ.-gpubnamesโ Generates the DWARF.debug_pubnamesand.debug_pubtypessections ๐.-ggnu-pubnamesโ Generates.debug_pubnamesand.debug_pubtypesin a format that's suitable for converting into a GDB index. This is only useful with a linker that can produce GDB index version 7 ๐งฉ.-gno-pubnamesโ Doesn't generate the DWARF.debug_pubnamesand.debug_pubtypessections ๐ซ.-fdebug-types-sectionโ With DWARF Version 4 or higher, type DIEs can go into their own.debug_typessection instead of living in.debug_info๐๏ธ. It's more efficient to put them in a separate comdat section, since the linker can then remove duplicates. But not every DWARF consumer supports.debug_typesyet, and for some objects it makes the debug info bigger instead of smaller ๐ต.-grecord-gcc-switches,-gno-record-gcc-switchesโ Appends the command-line options that might affect code generation to theDW_AT_producerattribute in DWARF debug info ๐. The options are joined with spaces, separating them from each other and from the compiler version. It's enabled by default. See also-frecord-gcc-switchesfor another way to store compiler options in the object file.-gstrict-dwarfโ Disallows using extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ง. On most targets, using non-conflicting DWARF extensions from later standard versions is allowed.-gno-strict-dwarfโ Allows using extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ธ.-gas-loc-support: okay so this one tells the compiler the assembler speaks.locdirectives ๐ง, which means the compiler can let the assembler build the DWARF2+ line number tables. Ngl that's super desirable, because assembler-made line-number tables are a lot more compact than the ones the compiler can cook up on its own ๐ . It's on by default if GCC's configure step found the assembler supports those directives โจ.-gno-as-loc-support: the opposite energy ๐ โโ๏ธ. It forces GCC to generate DWARF2+ line number tables internally, but only if DWARF2+ line number tables are being generated in the first place.-gas-locview-support: tells the compiler the assembler can handle "view" assignment and reset assertion checking inside.locdirectives ๐ฆ. It's on by default if, at GCC configure time, the assembler was found to support them.-gno-as-locview-support: forces GCC to assign view numbers internally ๐ซถ, but only when-gvariable-location-viewshas been explicitly requested.-gcolumn-info,-gno-column-info: puts location column info into the DWARF debugging information, not just file and line ๐. It's on by default, bestie.-gstatement-frontiers,-gno-statement-frontiers: GCC drops markers into its internal representation at the start of each statement and keeps them roughly in place through the whole compile ๐. Then it uses them to steer whereis_stmtmarkers show up in the line number table. This is on by default when you compile with optimization (-Os,-O1,-O2,...) and output DWARF 2 debug info at the normal level ๐ธ.-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-views: adds progressive view numbers, implied from the line number table, onto the variable location lists ๐. This lets debug info consumers inspect state at certain points in the program, even when no instructions tied to those source locations are present there ๐. If the assembler can't handle view numbers in line number tables, the compiler emits the line number table itself, which makes things somewhat less compact ๐. The augmented line number tables and location lists are fully backward-compatible, so consumers that don't know about these augmentations can still read them. They just won't get any benefit from them either ๐คทโโ๏ธ.
This is on by default when outputting DWARF 2 debug info at the normal level, as long as there is assembler support, -fvar-tracking-assignments is enabled, and -gstrict-dwarf is not. When assembler support is missing, it can still be enabled, but it forces GCC to output internal line number tables. And if -ginternal-reset-location-views is not enabled, that most certainly leads to silently mismatching location views ๐ญ.
โ ๏ธ Heads up, bestie: there's a proposed view-number representation that is NOT backward compatible with the location list format introduced in DWARF 5. You can turn it on with -gvariable-location-views=incompat5. This option may be removed in the future, and it's only provided as a reference implementation of the proposed representation. Debug info consumers aren't expected to support this extended format, so they'd be unable to decode location lists using it ๐.
-ginternal-reset-location-views,-gno-internal-reset-location-views: tries to figure out which location views can be left out of location view lists ๐งฎ. This requires the compiler to have very accurate instruction length estimates, which isn't always the case. It may also silently generate incorrect view lists when using an assembler that doesn't support location view lists. The GNU assembler flags any such error as a "view number mismatch". It's only enabled on ports that define a reliable estimation function.-ginline-points,-gno-inline-points: generates extended debug info for inlined functions โจ. Location view tracking markers are inserted at inlined entry points, so address and view numbers can be computed and output in debug info. This can be enabled independently of location views, in which case the view numbers won't be output. It can only be enabled along with statement frontiers, and it's only enabled by default if location views are enabled.-gz[=type]: produces compressed debug sections in DWARF format, if that's supported ๐๏ธ. Iftypeisn't given, the default depends on the capabilities of the assembler and linker used.typemay be one ofnone(don't compress debug sections),zlib(use zlib compression in ELF gABI format), orzstd(use zstd compression in ELF gABI format). If the linker doesn't support writing compressed debug sections, the option is rejected. Otherwise, if the assembler doesn't support them,-gzis silently ignored when producing object files.-femit-struct-debug-baseonly: only emits debug info for struct-like types when the base name of the compilation source file matches the base name of the file where the struct is defined ๐ฏ. This substantially reduces the size of debug info, but at significant potential loss in type information for the debugger. See-femit-struct-debug-reducedfor a less aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option works only with DWARF debug output.-femit-struct-debug-reduced: only emits debug info for struct-like types when the base name of the compilation source file matches the base name of the file where the type is defined, unless the struct is a template or defined in a system header ๐งน. This significantly reduces the size of debug info, with some potential loss in type information for the debugger. See-femit-struct-debug-baseonlyfor a more aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option works only with DWARF debug output.-femit-struct-debug-detailed[=spec-list]: lets you specify the struct-like types GCC generates debug info for ๐. The intent is to reduce duplicate struct debug info between different object files within the same program. It's the detailed version of-femit-struct-debug-reducedand-femit-struct-debug-baseonly, and it serves most needs. A specification has the syntax[dir:|ind:][ord:|gen:](any|sys|base|none).- The optional first word limits the specification to structs that are used directly (
dir:) or used indirectly (ind:). A struct type is used directly when it's the type of a variable or member. Indirect uses arise through pointers to structs. That is, when use of an incomplete struct is valid, the use is indirect. An example isstruct one direct;andstruct two * indirect;. - The optional second word limits the specification to ordinary structs (
ord:) or generic structs (gen:). Generic structs are a bit complicated to explain. For C++, these are non-explicit specializations of template classes, or non-template classes within the above. Other programming languages have generics, but-femit-struct-debug-detaileddoes not yet implement them. - The third word specifies the source files for those structs for which the compiler should emit debug info. The values
noneandanyhave the normal meaning. The valuebasemeans that the base of the name of the file in which the type declaration appears must match the base of the name of the main compilation file. In practice, this means that when compilingfoo.c, debug info is generated for types declared in that file andfoo.h, but not other header files. The valuesysmeans those types satisfyingbaseor declared in system or compiler headers.
- The optional first word limits the specification to structs that are used directly (
You may need to experiment to determine the best settings for your application ๐งช. The default is -femit-struct-debug-detailed=all. This option works only with DWARF debug output.
-fno-dwarf2-cfi-asm: emits DWARF unwind info as a compiler-generated.eh_framesection, instead of using GAS.cfi_*directives ๐งพ.-fno-eliminate-unused-debug-types: normally, when producing DWARF output, GCC skips debug symbol output for types that are nowhere used in the source file being compiled. Sometimes it's useful to have GCC emit debug info for all types declared in a compilation unit, used or not. For example, if in the debugger you want to cast a value to a type that isn't actually used in your program (but is declared). More often, though, this just results in a significant amount of wasted space ๐.
โจ Options That Control Optimization โจ
These options control various sorts of optimizations ๐ช.
Without any optimization option, the compiler's goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any other statement in the function and get exactly the results you expect from the source code ๐ฏ.
Turning on optimization flags makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the ability to debug the program ๐๏ธโโ๏ธ.
The compiler performs optimization based on the knowledge it has of the program. Compiling multiple files at once to a single output file mode allows the compiler to use information gained from all of the files when compiling each of them ๐ง .
Not all optimizations are controlled directly by a flag. Only optimizations that have a flag are listed in this section.
Most optimizations are completely disabled at -O0 or if an -O level is not set on the command line, even if individual optimization flags are specified. Similarly, -Og suppresses many optimization passes ๐.
Depending on the target and how GCC was configured, a slightly different set of optimizations may be enabled at each -O level than those listed here. You can invoke GCC with -Q --help=optimizers to find out the exact set of optimizations that are enabled at each level ๐.
-O,-O1,--optimize: optimize, bestie ๐ฅ. Optimizing compilation takes somewhat more time, and a lot more memory for a large function.
Okay so with -O, the compiler tries to shrink your code and make it run faster ๐โโ๏ธ๐จ, but it won't do anything that takes forever to compile. Lowkey the perfect balance, bestie โจ
If you're dealing with huge machine-generated code, -O is the vibe ๐
. It's the recommended level because it balances compile time and memory use. The higher levels run optimizations with way more algorithmic complexity than plain -O does, so they cost more.
-O turns on this squad of flags ๐ซถ:
-fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments
-fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdelayed-branch
-fdse -fforward-propagate -fguess-branch-probability -fif-conversion
-fif-conversion2 -finline-functions-called-once -fipa-modref
-fipa-profile -fipa-pure-const -fipa-reference
-fipa-reference-addressable -fivopts -fmerge-constants
-fmove-loop-invariants -fmove-loop-stores -fomit-frame-pointer
-freorder-blocks -fshrink-wrap -fshrink-wrap-separate
-fsplit-wide-types -fssa-backprop -fssa-phiopt -ftree-bit-ccp
-ftree-ccp -ftree-ch -ftree-coalesce-vars -ftree-copy-prop
-ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop
-ftree-fre -ftree-phiprop -ftree-pta -ftree-scev-cprop -ftree-sink
-ftree-slsr -ftree-sra -ftree-ter -funit-at-a-time
๐ธ -O2 ๐ธ
Optimize even more! ๐ฅ GCC performs nearly all supported optimizations that don't involve a space-speed tradeoff. Compared to -O, this option increases both the compilation time and the performance of the generated code, so it's a glow-up with a cost.
-O2 turns on all optimization flags specified by -O1. It also turns on these extras:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fcaller-saves -fcode-hoisting -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -fdep-fusion
-fdevirtualize -fdevirtualize-speculatively
-fexpensive-optimizations -ffinite-loops -fgcse -fgcse-lm
-fhoist-adjacent-loads -finline-functions -finline-small-functions
-findirect-inlining -fipa-bit-cp -fipa-cp -fipa-icf -fipa-ra
-fipa-sra -fipa-vrp -fisolate-erroneous-paths-dereference
-flra-remat -foptimize-crc -foptimize-sibling-calls
-foptimize-strlen -fpartial-inlining -fpeephole2
-freorder-blocks-algorithm=stc -freorder-blocks-and-partition
-freorder-functions -frerun-cse-after-loop -fschedule-insns
-fschedule-insns2 -fsched-interblock -fsched-spec
-fspeculatively-call-stored-functions -fstore-merging
-fstrict-aliasing -fthread-jumps -ftree-builtin-call-dce
-ftree-loop-vectorize -ftree-pre -ftree-slp-vectorize
-ftree-switch-conversion -ftree-tail-merge -ftree-vrp
-fvect-cost-model=very-cheap
Heads up, bestie ๐จ: please check the warning under-fgcseabout invoking-O2on programs that use computed gotos. It's important, no cap.
NOTE ๐: In Ubuntu 8.10 and later versions,-D_FORTIFY_SOURCE=2, and in Ubuntu 24.04 and later versions,-D_FORTIFY_SOURCE=3, is set by default. It's activated when-Ois set to 2 or higher. This enables additional compile-time and run-time checks for several libc functions. To turn it off, specify either-U_FORTIFY_SOURCEor-D_FORTIFY_SOURCE=0.
NOTE ๐ฆ: In Debian 13 and Ubuntu 24.04 and later versions,-D_TIME_BITS=64together with-D_FILE_OFFSET_BITS=64is set by default on the 32bit architectures armel, armhf, hppa, m68k, mips, mipsel, powerpc and sh4.
๐ -O3 ๐
Optimize yet more! ๐ -O3 turns on every optimization specified by -O2, and it also brings along these flags:
-fgcse-after-reload -fipa-cp-clone -floop-interchange
-floop-unroll-and-jam -fpeel-loops -fpredictive-commoning
-fsplit-loops -fsplit-paths -ftree-loop-distribution
-ftree-partial-pre -funswitch-loops -fvect-cost-model=dynamic
-fversion-loops-for-strides
๐ง -O0 ๐ง
Reduce compilation time and make debugging produce the expected results. This is the default, so you get it without asking ๐ .
At -O0, GCC completely disables most optimization passes. They don't run even if you explicitly enable them on the command line, or if -Q --help=optimizers lists them as enabled by default. Many optimizations depend on code analysis or canonicalization passes that -O turns on, so running individual optimization passes in isolation wouldn't be useful anyway. Not worth the chaos, bestie.
๐ -Os ๐
Optimize for size! ๐งธ -Os enables all the -O2 optimizations except the ones that often make your code bigger:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, tells the compiler to tune for code size instead of execution speed, and runs further optimizations designed to shrink your code.
โก -Ofast โก
Disregard strict standards compliance. ๐ -Ofast enables all -O3 optimizations. It also enables optimizations that aren't valid for every standard-compliant program. It turns on -ffast-math, -fallow-store-data-races and the Fortran-specific -fstack-arrays, unless -fmax-stack-var-size is specified, and -fno-protect-parens. It turns off -fsemantic-interposition.
โ ๏ธ Danger zone, bestie: because -Ofast enables optimizations that aren't valid for all standard-compliant programs, it can change how your code behaves. Only reach for it if you've checked that your code can handle it. ๐
๐ -Og ๐
Optimize while keeping debugging in mind! ๐ต๏ธโโ๏ธ -Og should be the level of choice for the standard edit-compile-debug cycle. It gives you a reasonable blend of optimization, fast compilation and a good debugging experience, especially for code with a high abstraction penalty. Unlike -O0, this enables -fvar-tracking-assignments and -fvar-tracking, which handle debug information in the prologue and epilogue of functions better than -O0 does.
Like -O0, -Og completely skips a number of optimization passes, so the individual options that control them have no effect. Otherwise, -Og enables all -O1 optimization flags except the ones known to greatly interfere with debugging ๐
โโ๏ธ:
-fbranch-count-reg -fdelayed-branch -fdse -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fmove-loop-stores -fssa-phiopt
-ftree-bit-ccp -ftree-dse -ftree-pta -ftree-sra
๐ฆ -Oz ๐ฆ
Optimize aggressively for size rather than speed. ๐๏ธ This may increase the number of instructions executed if those instructions need fewer bytes to encode. -Oz behaves similarly to -Os, including enabling most -O2 optimizations.
If you use multiple -O options, with or without level numbers, the last one is the one that takes effect. Main character energy, the last one wins ๐.
Options of the form -fflag specify machine-independent flags. Most flags have both positive and negative forms, and the negative form of -ffoo is -fno-foo. In the list below, only one of the forms is listed, the one you typically use. You can figure out the other form by either removing no- or adding it. Easy peasy ๐.
The following options control specific optimizations. They're either activated by -O options or related to ones that are. You can use these flags in the rare cases when "fine-tuning" of the optimizations to be performed is desired. Only touch these if you know what you're doing, bestie ๐ซถ.
-fno-defer-popโ For machines that must pop arguments after a function call, this always pops the arguments as soon as each function returns. At levels-O1and higher,-fdefer-popis the default, which lets the compiler let arguments pile up on the stack for several function calls and then pop them all at once.-fforward-propagateโ Runs a forward propagation pass on RTL. The pass tries to combine two instructions and checks whether the result can be simplified. If loop unrolling is active, two passes are performed and the second one is scheduled after loop unrolling.
This option is enabled by default at optimization levels -O1, -O2, -O3 and -Os.
-favoid-store-forwarding/-fno-avoid-store-forwardingโ Lots of CPUs stall for many cycles when a load partially depends on previous smaller stores. This pass tries to spot those cases and dodge the penalty by changing the order of the load and store, then fixing up the loaded value. ๐ง
Disabled by default.
-ffp-contract=styleโ-ffp-contract=offturns off floating-point expression contraction.-ffp-contract=fastenables it, such as forming fused multiply-add operations, if the target has native support for them.-ffp-contract=onenables contraction if the language standard allows it. This is implemented for C and C++, where it enables contraction within one expression but not across different statements.
The default is -ffp-contract=off for C in a standards compliant mode (-std=c11 or similar), and -ffp-contract=fast otherwise.
-ffp-int-builtin-inexactโ Allows the built-in functions "ceil", "floor", "round" and "trunc", plus their "float" and "long double" variants, to generate code that raises the "inexact" floating-point exception for noninteger arguments. ISO C99 and C11 let these functions raise the "inexact" exception, but ISO/IEC TS 18661-1:2014, the C bindings to IEEE 754-2008 as integrated into ISO C23, does not. ๐ค
The default is -fno-fp-int-builtin-inexact, which disallows the exception from being raised, unless C17 or an earlier C standard is selected. This option does nothing unless -ftrapping-math is in effect.
NOTE ๐ท: Even if -fno-fp-int-builtin-inexact is used, if these functions generate a call to a library function, the "inexact" exception may still be raised if the library implementation doesn't follow TS 18661.
-fomit-frame-pointerโ Omits the frame pointer in functions that don't need one. This skips the instructions that save, set up and restore the frame pointer, and on many targets it also frees up an extra register. โจ
On some targets this flag has no effect, because the standard calling sequence always uses a frame pointer, so it can't be omitted.
Note that -fno-omit-frame-pointer doesn't guarantee the frame pointer is used in all functions. Several targets always omit the frame pointer in leaf functions.
Enabled by default at -O1 and higher.
-foptimize-crcโ okay bestie, this one is a CRC detective ๐ต๏ธโโ๏ธโจ It spots loops doing CRC math (that's polynomial long division, so fancy ๐งฎ) and swaps them for a faster version ๐ It recognizes 8, 16, 32, and 64 bit CRCs using a constant polynomial without the leading 1 bit, in both bit-forward and bit-reversed flavors ๐ฆ If the target has a CRC instruction and your polynomial matches it, it generates that instruction ๐ Otherwise, if the target has a carry-less-multiplication instruction, it uses that to make the CRC ๐ธ and if neither is available, it falls back to a table-based CRC ๐- Enabled by default at
-O2and higher. ๐
- Enabled by default at
-foptimize-sibling-callsโ this one optimizes sibling and tail recursive calls, so your recursion stops wasting stack space ๐ง- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-foptimize-strlenโ it glows up standard C string functions like"strlen","strchr", or"strcpy", plus their"_FORTIFY_SOURCE"counterparts, into faster alternatives ๐๏ธ๐จ- Enabled at levels
-O2,-O3.
- Enabled at levels
-finline-atomics,-fno-inline-atomicsโ inlines__atomicoperations whenever a lock-free instruction sequence is available ๐ This optimization is enabled by default. ๐-finline-stringops[=fn]โ expands memory and string operations (for now, only"memset") inline, even when the length is variable or big enough to need looping ๐งต This is most useful alongside-ffreestandingand-fno-builtin.- In some circumstances it can take advantage of known alignment and length multipliers, but even then it might be less efficient than optimized runtime implementations ๐ It can also bloat code size so much that a less performant but shared implementation ends up running faster, thanks to better use of code caches.
- This option is disabled by default. ๐ซถ
-fno-inlineโ don't expand any functions inline unless they're marked with the"always_inline"attribute ๐ซ This is the default when not optimizing.- You can exempt single functions from inlining by marking them with the
"noinline"attribute. ๐ฆ
- You can exempt single functions from inlining by marking them with the
-finline-small-functionsโ integrates functions into their callers when their body is smaller than the function call code, so the whole program gets smaller ๐ The compiler heuristically decides which functions are simple enough for this, and it applies to all functions, even ones not declared inline โจ- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-findirect-inliningโ inlines indirect calls that are known at compile time thanks to previous inlining ๐ง This only does anything when inlining is turned on by-finline-functionsor-finline-small-functions.- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-finline-functionsโ considers all functions for inlining, even ones not declared inline ๐ The compiler heuristically decides which are worth integrating.- If all calls to a given function get integrated, and the function is declared
"static", then it's normally not output as assembler code in its own right. ๐ - Enabled at levels
-O2,-O3,-Os. Also enabled by-fprofile-useand-fauto-profile. ๐ฅ
- If all calls to a given function get integrated, and the function is declared
-finline-functions-called-onceโ considers all"static"functions called once for inlining into their caller, even if they aren't marked"inline"๐ If a call to a function gets integrated, the function isn't output as assembler code on its own either.- Enabled at levels
-O1,-O2,-O3and-Os, but not-Og.
- Enabled at levels
-fearly-inliningโ inlines functions marked"always_inline", plus functions whose body seems smaller than the call overhead, early ๐โโ๏ธ This happens before the-fprofile-generateinstrumentation and the real inlining pass. It makes profiling significantly cheaper and usually makes inlining faster on programs with large chains of nested wrapper functions ๐ง- Enabled by default. โจ
-fipa-sraโ performs interprocedural scalar replacement of aggregates, removes unused parameters, and swaps parameters passed by reference for parameters passed by value ๐งฉ- Enabled at levels
-O2,-O3and-Os.
- Enabled at levels
-finline-limit=nโ by default, GCC caps the size of functions it'll inline ๐ This flag gives you coarse control over that cap.nis the size of functions that can be inlined, measured in pseudo instructions.- Inlining is actually controlled by a bunch of internal parameters, which are documented in the GCC Internals manual and shouldn't normally be set directly ๐ โโ๏ธ
- Note: there may be no value of
-finline-limitthat results in default behavior. ๐คทโโ๏ธ
Note: a pseudo instruction, in this particular context, is an abstract measurement of a function's size ๐ It in no way represents a count of assembly instructions, so its exact meaning might change from one release to another.
-fno-keep-inline-dllexportโ this is a more fine-grained version of-fkeep-inline-functions, and it only applies to functions declared with the"dllexport"attribute or declspec ๐ฏ-fkeep-inline-functionsโ in C, emits"static"functions declared"inline"into the object file, even if the function got inlined into all of its callers ๐ธ This switch doesn't affect functions using the"extern inline"extension in GNU C90. In C++, it emits any and all inline functions into the object file ๐-fkeep-static-functionsโ emits"static"functions into the object file, even if they're never used ๐ฆ-fkeep-static-constsโ emits variables declared"static const"when optimization isn't turned on, even if the variables aren't referenced ๐- GCC enables this option by default. If you want the compiler to check whether a variable is referenced regardless of optimization, use
-fno-keep-static-consts. ๐
- GCC enables this option by default. If you want the compiler to check whether a variable is referenced regardless of optimization, use
-fmerge-constantsโ tries to merge identical constants (string constants and floating-point constants) across compilation units ๐งฒ- This option is the default for optimized compilation if the assembler and linker support it. Use
-fno-merge-constantsto inhibit this behavior. - Enabled at levels
-O1,-O2,-O3,-Os.
- This option is the default for optimized compilation if the assembler and linker support it. Use
-fmerge-all-constantsโ tries to merge identical constants and identical variables ๐ This option implies-fmerge-constants. On top of that, it considers things like even constant initialized arrays, or initialized constant variables with integral or floating-point types ๐ง
โ ๏ธ Bestie, listen: languages like C or C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations. Using this option results in non-conforming behavior ๐ญ
-fmodulo-schedโ performs swing modulo scheduling immediately before the first scheduling pass ๐ It looks at innermost loops and reorders their instructions by overlapping different iterations.-fmodulo-sched-allow-regmovesโ more aggressive SMS-based modulo scheduling, with register moves allowed ๐ Setting this flag deletes certain anti-dependence edges, which triggers the generation of reg-moves based on life-range analysis. This option is only effective with-fmodulo-schedenabled.-fno-branch-count-regโ disables the optimization pass that scans for chances to use "decrement and branch" instructions on a count register, instead of instruction sequences that decrement a register, compare it against zero, and then branch based on the result ๐ข This is only meaningful on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390.- Note that
-fno-branch-count-regdoesn't remove the decrement and branch instructions introduced into the generated instruction stream by other optimization passes. - The default is
-fbranch-count-regat-O1and higher, except for-Og. ๐
- Note that
-fno-function-cseโ doesn't put function addresses in registers ๐ โโ๏ธ Instead, each instruction that calls a constant function contains the function's address explicitly.- This results in less efficient code, but some strange hacks that alter the assembler output may get confused by the optimizations performed when this option isn't used ๐
- The default is
-ffunction-cse
-ffuse-ops-with-volatile-accessโ allows limited optimization of operations with volatile memory access when doing so does not change the semantics outlined in- The default is
-ffuse-ops-with-volatile-access๐
- The default is
-fno-zero-initialized-in-bssโ if the target supports a BSS section, GCC by default puts variables initialized to zero into BSS, which can save space in the resulting code ๐พ This option turns that behavior off, because some programs explicitly rely on variables going to the data section---e.g., so the resulting executable can find the beginning of that section and/or make assumptions based on that ๐งธ- The default is
-fzero-initialized-in-bssexcept in Ada. ๐
- The default is
-fthread-jumpsโ performs optimizations that check whether a jump branches to a location where another comparison subsumed by the first one is found ๐ฆ If so, the first branch is redirected to either the destination of the second branch or a point immediately following it, depending on whether the condition is known to be true or false.- Enabled at levels
-O1,-O2,-O3,-Os.
- Enabled at levels
-fsplit-wide-typesโ when using a type that occupies multiple registers, such as"long long"on a 32-bit system, the registers get split apart and allocated independently ๐ง This normally generates better code for those types, but may make debugging more difficult ๐- Enabled at levels
-O1,-O2,-O3,-Os.
- Enabled at levels
-fsplit-wide-types-earlyโ fully splits wide types early, instead of very late โฐ This option has no effect unless-fsplit-wide-typesis turned on.- This is the default on some targets. โจ
-fcse-follow-jumpsโ in common subexpression elimination (CSE), it scans through jump instructions when the target of the jump isn't reached by any other path ๐ For example, when CSE encounters an"if"statement with an"else"clause, CSE follows the jump when the condition tested is false.- Enabled at levels
-O2,-O3,-Os. ๐ซถ
- Enabled at levels
-fcse-skip-blocksโ okay bestie, this is basically-fcse-follow-jumpsbut with more โจReACHโจ ๐ฆ It makes CSE follow jumps that conditionally skip over blocks. When CSE hits a simpleifwith noelseclause,-fcse-skip-blockstells it to follow the jump right around the body of theif. ๐
Enabled at levels -O2, -O3, -Os.
Wait, let me redo that properly, because I'm getting ahead of myself. Here it is in order:
โจ OPTIONS (continued) โจ
-fcse-skip-blocksโ this is giving "follow the jump" energy ๐ฆ It's similar to-fcse-follow-jumps, but CSE also follows jumps that conditionally skip over blocks. When CSE runs into a simpleifwith noelseclause,-fcse-skip-blocksmakes it follow the jump around the body of theif. ๐
Enabled at levels -O2, -O3, -Os.
-frerun-cse-after-loopโ okay so this one re-runs common subexpression elimination after the loop optimizations finish ๐โจ main character re-run energy ๐
Enabled at levels -O2, -O3, -Os.
-fgcseโ slay ๐ this performs a global common subexpression elimination pass, and it also does global constant and copy propagation. iconic behavior ๐
โ ๏ธ Heads up, bestie: when you're compiling a program that uses computed gotos (a GCC extension ๐), you might get better run-time performance if you disable the global CSE pass by adding -fno-gcse to the command line. no cap.
Enabled at levels -O2, -O3, -Os.
-fgcse-lmโ lowkey my favourite of the GCSE crew ๐ธ When it's enabled, global CSE tries to move loads that are only killed by stores into themselves. So a loop with a load/store sequence can become a load outside the loop and a copy/store inside the loop. ๐ง
Enabled by default when -fgcse is enabled.
-fgcse-smโ store motion, babe ๐ฆ When it's enabled, a store motion pass runs after global CSE and tries to move stores out of loops. Used together with-fgcse-lm, a loop with a load/store sequence can turn into a load before the loop and a store after it. ๐ซถ
Not enabled at any optimization level.
-fgcse-lasโ this one is so precious ๐ฅน It makes the global CSE pass eliminate redundant loads that come after stores to the same memory location (both partial and full redundancies). no notes ๐
Not enabled at any optimization level.
-fgcse-after-reloadโ clean-up crew vibes ๐งนโจ When it's enabled, a redundant load elimination pass runs after reload. Its whole purpose is to tidy up redundant spilling.
Enabled by -O3, -fprofile-use and -fauto-profile.
-faggressive-loop-optimizationsโ the loop optimizer gets to use language constraints to work out bounds on how many iterations a loop does ๐ฅ It assumes loop code doesn't invoke undefined behavior, like causing signed integer overflows or out-of-bounds array accesses ๐ญ Those bounds then guide loop unrolling, peeling, and loop exit test optimizations. This option is enabled by default.-funconstrained-commonsโ this tells the compiler that variables declared in common blocks (for example, in Fortran) may later be overridden with longer trailing arrays. It prevents certain optimizations that depend on knowing the array bounds. ๐-fcrossjumpingโ performs the cross-jumping transformation, which unifies equivalent code and saves code size ๐ The resulting code may or may not perform better than without cross-jumping, so it's a mixed bag ngl.
Enabled at levels -O2, -O3, -Os.
-fauto-inc-decโ combines increments or decrements of addresses with memory accesses โจ This pass is always skipped on architectures that don't have instructions to support it. Enabled by default at-O1and higher on architectures that support this.-fdceโ performs dead code elimination (DCE) on RTL ๐๏ธ๐ Enabled by default at-O1and higher.-fdseโ performs dead store elimination (DSE) on RTL ๐ Enabled by default at-O1and higher.-fif-conversionโ attempts to transform conditional jumps into branch-less equivalents ๐ฆ This includes conditional moves, min, max, set flags and abs instructions, and some tricks doable with standard arithmetic. Whether conditional execution gets used on chips that have it is controlled by-fif-conversion2.
Enabled at levels -O1, -O2, -O3, -Os, but not with -Og.
-fif-conversion2โ uses conditional execution (where available) to transform conditional jumps into branch-less equivalents ๐
Enabled at levels -O1, -O2, -O3, -Os, but not with -Og.
-fdeclone-ctor-dtorโ okay so the C++ ABI wants multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that callsoperator deleteafterwards ๐ For a hierarchy with virtual bases, the base and complete variants are clones, meaning two copies of the function. With this option, those two variants become thunks that call a common implementation. ๐ง
Enabled by -Os.
-fdelete-null-pointer-checksโ assumes programs can't safely dereference null pointers, and that no code or data element lives at address zero ๐ This option enables simple constant folding optimizations at all optimization levels. Other GCC passes use this flag to control global dataflow analyses that eliminate useless null pointer checks. These assume that a memory access to address zero always results in a trap, so if a pointer is checked after it has already been dereferenced, it can't be null.
โ ๏ธ Careful, bestie: in some environments this assumption isn't true. Use -fno-delete-null-pointer-checks to disable this optimization for programs that depend on that behavior.
This option is enabled by default on most targets. On AVR and MSP430, this option is completely disabled.
Passes that use the dataflow information are enabled independently at different optimization levels.
-fdevirtualizeโ attempts to convert calls to virtual functions into direct calls ๐ฆ This happens both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp). Enabled at levels-O2,-O3,-Os.-fdevirtualize-speculativelyโ attempts to convert calls to virtual functions into speculative direct calls ๐ฎ Based on analysis of the type inheritance graph, it figures out the set of likely targets for a given call. If the set is small (preferably size 1), the call becomes a conditional that picks between a direct and an indirect call. The speculative calls enable more optimizations, like inlining. If they seem useless after further optimization, they get converted back into their original form.-fdevirtualize-at-ltransโ streams extra information needed for aggressive devirtualization when running the link-time optimizer in local transformation mode ๐ฆ This enables more devirtualization but significantly increases the size of streamed data. For this reason it's disabled by default.-fexpensive-optimizationsโ performs a number of minor optimizations that are relatively expensive ๐ธ
Enabled at levels -O2, -O3, -Os.
-fext-dce,-fno-ext-dceโ performs dead code elimination on zero and sign extensions, using special dataflow analysis ๐งผ-freeโ attempts to remove redundant extension instructions ๐ท This is especially helpful for the x86-64 architecture, which implicitly zero-extends in 64-bit registers after writing to their lower 32-bit half.
Enabled for Alpha, AArch64, LoongArch, PowerPC, RISC-V, SPARC, h83000 and x86 at levels -O2, -O3, -Os.
-fno-lifetime-dseโ in C++, an object's value is only affected by changes within its lifetime ๐ฐ๏ธ When the constructor begins, the object has an indeterminate value, and any changes during its lifetime are dead once it's destroyed. Normally dead store elimination takes advantage of this. If your code relies on the object storage's value persisting past the object's lifetime, use this flag to turn that optimization off. To keep stores made before the constructor starts (for example, because youroperator newclears the object storage) but still treat the object as dead after the destructor, use-flifetime-dse=1. The default behavior can be explicitly selected with-flifetime-dse=2.-flifetime-dse=0is equivalent to-fno-lifetime-dse.-flive-range-shrinkageโ attempts to decrease register pressure through register live range shrinkage ๐ฌ๏ธ This is helpful for fast processors with small or moderate-size register sets.- *
-fira-algorithm=algorithm* โ picks the coloring algorithm for the integrated register allocator ๐จ The algorithm argument can bepriority, which specifies Chow's priority coloring, orCB, which specifies Chaitin-Briggs coloring. Chaitin-Briggs coloring isn't implemented for all architectures, but on the targets that do support it, it's the default because it generates better code. โจ - *
-fira-region=region* โ picks the regions the integrated register allocator uses ๐บ๏ธ The region argument should be one of the following:allโ uses all loops as register allocation regions. This can give the best results for machines with a small and/or irregular register set.mixedโ uses all loops except loops with small register pressure as the regions. This usually gives the best results in most cases and for most architectures, and it's enabled by default when compiling with optimization for speed (-O,-O2, ...).oneโ uses all functions as a single region. This typically results in the smallest code size, and it's enabled by default for-Osor-O0.
-fira-hoist-pressureโ uses IRA to evaluate register pressure in the code hoisting pass when deciding whether to hoist expressions ๐๏ธ This usually results in smaller code, but it can slow the compiler down.
This option is enabled at level -Os for all targets.
-fira-loop-pressureโ uses IRA to evaluate register pressure in loops when deciding whether to move loop invariants ๐ This usually results in faster and smaller code on machines with large register files (>= 32 registers), but it can slow the compiler down.
This option is enabled at level -O3 for some targets.
-fno-ira-share-save-slotsโ disables sharing of stack slots used for saving call-used hard registers that live through a call ๐ โโ๏ธ Each hard register gets its own stack slot, so function stack frames end up larger.-fno-ira-share-spill-slots: bestie, this one is a hard pass ๐ โโ๏ธ It disables sharing of stack slots allocated for pseudo-registers ๐งฑ Every pseudo-register that doesn't get a hard register gets its very own stack slot, so function stack frames end up larger ๐ฆ๐-flra-remat: okay this one is giving main character energy โจ It turns on CFG-sensitive rematerialization in LRA ๐ฆ Instead of loading values of spilled pseudos, LRA tries to rematerialize (recalculate) them whenever that's profitable ๐งฎ Enabled at levels-O2,-O3,-Os๐-fdelayed-branch: if the target machine supports it, GCC tries reordering instructions so they can use the instruction slots after delayed branch instructions ๐ง Enabled at levels-O1,-O2,-O3,-Os, but not at-Og๐ โโ๏ธ-fschedule-insns: if the target supports it, GCC reorders instructions to get rid of execution stalls caused by required data being unavailable โณ This helps machines with slow floating point or memory load instructions, since other instructions can get issued while you wait for the load or float result to show up ๐ซถ It's conventionally enabled at-O2and-O3, but lowkey plenty of targets override that ๐ญ On x86 it's disabled at all levels, while on AArch64 it's only enabled at-O3๐ธ-fschedule-insns2: same main vibe as-fschedule-insns, but this one adds an extra pass of instruction scheduling after register allocation ๐ It's especially useful on machines with a relatively small number of registers, where memory load instructions take more than one cycle ๐ง Enabled at levels-O2,-O3,-Osโจ-fno-sched-interblock: disables instruction scheduling across basic blocks ๐ซ This is normally on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐-fno-sched-spec: disables speculative motion of non-load instructions ๐ โโ๏ธ This is normally enabled when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐ซง-fsched-pressure: turns on register pressure sensitive insn scheduling before register allocation ๐ง It only makes sense when scheduling before register allocation is enabled, i.e. with-fschedule-insnsor at-O2or higher ๐ Using it can improve the generated code and shrink its size by stopping register pressure from climbing above the number of available hard registers, which would otherwise mean spills later in register allocation ๐ซ-fsched-spec-load: allows speculative motion of some load instructions ๐ฎ It only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐ท-fsched-spec-load-dangerous: allows speculative motion of more load instructions โ ๏ธ The name is literally a warning label ๐ It only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐-fsched-stalled-insns,-fsched-stalled-insns=n: this decides how many insns (if any!) can be moved prematurely from the queue of stalled insns into the ready list during the second scheduling pass ๐-fno-sched-stalled-insnsmeans none get moved early,-fsched-stalled-insns=0means there's no limit on how many queued insns can be moved prematurely, and-fsched-stalled-insnswith no value is the same as-fsched-stalled-insns=1๐ง-fsched-stalled-insns-dep,-fsched-stalled-insns-dep=n: defines how many insn groups (cycles) get checked for a dependency on a stalled insn that's a candidate for premature removal from the queue of stalled insns ๐ This only has an effect during the second scheduling pass, and only if-fsched-stalled-insnsis used ๐ซถ-fno-sched-stalled-insns-depis equivalent to-fsched-stalled-insns-dep=0, and-fsched-stalled-insns-depwithout a value is equivalent to-fsched-stalled-insns-dep=1๐-fsched2-use-superblocks: when scheduling after register allocation, this uses superblock scheduling ๐งฉ That allows motion across basic block boundaries, which gives faster schedules โก Heads up, though: this one is experimental, because not all machine descriptions model the CPU closely enough to avoid unreliable results from the algorithm ๐ฅบ It only makes sense after register allocation, i.e. with-fschedule-insns2or at-O2or higher ๐-fsched-group-heuristic: enables the group heuristic in the scheduler ๐งโ๐คโ๐ง It favors the instruction that belongs to a schedule group ๐ This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-critical-path-heuristic: enables the critical-path heuristic in the scheduler ๐ค๏ธ It favors instructions on the critical path ๐ This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher โญ-fsched-spec-insn-heuristic: enables the speculative instruction heuristic ๐ฎ It favors speculative instructions with greater dependency weakness ๐ฆ This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐ซถ-fsched-rank-heuristic: enables the rank heuristic ๐ It favors the instruction belonging to a basic block with greater size or frequency ๐ This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-last-insn-heuristic: enables the last-instruction heuristic ๐ฐ๏ธ It favors the instruction that's less dependent on the last instruction scheduled ๐ง This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐ธ-fsched-dep-count-heuristic: enables the dependent-count heuristic ๐งฎ It favors the instruction that has more instructions depending on it ๐ซ This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher โจ-fspeculatively-call-stored-functions: GCC attempts to convert indirect calls of function pointers into calls through pointers loaded from a structure field, but only if all visible stores to that field store just a single candidate ๐ฒ When it works, the call becomes a conditional that picks between the direct call and the original indirect one ๐ง These speculative calls often enable more optimizations, such as inlining ๐ And if they seem useless after further optimization, they get converted back into their original form ๐-freschedule-modulo-scheduled-loops: modulo scheduling is performed before traditional scheduling ๐ If a loop is modulo scheduled, later scheduling passes may change its schedule, and this option is how you control that behavior ๐๏ธ-fselective-scheduling: schedules instructions using the selective scheduling algorithm ๐ฏ Selective scheduling runs instead of the first scheduler pass ๐ซถ-fselective-scheduling2: same energy, schedules instructions with the selective scheduling algorithm, but this one runs instead of the second scheduler pass ๐ฅฐ-fsel-sched-pipelining: enables software pipelining of innermost loops during selective scheduling ๐ This option has no effect unless-fselective-schedulingor-fselective-scheduling2is turned on ๐-fsel-sched-pipelining-outer-loops: when pipelining loops during selective scheduling, this also pipelines outer loops ๐ช It has no effect unless-fsel-sched-pipeliningis turned on ๐ซ-fsemantic-interposition: okay this one is a lot ๐ซ Some object formats, like ELF, allow the dynamic linker to interpose symbols ๐ That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, because it has to assume the function or variable in question might get swapped out ๐ต This is useful for things like rewriting memory allocation functions with a debugging implementation, but it's expensive in terms of code quality ๐ธ With-fno-semantic-interposition, the compiler assumes that if interposition happens for functions, the overwriting function will have precisely the same semantics (and side effects) ๐งธ Similarly, if interposition happens for variables, the constructor of the variable will be the same ๐ The flag has no effect for functions explicitly declaredinline(where interposition is never allowed to change semantics), and for symbols explicitly declared weak ๐ โโ๏ธ-fshrink-wrap: emits function prologues only before the parts of the function that actually need them, instead of at the very top ๐ This flag is enabled by default at-Oand higher โจ-fshrink-wrap-separate: shrink-wraps separate parts of the prologue and epilogue separately, so those parts only run when they're needed ๐ This option is on by default, but has no effect unless-fshrink-wrapis also turned on and the target supports this ๐ฆ-fcaller-saves: enables allocating values to registers that get clobbered by function calls, by emitting extra instructions to save and restore those registers around such calls ๐งบ This allocation only happens when it seems to result in better code ๐ This option is always enabled by default on certain machines, usually the ones with no call-preserved registers to use instead ๐ฅ๏ธ Enabled at levels-O2,-O3,-Os๐ธ-fcombine-stack-adjustments: tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐งฉ Enabled by default at-O1and higher ๐-fipa-ra: uses caller save registers for allocation if those registers aren't used by any called function ๐งโ๐ณ In that case, there's no need to save and restore them around calls ๐ซง This is only possible if the called functions are part of the same compilation unit as the current function, and they're compiled before it ๐ Enabled at levels-O2,-O3,-Os, however the option is disabled if the generated code will be instrumented for profiling (-p, or-pg) or if the callee's register usage can't be known exactly (this happens on targets that don't expose prologues and epilogues in RTL) ๐-fconserve-stack: minimizes stack usage ๐ฅน The compiler tries to use less stack space, even if that makes the program slower ๐ข This option implies setting thelarge-stack-frameparameter to100and thelarge-stack-frame-growthparameter to400๐-ftree-reassocโ okay so this one does reassociation on trees ๐ฆ It's switched on by default at-O1and higher โจ-fcode-hoistingโ code hoisting, bestie ๐ซถ It tries to move the evaluation of expressions that run on all paths to the function exit as early as possible. It's especially useful as a code size optimization, but it often helps code speed too ๐ On by default at-O2and higher.-ftree-preโ partial redundancy elimination (PRE) on trees ๐ธ Enabled by default at-O2and-O3.-ftree-partial-preโ makes PRE more aggressive ๐ฅ Enabled by default at-O3.-ftree-forwpropโ forward propagation on trees ๐ง On by default at-O1and higher.-ftree-freโ full redundancy elimination (FRE) on trees ๐ The tea is that FRE only considers expressions computed on all paths leading to the redundant computation, while PRE is the bigger, messier sibling. FRE's analysis is faster than PRE, though it exposes fewer redundancies. On by default at-O1and higher.-ftree-phipropโ hoists loads from conditional pointers on trees โจ This pass is enabled by default at-O1and higher.-fhoist-adjacent-loadsโ speculatively hoists loads from both branches of an if-then-else, but only if the loads come from adjacent locations in the same structure and the target architecture has a conditional move instruction ๐ On by default at-O2and higher.-ftree-copy-propโ copy propagation on trees ๐ฆ This pass gets rid of unnecessary copy operations. On by default at-O1and higher.-fipa-pure-constโ figures out which functions are pure or constant ๐ฎ Enabled by default at-O1and higher.-fipa-referenceโ finds which static variables do not escape the compilation unit ๐ Enabled by default at-O1and higher.-fipa-reference-addressableโ finds read-only, write-only and non-addressable static variables ๐ Enabled by default at-O1and higher.-fipa-reorder-for-localityโ groups call chains close together in the binary layout ๐ง The goal is better code locality and shorter jump distances between frequently called functions. Unlike-freorder-functions, this pass looks at the call chains between functions and groups them together, instead of putting all hot/normal/cold/never-executed functions into separate sections. Unlike-fprofile-reorder-functions, it aims to improve code locality throughout the runtime of the program rather than focusing on program startup.
This option is incompatible with an explicit -flto-partition= option, since it enforces a custom partitioning scheme.
If you use this option, it's recommended to also use profile feedback, but this option is not enabled by default otherwise ๐
-fipa-stack-alignmentโ reduces stack alignment on call sites if possible ๐ Enabled by default.-fipa-ptaโ interprocedural pointer analysis and interprocedural modification and reference analysis ๐ง
This one can cause excessive memory and compile-time usage on large compilation units, so be careful, bestie ๐ It is not enabled by default at any optimization level.
-fipa-profileโ interprocedural profile propagation ๐ Functions called only from cold functions are marked as cold. Functions executed once (such as "cold", "noreturn", static constructors or destructors) are identified too. Cold functions and loop less parts of functions executed once are then optimized for size. Enabled by default at-O1and higher.-fipa-modrefโ interprocedural mod/ref analysis ๐ฆ This optimization analyzes the side effects of functions (memory locations that are modified or referenced), which lets the compiler optimize better across the function call boundary. On by default at-O1and higher.-fipa-cpโ interprocedural constant propagation ๐ This optimization analyzes the program to figure out when values passed to functions are constants, then optimizes accordingly. It can substantially increase performance if your app passes constants to functions. Enabled by default at-O2,-Osand-O3. It's also enabled by-fprofile-useand-fauto-profile.-fipa-cp-cloneโ function cloning to make interprocedural constant propagation stronger ๐ When enabled, interprocedural constant propagation clones a function when an externally visible function can be called with constant arguments.
Because this optimization can create multiple copies of functions, it may significantly increase code size ๐ญ Enabled by default at-O3. It's also enabled by-fprofile-useand-fauto-profile.
-fipa-bit-cpโ interprocedural bitwise constant propagation ๐ When enabled, it does the bitwise version of the constant propagation. Enabled by default at-O2, and by-fprofile-useand-fauto-profile. It requires that-fipa-cpis enabled.-fipa-vrpโ interprocedural propagation of value ranges ๐ธ When enabled, it propagates value ranges across functions. Enabled by default at-O2. It requires that-fipa-cpis enabled.-fipa-icf-functions,-fipa-icf-variables,-fipa-icfโ Identical Code Folding ๐ง-fipa-icf-functionsdoes it for functions,-fipa-icf-variablesdoes it for read-only variables, and-fipa-icfdoes both. This reduces code size, but it may disturb unwind stacks by swapping a function out for an equivalent one with a different name. It works even better with link-time optimization enabled โจ
Although the behavior is similar to the Gold Linker's ICF optimization, GCC ICF works on different levels, so the optimizations are not the same. There are equivalences that only GCC finds and equivalences that only Gold finds ๐ฆ
-fipa-icf is enabled by default at -O2 and -Os.
-flate-combine-instructionsโ turns on two instruction combination passes that run pretty late in the compilation process ๐ฅ One runs before register allocation and the other runs after it. The main goal is to substitute definitions into all their uses. Most targets enable this flag by default at-O2and-Os.-flive-patching=levelโ controls GCC's optimizations so the output is suitable for live-patching ๐ฉน Here's the deal: if an optimization uses a function's body (or info pulled from it) to change another function, that other function is called an impacted function. If a function gets patched, its impacted functions should be patched too. The impacted functions are determined by the compiler's interprocedural optimizations. For example, a caller is impacted when a function gets inlined into it, when a function is cloned and its caller is changed to call the clone, or when a function's pureness/constness info is extracted to optimize its direct or indirect callers. Usually, the more IPA optimizations are on, the more impacted functions each function has. So IPA optimizations can be partially enabled at two different levels, which keeps the list manageable ๐งฎ
The level argument should be one of the following:
inline-cloneโ only inlining and cloning optimizations are enabled, which includes inlining, cloning, interprocedural scalar replacement of aggregates and partial inlining. So when patching a function, all its callers and its clones' callers are impacted, and they need to be patched too.
-flive-patching=inline-clone disables the following optimization flags: -fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment -fipa-modref
inline-only-staticโ only inlining of static functions is enabled ๐ท So when patching a static function, all its callers are impacted and need to be patched too.
On top of everything -flive-patching=inline-clone disables, -flive-patching=inline-only-static also disables these: -fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp
When -flive-patching is specified without any value, the default value is inline-clone.
This flag is disabled by default.
Note that-flive-patchingis not supported with link-time optimization (-flto) โ ๏ธ
-fisolate-erroneous-paths-dereferenceโ detects paths that trigger erroneous or undefined behavior from dereferencing a null pointer (with-fdelete-null-pointer-checksenabled) or from a division by zero ๐ง It isolates those paths from the main control flow and turns the statement with erroneous or undefined behavior into a trap. On by default at-O2and higher.-fisolate-erroneous-paths-attributeโ detects paths that trigger erroneous or undefined behavior because a null value is used in a way forbidden by a "returns_nonnull" or "nonnull" attribute ๐ It isolates those paths from the main control flow and turns the statement into a trap.
This is not currently enabled, but it may be enabled by -O2 in the future ๐
-ftree-sinkโ forward store motion on trees ๐ฆ On by default at-O1and higher.-ftree-bit-ccpโ sparse conditional bit constant propagation on trees, plus pointer alignment info propagation ๐ This pass only operates on local scalar variables. It's enabled by default at-O1and higher, except for-Og. It requires that-ftree-ccpis enabled.-ftree-ccpโ sparse conditional constant propagation (CCP) on trees ๐ This pass only operates on local scalar variables. Enabled by default at-O1and higher.-fssa-backpropโ propagates info about uses of a value up the definition chain to simplify the definitions ๐งน For example, this pass strips sign operations if the sign of a value never matters. Enabled by default at-O1and higher.
Okay bestie, let's keep going ๐ โจ These are the tree-level passes doing the behind-the-scenes cleanup, and they are giving main character energy ๐ฆ
-fssa-phioptโ pattern matching on SSA PHI nodes to tidy up conditional code ๐ง It's on by default at-O1and higher, except for-Og๐-ftree-switch-conversionโ turns simple initializations inside a switch into initializations from a scalar array ๐ On by default at-O2and higher.-ftree-tail-mergeโ hunts down identical chunks of code and, when it finds them, swaps one for a jump to the other ๐ฆ This is known as tail merging or cross jumping. On by default at-O2and higher. You can cap how long this pass takes with themax-tail-merge-comparisonsparameter and themax-tail-merge-iterationsparameter ๐-ftree-cselimโ conditional store elimination on trees ๐ On by default at-O1and higher, but only on targets that have conditional move instructions.-ftree-dceโ dead code elimination (DCE) on trees ๐ On by default at-O1and higher.-ftree-builtin-call-dceโ conditional DCE for calls to built-in functions that may set"errno"but are otherwise free of side effects ๐ธ On by default at-O2and higher, as long as-Osisn't also specified.-ffinite-loopsโ assumes a loop with an exit will eventually take that exit instead of spinning forever ๐ This lets the compiler remove loops that have no side effects, since it isn't worrying about endless looping. It's on by default at-O2for C++ with-std=c++11or higher.-ftree-dominator-optsโ a bunch of simple scalar cleanups (constant/copy propagation, redundancy elimination, range propagation and expression simplification) based on a dominator tree traversal โจ It also does jump threading, which reduces jumps to jumps. On by default at-O1and higher.-ftree-dseโ dead store elimination (DSE) on trees ๐งน A dead store is a store into a memory location that gets overwritten later by another store with no loads in between. In that case the earlier store can be deleted. On by default at-O1and higher.-ftree-chโ loop header copying on trees ๐ This helps code motion optimizations work better and saves one jump. On by default at-O1and higher, but not for-Os, since it usually bumps up code size.-ftree-loop-optimizeโ loop optimizations on trees ๐ On by default at-O1and higher.-ftree-loop-linear,-floop-strip-mine,-floop-blockโ loop nest optimizations, same as-floop-nest-optimize๐ง To use this transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure is enabled.-fgraphite-identityโ enables the identity transformation for graphite ๐ช For every SCoP, GCC builds the polyhedral representation and transforms it back to gimple. With-fgraphite-identityyou can check the costs or benefits of the GIMPLE -> GRAPHITE -> GIMPLE round trip. The isl code generator also does some minimal optimizations, like index splitting and dead code elimination in loops.-floop-nest-optimizeโ turns on the isl based loop nest optimizer ๐ It's a generic one built on the Pluto optimization algorithms, and it works out a loop structure tuned for data-locality and parallelism.
โ ๏ธ This option is experimental, so handle it with care bestie ๐
-floop-parallelize-allโ uses Graphite data dependence analysis to find loops that can be parallelized ๐งต It parallelizes every loop that can be analyzed as having no loop carried dependences, without checking whether parallelizing is actually profitable.-ftree-coalesce-varsโ when the program is transformed out of SSA representation, this tries to reduce copying by coalescing versions of different user-defined variables, not just compiler temporaries ๐ซถ In the negated form, this flag prevents SSA coalescing of user variables. It's on by default if optimization is enabled, and it does very little otherwise.
โ ๏ธ This may severely limit your ability to debug an optimized program compiled with -fno-var-tracking-assignments ๐ญ
-ftree-loop-if-convertโ transforms conditional jumps in the innermost loops into branch-less equivalents ๐ The goal is to strip control flow out of those loops so the vectorization pass can handle them better. It's on by default if vectorization is enabled.-ftree-loop-distributionโ loop distribution ๐ This can improve cache performance on big loop bodies and lets further loop optimizations, like parallelization or vectorization, take place. For example, this loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
gets split into this:
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
On by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-ftree-loop-distribute-patternsโ distributes loops that can be code generated as calls to a library ๐งธ On by default at-O2and higher, and also enabled by-fprofile-useand-fauto-profile.
This pass distributes the initialization loops and generates a call to memset zero. For example, this loop:
DO I = 1, N
A(I) = 0
B(I) = A(I) + I
ENDDO
becomes this:
DO I = 1, N
A(I) = 0
ENDDO
DO I = 1, N
B(I) = A(I) + I
ENDDO
and the initialization loop turns into a call to memset zero ๐
-floop-interchangeโ loop interchange, done outside of graphite ๐ This can improve cache performance on loop nests and lets further loop optimizations, like vectorization, happen. For example, this C loop:
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
gets transformed into this:
for (int i = 0; i < N; i++)
for (int k = 0; k < N; k++)
for (int j = 0; j < N; j++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
On by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐ซง
-floop-unroll-and-jamโ applies unroll and jam transformations to feasible loops ๐ซง In a loop nest, this unrolls the outer loop by some factor and fuses the resulting multiple inner loops. On by default at-O3, and also enabled by-fprofile-useand-fauto-profile.-ftree-loop-imโ loop invariant motion on trees ๐งฒ This only moves the invariants that are hard to handle at RTL level, like function calls or operations that expand into nontrivial sequences of insns. With-funswitch-loops, it also moves operands of invariant conditions out of the loop, so loop unswitching can rely on just trivial invariantness analysis. The pass also includes store motion.-ftree-loop-ivcanonโ creates a canonical counter for the number of iterations in loops where figuring that count out needs complicated analysis ๐ข Later optimizations can then find the number easily. It's especially useful together with unrolling.-ftree-scev-cpropโ final value replacement โจ If a variable changes in a loop in a way that its value on exit can be worked out from just its initial value and the number of loop iterations, uses of the final value get replaced with that computation, as long as it's cheap enough. This reduces data dependencies and may allow more simplifications. On by default at-O1and higher.-fivoptsโ induction variable optimizations on trees ๐ That's strength reduction, induction variable merging and induction variable elimination. On by default at-O1and higher.-ftree-parallelize-loops,-ftree-parallelize-loops=nโ parallelizes loops by splitting their iteration space to run in multiple threads ๐งต This only works for loops whose iterations are independent and can be arbitrarily reordered. It's only worth it on multiprocessor machines, for CPU-intensive loops rather than ones held back by something like memory bandwidth. This option implies-pthread, so it's only supported on targets that support-pthread.- With a positive value
n, the number of threads is fixed at compile time and can't be changed after compilation. The compiler generates#pragma omp parallel num_threads(n). - Without
=n(just-ftree-parallelize-loops), the number of threads is decided at program execution time through theOMP_NUM_THREADSenvironment variable. IfOMP_NUM_THREADSisn't set, the OpenMP runtime auto-detects the number of available processors and uses that value. This lets you make binaries that adapt to different hardware without recompiling ๐ธ
- With a positive value
-ftree-ptaโ function-local points-to analysis on trees ๐ฏ On by default at-O1and higher, except for-Og.-ftree-sraโ scalar replacement of aggregates ๐ฌ This swaps structure references for scalars so structs don't get committed to memory too early. On by default at-O1and higher, except for-Og.-fstore-mergingโ merges narrow stores to consecutive memory addresses ๐ฆ It takes contiguous stores of immediate values that are narrower than a word and merges them into fewer, wider stores to cut down on instructions. On by default at-O2and higher, as well as-Os๐ซถ-ftree-terโ okay bestie, this one does temporary expression replacement during theSSA->normalphase ๐ Single use/single def temporaries get swapped out at their use location for their defining expression โจ It leaves you with non-GIMPLE code, but the expanders get way more complex trees to work with, which means better RTL generation ๐ง It's on by default at-O1and higher ๐ธ-ftree-slsrโ this is giving straight-line strength reduction on trees ๐ฅ It spots related expressions involving multiplications and swaps them for cheaper calculations when it can ๐ Enabled by default at-O1and higher โจ-ftree-vectorizeโ vectorization on trees ๐ฆ This flag also turns on-ftree-loop-vectorizeand-ftree-slp-vectorize, as long as you haven't explicitly specified them ๐-ftree-loop-vectorizeโ loop vectorization on trees ๐ It's on by default at-O2, and it also gets switched on by-ftree-vectorize,-fprofile-use, and-fauto-profile๐ซถ-ftree-slp-vectorizeโ basic block vectorization on trees ๐ On by default at-O2, and also enabled by-ftree-vectorize,-fprofile-use, and-fauto-profile๐-ftrivial-auto-var-init=choiceโ main character energy alert ๐จ This one initializes automatic variables and temporary objects with either a pattern or zeroes, which boosts security and predictability by stopping uninitialized memory from being leaked or used ๐ก๏ธ GCC still treats an automatic variable with no explicit initializer as uninitialized, so-Wuninitializedand-Wanalyzer-use-of-uninitialized-valuewill still warn about those, and the compiler will still optimize as if the variable were uninitialized ๐ With this flag on, GCC also zeroes any padding in automatic variables or temporaries that have structure or union types ๐งธ Heads up: the current implementation can't initialize automatic variables whose initialization gets bypassed through aswitchorgotostatement ๐ญ Use-Wtrivial-auto-var-initto report all such cases ๐- The three values of choice are:
uninitializedโ doesn't initialize any automatic variables ๐patternโ initializes automatic variables with values that will likely turn logic bugs into crashes down the line ๐ฅ They're easy to recognize in a crash dump ๐ and they aren't values programmers can rely on for useful program semantics ๐ซ The current value is a byte-repeatable pattern with byte0xFE, and the values used for pattern initialization might be changed in the future ๐ฎzeroโ initializes automatic variables with zeroes ๐
- The default is
uninitializedexcept for C++26. In C++26, if-ftrivial-auto-var-init=isn't specified at all, automatic variables and temporary objects are zero initialized, but zero initialization of padding bits does not happen ๐งธ - Quick note: the initializer values, whether zero or pattern, refer to the data representation (in memory or machine registers), not to their interpretation as numerical values ๐ค This distinction can matter in languages that support types with biases or implicit multipliers, and with extensions like hardbool. For example, a variable that uses 8 bits to represent (biased) quantities in the "range 160..400" will be initialized with the bit patterns
0x00or0xFE, depending on the choice, whether or not those representations stand for values in that range. Even if they do, the interpretation of the value held by the variable depends on the bias ๐ฏ - A hardbool variable that uses, say,
0x5Aand0xA5for "false" and "true", respectively, will trap with either choice of trivial initializer. That means zero initialization won't convert to the representation for "false", even if it would for astaticvariable of the same type ๐ So the initializer pattern doesn't generally depend on the type of the initialized variable. One notable exception is that (non-hardened) boolean variables that fit in registers are initialized with "false" (zero), even when pattern is requested ๐ - You can control this for a specific variable with the
uninitializedvariable attribute (the standard attribute) or C++26's[[indeterminate]]๐ฏ
- The three values of choice are:
-fvect-cost-model=modelโ tweaks the cost model used for vectorization ๐ Themodelargument should be one ofunlimited,dynamic,cheap, orvery-cheap:unlimitedโ the vectorized code path is assumed to be profitable ๐ชdynamicโ a runtime check guards the vectorized code path, so it only gets enabled for iteration counts that will likely run faster than the original scalar loop ๐โโ๏ธcheapโ disables vectorization of loops where doing so would be cost prohibitive, for example because of required runtime checks for data dependence or alignment. Otherwise it's equal todynamic๐ชvery-cheapโ disables vectorization of loops whenever any runtime check for data dependence or alignment is required. It also disables vectorization of epilogue loops, but otherwise it's equal tocheap๐ง- The default cost model depends on other optimization flags and is either
dynamicorcheap๐ธ
-fsimd-cost-model=modelโ same vibe, but for loops marked with the OpenMPsimddirective ๐ Themodelargument should be one ofunlimited,dynamic, orcheap. All values ofmodelhave the same meaning as described in-fvect-cost-model, and by default the cost model defined with-fvect-cost-modelis used ๐ซถ-ftree-vrpโ Value Range Propagation on trees ๐ It's similar to the constant propagation pass, but instead of values, ranges of values get propagated ๐ That lets the optimizers remove unnecessary range checks, like array bound checks and null pointer checks ๐๏ธ Enabled by default at-O2and higher ๐ฅ Null pointer check elimination only happens if-fdelete-null-pointer-checksis enabled ๐-fsplit-pathsโ splits paths leading to loop backedges โ๏ธ This can improve dead code elimination and common subexpression elimination ๐งน Enabled by default at-O3and above ๐-fsplit-ivs-in-unrollerโ lets values of induction variables in later iterations of an unrolled loop be expressed using the value from the first iteration ๐ง That breaks long dependency chains, which improves the efficiency of the scheduling passes โก- A combination of
-fweband CSE is often enough to get the same effect ๐ค But that's not reliable when the loop body is more complicated than a single basic block ๐ฌ It also doesn't work at all on some architectures, due to restrictions in the CSE pass ๐ซ - This optimization is enabled by default โจ
- A combination of
-fvariable-expansion-in-unrollerโ when unrolling a loop, the compiler creates multiple copies of some local variables, which can result in superior code ๐ Enabled by default for PowerPC targets, but disabled by default otherwise ๐ฆ-fpartial-inliningโ inlines parts of functions ๐งฉ This option only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functions๐ซถ Enabled at levels-O2,-O3,-Os๐-fpredictive-commoningโ performs predictive commoning, which means reusing computations (especially memory loads and stores) performed in previous loop iterations ๐ Enabled at level-O3, and also by-fprofile-useand-fauto-profile๐-fprefetch-loop-arraysโ if the target machine supports it, generates instructions to prefetch memory, which can improve the performance of loops that access large arrays ๐๏ธ This may generate better or worse code, since results are highly dependent on the structure of loops in the source code ๐คท Disabled at level-Os๐ด-fno-printf-return-valueโ don't substitute constants for the known return values of formatted output functions like"sprintf","snprintf","vsprintf", and"vsnprintf"(but not"printf"or"fprintf") ๐ โโ๏ธ This lets GCC optimize or even eliminate branches based on the known return value of these functions, when they're called with arguments that are constant, or whose values are known to be in a range that makes the exact return value possible to determine ๐งฎ For example, when-fprintf-return-valueis in effect, both the branch and the body of theifstatement (but not the call tosnprint) can be optimized away wheniis a 32-bit or smaller integer, because the return value is guaranteed to be at most 8 ๐
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations and yields the best results with -O2 and above ๐ It works in tandem with -Wformat-overflow and -Wformat-truncation ๐ค The -fprintf-return-value option is enabled by default โจ
-fno-peephole,-fno-peephole2โ disables any machine-specific peephole optimizations ๐งผ The difference between-fno-peepholeand-fno-peephole2is in how they're implemented in the compiler. Some targets use one, some use the other, and a few use both ๐ค-fpeepholeis enabled by default ๐-fpeephole2is enabled at levels-O2,-O3,-Os๐ธ
-fno-guess-branch-probabilityโ don't guess branch probabilities using heuristics ๐ GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (-fprofile-arcs) ๐ฎ These heuristics are based on the control flow graph ๐บ๏ธ If some branch probabilities are specified by__builtin_expect, the heuristics are used to guess the rest of the control flow graph, taking the__builtin_expectinfo into account ๐ง The interactions between the heuristics and__builtin_expectcan get complex, so in some cases it's useful to disable the heuristics, making the effects of__builtin_expecteasier to understand ๐ซ- It's also possible to specify the expected probability of an expression with the
__builtin_expect_with_probabilitybuilt-in function ๐ฏ - The default is
-fguess-branch-probabilityat levels-O,-O2,-O3,-Os๐
- It's also possible to specify the expected probability of an expression with the
-freorder-blocksโ reorders basic blocks in the compiled function to reduce the number of taken branches and improve code locality ๐ฆ
Okay so this one is enabled at -O1, -O2, -O3, and -Os ๐
โจ
-freorder-blocks-algorithm=algorithm ๐ฆ
Tells the compiler which algorithm to use when it shuffles basic blocks around. You can pick simple, which doesn't bloat your code size (though sometimes alignment side effects can nudge it a bit ๐), or stc, the "software trace cache" algorithm. stc groups all the frequently run code together so fewer branches get executed, but it does it by making extra copies of code, so it's giving bigger binary energy ๐
The default is simple at -O1 and -Os, and stc at -O2 and -O3.
-freorder-blocks-and-partition ๐ธ
On top of reordering basic blocks inside each compiled function (to cut down on taken branches), this one splits hot and cold blocks into separate sections in the assembly and .o files. The result is better paging and cache locality, which is a whole vibe ๐ง
This optimization gets turned off automatically in a few situations: when exception handling or unwind tables are present (on targets using setjump/longjump or a target-specific scheme), for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections. If you're using -fsplit-stack, it's not enabled by default (to avoid linker errors), but you can turn it on explicitly if your linker actually works ๐
Enabled for x86 at -O2, -O3, and -Os.
-freorder-functions ๐
Reorders functions in the object file to improve code locality. Unlike -fipa-reorder-for-locality, this one prioritizes grouping every function in a category (hot, normal, cold, or never-executed) together. It does this with special subsections: .text.hot for the most frequently executed functions and .text.unlikely for the ones that are unlikely to run. The linker does the actual reordering, so your object file format needs to support named sections, and the linker has to place them sensibly โจ
This option doesn't do anything unless you either provide profile feedback (see -fprofile-arcs for details) or manually annotate functions with hot or cold attributes. No profile, no annotations, no glow-up ๐ฅ
Enabled at levels -O2, -O3, and -Os.
-fstrict-aliasing ๐
This lets the compiler assume the strictest aliasing rules that apply to the language being compiled. For C (and C++), that turns on optimizations based on the type of expressions. Specifically, accessing an object of one type through an expression of a different type is not allowed, unless the types are compatible, differ only in signedness or qualifiers, or the expression has a character type. Accessing scalar objects through a corresponding vector type is also allowed.
For example, an unsigned int can alias an int, but not a void* or a double. A character type may alias any other type.
Pay special attention to code like this:
union a_union {
int i;
double d;
};
int f() {
union a_union t;
t.d = 3.0;
return t.i;
}
Reading from a different union member than the one you most recently wrote to (called "type-punning") is super common. Even with -fstrict-aliasing, type-punning is allowed in C, as long as the memory is accessed through the union type. In ISO C++, type-punning through a union type is undefined behavior, but GCC supports it as an extension, so the code above works as expected. However, this code might not:
int f() {
union a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Same energy goes for accessing something by taking its address, casting the resulting pointer, and dereferencing it. That has undefined behavior, even if the cast uses a union type, for example:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
โ ๏ธ Heads up bestie: all of the above is undefined behavior territory in some cases, so be careful with your pointers ๐ญ
The -fstrict-aliasing option is enabled at levels -O2, -O3, and -Os.
-fipa-strict-aliasing ๐ฅ
Controls whether the rules of -fstrict-aliasing get applied across function boundaries. Fun fact: if multiple functions get inlined into a single function, the memory accesses are no longer considered to be crossing a function boundary ๐ง
The -fipa-strict-aliasing option is enabled by default, but it only does anything in combination with -fstrict-aliasing.
-falign-functions ๐
Aligns the start of functions to the next power-of-two greater than or equal to n, skipping up to m-1 bytes. This makes sure that at least the first m bytes of the function can be fetched by the CPU without crossing an n-byte alignment boundary. It's a code performance optimization, and alignment is ignored for functions considered cold. If you need alignment for every single function, use -fmin-function-alignment instead ๐ซถ
The forms you can use are:
-falign-functions
-falign-functions=n
-falign-functions=n:m
-falign-functions=n:m:n2
-falign-functions=n:m:n2:m2
If m isn't specified, it defaults to n.
Examples: -falign-functions=32 aligns functions to the next 32-byte boundary. -falign-functions=24 aligns to the next 32-byte boundary only if that can be done by skipping 23 bytes or less. -falign-functions=32:7 aligns to the next 32-byte boundary only if that can be done by skipping 6 bytes or less.
The second pair, n2:m2, lets you set a secondary alignment. -falign-functions=64:7:32:3 aligns to the next 64-byte boundary if that can be done by skipping 6 bytes or less, and otherwise aligns to the next 32-byte boundary if that can be done by skipping 2 bytes or less. If m2 isn't specified, it defaults to n2 ๐
Some assemblers only support this flag when n is a power of two. In that case, the value gets rounded up.
-fno-align-functions and -falign-functions=1 are equivalent, and both mean that functions are not aligned.
If n isn't specified or is zero, the compiler uses a machine-dependent default. The maximum allowed n value is 65536.
Enabled at levels -O2 and -O3.
-flimit-function-alignment ๐ฆ
When this is enabled, the compiler tries not to overalign functions for no reason. It asks the assembler to align by the amount specified by -falign-functions, but it won't skip more bytes than the size of the function itself ๐
โโ๏ธ
-falign-labels ๐
Aligns all branch targets to a power-of-two boundary.
The parameters for this option work the same way as they do for -falign-functions. -fno-align-labels and -falign-labels=1 are equivalent and both mean labels are not aligned.
The forms you can use are:
-falign-labels
-falign-labels=n
-falign-labels=n:m
-falign-labels=n:m:n2
-falign-labels=n:m:n2:m2
If -falign-loops or -falign-jumps apply and are greater than this value, their values are used instead.
If n isn't specified or is zero, the compiler uses a machine-dependent default, which is very likely to be 1, meaning no alignment. The maximum allowed n value is 65536.
Enabled at levels -O2 and -O3.
-falign-loops ๐
Aligns loops to a power-of-two boundary. If the loops run many times, this makes up for the cost of the dummy padding instructions. It's a code performance optimization, and alignment is ignored for loops considered cold.
If -falign-labels is greater than this value, its value is used instead.
The parameters work like -falign-functions. -fno-align-loops and -falign-loops=1 are equivalent and both mean loops are not aligned. The maximum allowed n value is 65536.
The forms you can use are:
-falign-loops
-falign-loops=n
-falign-loops=n:m
-falign-loops=n:m:n2
-falign-loops=n:m:n2:m2
If n isn't specified or is zero, the compiler uses a machine-dependent default.
Enabled at levels -O2 and -O3.
-falign-jumps ๐ง
Aligns branch targets to a power-of-two boundary, but only for branch targets that can only be reached by jumping. In that case no dummy operations need to run. It's a code performance optimization, and alignment is ignored for jumps considered cold.
If -falign-labels is greater than this value, its value is used instead.
The parameters work like -falign-functions. -fno-align-jumps and -falign-jumps=1 are equivalent and both mean loops are not aligned (yes, the original says loops, it's a lil mix-up ๐). The maximum allowed n value is 65536.
The forms you can use are:
-falign-jumps
-falign-jumps=n
-falign-jumps=n:m
-falign-jumps=n:m:n2
-falign-jumps=n:m:n2:m2
If n isn't specified or is zero, the compiler uses a machine-dependent default.
Enabled at levels -O2 and -O3.
-fmin-function-alignment ๐
Specifies the minimal alignment of functions to the next power-of-two greater than or equal to n. Unlike -falign-functions, this alignment gets applied to all functions, even the ones considered cold. It's also not affected by -flimit-function-alignment ๐
-fno-allocation-dce โจ
Stops the compiler from removing unused C++ allocations (the ones using operator "new" and operator "delete") during dead code elimination. So those allocations stay put ๐ซถ
See also -fmalloc-dce.
-fallow-store-data-races โญ
Lets the compiler do optimizations that might introduce new data races on stores, without proving that the variable can't be accessed by other threads at the same time. It doesn't affect optimization of local data. It's safe to use this if you know global data won't be accessed by multiple threads ๐งต
Examples of optimizations this enables include hoisting, or if-conversions that might cause a value already in memory to be rewritten with that same value. That rewrite is safe in a single-threaded context but can be unsafe in a multi-threaded one. Also, on some processors, if-conversions may be required before vectorization can happen.
โ ๏ธ Only use this if global data is single-threaded, otherwise you're playing with fire ๐ฅ
Enabled at level -Ofast.
-funit-at-a-time ๐ธ
This one is only here for compatibility reasons. -funit-at-a-time has no effect, but -fno-unit-at-a-time implies -fno-toplevel-reorder and -fno-section-anchors ๐
Enabled by default.
-fno-toplevel-reorder ๐
Stops the compiler from reordering top-level functions, variables, and asm statements. It outputs them in the same order they appear in the input file. When this is used, unreferenced static variables are not removed. This option exists to support existing code that relies on a specific ordering. For new code, it's better to use attributes whenever you can ๐
-ftoplevel-reorder is the default at -O1 and higher ๐
, and at -O0 too if you explicitly ask for -fsection-anchors ๐ฆ. Also, -fno-toplevel-reorder implies -fno-section-anchors ๐.
-funreachable-trapsโ okay so this one is a whole vibe ๐. With it on, the compiler turns calls to__builtin_unreachableinto traps instead of using them for optimization. It also hits any of those calls the compiler generates on its own ๐ง.
This is the same as -fsanitize=unreachable -fsanitize-trap=unreachable, but it doesn't change the values of those options ๐ซถ. If -fsanitize=unreachable is enabled, that one takes priority over this one ๐. It's enabled by default at -O0 and -Og โจ.
-fwebโ this builds webs for register allocation and gives each web its own pseudo register ๐ง . That lets the register allocation pass work on pseudos directly and also boosts CSE, the loop optimizer, and the trivial dead code remover ๐ฅ. The catch? It can make debugging impossible, since variables no longer stay in a "home register" ๐ญ. It's enabled by default with-funroll-loops.-fwhole-programโ you're basically telling the compiler "this compilation unit is the whole program" ๐. All public functions and variables become static, exceptmainand anything merged by attributeexternally_visible, so the interprocedural optimizers can go hard ๐.
With -flto, this one has limited use ๐ฅบ. Usually the linker plugin already knows the precise list of symbols used or exported from the binary, from the resolution info the linker passes to the link-time optimizer. It's still useful if no linker plugin is used, or during the incremental link step when final code is produced (with -flto -flinker-output=nolto-rel).
-flto[=n]
Okay, the link-time optimizer is literally so iconic ๐ฆ. This option runs the standard link-time optimizer. When you invoke it with source code, it generates GIMPLE (one of GCC's internal representations) and writes it to special ELF sections in the object file ๐ธ. When the object files get linked together, all the function bodies are read back from those ELF sections and instantiated as if they had been part of the same translation unit โจ.
To use it, -flto and optimization options should be specified at compile time and during the final link ๐. It's recommended that you compile all the files in the same link with the same options, and specify those options at link time too. For example:
gcc -c -O2 -flto foo.c
gcc -c -O2 -flto bar.c
gcc -o myprog -flto -O2 foo.o bar.o
The first two invocations save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o ๐พ. The final invocation reads that GIMPLE bytecode from foo.o and bar.o, merges the two files into a single internal image, and compiles the result as usual ๐ซถ. Since both get merged into one image, all the interprocedural analyses and optimizations in GCC work across the two files as if they were a single one. So, for example, the inliner can inline functions in bar.o into functions in foo.o and vice-versa ๐ญ.
Another (simpler) way to enable link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
That generates bytecode for foo.c and bar.c, merges them into a single GIMPLE representation, and optimizes them as usual to produce myprog ๐.
The important thing to keep in mind is that you need to use the GCC driver to perform the link step ๐. GCC automatically performs link-time optimization if any of the objects involved were compiled with the -flto command-line option. You can always override that automatic decision by passing -fno-lto to the link command ๐.
To make whole-program optimization effective, you have to make certain assumptions ๐ง. The compiler needs to know which functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes that information about used and externally visible symbols to the compiler. When the linker plugin isn't available, use -fwhole-program so the compiler can make those assumptions, which leads to more aggressive optimization decisions ๐
.
When a file is compiled with -flto without -fuse-linker-plugin, the generated object file is bigger than a regular one ๐ฆ. That's because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). So object files with LTO information can still be linked as normal object files. If -fno-lto is passed to the linker, though, no interprocedural optimizations get applied ๐ญ. Note that when -fno-fat-lto-objects is enabled, the compile stage is faster, but you cannot perform a regular, non-LTO link on them โ ๏ธ.
When producing the final binary, GCC only applies link-time optimizations to files that contain bytecode ๐ง. So you can mix and match object files and libraries with GIMPLE bytecodes and final object code. GCC automatically picks which files to optimize in LTO mode and which to link without further processing โจ.
Generally, options specified at link time override those specified at compile time ๐. In some cases, though, GCC attempts to infer link-time options from the settings used to compile the input files ๐.
If you don't specify an optimization level option -O at link time, GCC uses the highest optimization level used when compiling the object files ๐. Note that it's generally ineffective to specify an optimization level option only at link time and not at compile time, for two reasons ๐
โโ๏ธ. First, compiling without optimization suppresses the compiler passes that gather information needed for effective optimization at link time. Second, some early optimization passes can only be performed at compile time and not at link time.
There are some code generation flags GCC preserves when generating bytecodes, since they need to be used during the final link ๐. Currently, the following options and their settings are taken from the first object file that explicitly specifies them: -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm and all the -m target flags ๐ฆ.
The options -fPIC, -fpic, -fpie and -fPIE get combined based on this scheme ๐ธ:
-fPIC + -fpic = -fpic
-fPIC + -fno-pic = -fno-pic
-fpic/-fPIC + (no option) = (no option)
-fPIC + -fPIE = -fPIE
-fpic + -fPIE = -fpie
-fPIC/-fpic + -fpie = -fpie
Certain ABI-changing flags have to match in all compilation units ๐ซ. Trying to override them at link time with a conflicting value gets ignored. This includes options such as -freg-struct-return and -fpcc-struct-return ๐ค.
Other options, such as -ffp-contract, -fno-strict-overflow, -fwrapv, -fno-trapv or -fno-strict-aliasing, get passed through to the link stage and merged conservatively for conflicting translation units ๐ค. Specifically, -fno-strict-overflow, -fwrapv and -fno-trapv take precedence, and for example -ffp-contract=off takes precedence over -ffp-contract=fast ๐. You can override them at link time ๐
.
Diagnostic options such as -Wstringop-overflow get passed through to the link stage too, and their setting matches that of the compile step at function granularity ๐. This only matters for diagnostics emitted during optimization. Also, code transforms such as inlining can lead to warnings being enabled or disabled for regions of code that aren't consistent with the setting at compile time ๐.
When you need to pass options to the assembler via -Wa or -Xassembler, make sure to either compile such translation units with -fno-lto, or consistently use the same assembler options on all translation units ๐งต. You can also specify assembler options at LTO link time instead ๐.
To enable debug info generation, you need to supply -g at compile time ๐. If any of the input files at link time were built with debug info generation enabled, the link enables debug info generation as well. Any elaborate debug info settings, like the DWARF level -gdwarf-5, need to be explicitly repeated on the linker command line, and mixing different settings across translation units is discouraged ๐ฌ.
If LTO encounters objects with C linkage declared with incompatible types in separate translation units being linked together, a non-fatal diagnostic may be issued ๐จ. That's undefined behavior according to ISO C99 6.2.7, and the behavior is still undefined at run time ๐. Similar diagnostics may be raised for other languages too.
Another feature of LTO is that you can apply interprocedural optimizations to files written in different languages ๐:
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice that the final link is done with g++ to get the C++ runtime libraries, and -lgfortran is added to get the Fortran runtime libraries ๐งโโ๏ธ. In general, when mixing languages in LTO mode, you should use the same link command options as when mixing languages in a regular (non-LTO) compilation.
If object files containing GIMPLE bytecode are stored in a library archive, say libfoo.a, you can extract and use them in an LTO link, as long as you're using a linker with plugin support ๐. To create static libraries suitable for LTO, use gcc-ar and gcc-ranlib instead of ar and ranlib. To show the symbols of object files with GIMPLE bytecode, use gcc-nm. Those commands require that ar, ranlib and nm have been compiled with plugin support ๐. At link time, use the flag -fuse-linker-plugin to make sure the library participates in the LTO optimization process:
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin enabled, the linker extracts the needed GIMPLE files from libfoo.a and passes them on to the running GCC, so they become part of the aggregated GIMPLE image to be optimized ๐.
Okay so if you're NOT using a linker with plugin support and/or you don't turn the linker plugin on ๐
, the objects inside libfoo.a still get extracted and linked like normal, but they just sit out the LTO optimization process ๐ญ. If you want a static library that works for BOTH LTO optimization and regular linking, compile its object files with -flto -ffat-lto-objects ๐.
Link-time optimizations don't need the whole program to be present to work ๐ฆ. If the program doesn't need any symbols exported, you can combine -flto and -fwhole-program so the interprocedural optimizers can make more aggressive assumptions, which may open up better optimization opportunities โจ. You don't need -fwhole-program when the linker plugin is active (see -fuse-linker-plugin).
The current LTO implementation makes no attempt to generate bytecode that's portable between different types of hosts ๐. The bytecode files are versioned with a strict version check, so bytecode from one version of GCC won't work with an older or newer GCC. Not it ๐.
Link-time optimization doesn't work well with generating debugging information on systems other than the ones using a combination of ELF and DWARF ๐ญ.
If you specify the optional n, the link-time optimization and code generation run in parallel using n jobs by utilizing an installed make program ๐ฅ. The environment variable MAKE can be used to override which program gets used.
You can also use -flto=jobserver to tap into GNU make's job server mode and let it decide how many parallel jobs to run ๐. This is super useful when the Makefile calling GCC is already running in parallel. You must prepend a + to the command recipe in the parent Makefile for this to work. This option likely only works if MAKE is GNU make. Even without the option value, GCC tries to automatically detect a running GNU make's job server ๐ซถ.
Use -flto=auto to use GNU make's job server if it's available, or otherwise fall back to autodetecting the number of CPU threads in your system โญ.
-flto-partition=alg ๐งฉ
Okay this one picks the partitioning algorithm the link-time optimizer uses ๐. The value is one of:
1to1, which mirrors the partitioning of the original source filesbalanced, which splits things into equally sized chunks (whenever possible)max, which creates a new partition for every symbol where possiblecache, which balances chunk sizes while keeping related symbols together for better caching in incremental LTO
Specifying none as the algorithm disables partitioning and streaming completely ๐
. The default is balanced. 1to1 can be used as a workaround for various code ordering issues, but max partitioning is intended for internal testing only ๐งช. The value one specifies that exactly one partition should be used, while none bypasses partitioning and runs the link-time optimization step directly from the WPA phase ๐ฆ.
-flto-incremental=path โก
Enables incremental LTO, with its cache living in the given existing directory. It can seriously shorten your edit-compile cycles with LTO ๐ธ.
When you use LTO (-flto), the output of translation units inside LTO gets cached ๐. Cached translation units are likely to be hit again when you recompile after small code changes, which means faster recompile times โจ.
Multiple GCC instances can share the same cache in parallel ๐ซถ.
-flto-incremental-cache-size=n ๐๏ธ
Specifies the number of cache entries in incremental LTO after which old entries get pruned. This is a soft limit, so there may temporarily be more entries than that ๐คทโโ๏ธ.
-flto-compression-level=n ๐๏ธ
This sets the compression level for the intermediate language written to LTO object files ๐
. It only matters together with LTO mode (-flto). GCC currently supports two LTO compression algorithms. For zstd, valid values are 0 (no compression) to 19 (maximum compression), while zlib supports values from 0 to 9. Values outside this range get clamped to the minimum or maximum of the supported values ๐. If you don't give the option, a default balanced compression setting is used ๐.
-flto-toplevel-asm-heuristics ๐
This enables heuristics that find symbols used in top-level basic asm ๐ต๏ธโโ๏ธ. It restricts the link-time optimizations that could rename or delete those symbols, which would otherwise cause missing symbol errors from the linker ๐ซ.
This flag is meant for projects that haven't switched to top-level extended asm, which specifies the usage directly without any false positives ๐.
The heuristics are simple and don't parse the assembly. They scan through top-level assembly for all possible identifiers. If an identifier matches one of the declared symbols, that symbol gets marked to restrict link-time optimizations. Static symbols disable more optimizations. Identifiers followed by ':' also disable more optimizations, because they might be a locally defined symbol in the assembly, even when the declaration is marked extern ๐.
-fuse-linker-plugin ๐
Enables the use of a linker plugin during link-time optimization ๐. This relies on plugin support in the linker, which is available in gold or in GNU ld 2.21 or newer.
This option lets object files with GIMPLE bytecode get extracted out of library archives. That improves optimization quality by exposing more code to the link-time optimizer ๐ฅ. It also tells the optimizer which symbols can be accessed externally (by a non-LTO object or during dynamic linking). The resulting code quality improvements on binaries (and on shared libraries that use hidden visibility) are similar to -fwhole-program ๐. See -flto for a description of the effect of this flag and how to use it.
This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker that supports plugins (GNU ld 2.21 or newer, or gold) ๐ซถ.
-ffat-lto-objects ๐ฑ
Fat LTO objects are object files that contain both the intermediate language and the object code ๐ฅฐ. That makes them usable for both LTO linking and normal linking. This option only works when you're compiling with -flto, and it's ignored at link time.
-fno-fat-lto-objects improves compilation time over plain LTO, but it requires the complete toolchain to be aware of LTO ๐ค. It needs a linker with linker plugin support for basic functionality. On top of that, nm, ar and ranlib need to support linker plugins to allow a full-featured build environment (one that can build static libraries and so on). GCC provides the gcc-ar, gcc-nm and gcc-ranlib wrappers to pass the right options to these tools. With non-fat LTO, makefiles need to be modified to use them ๐.
Modern binutils come with a plugin auto-load mechanism ๐คฉ. Installing the linker plugin into $libdir/bfd-plugins has the same effect as using the command wrappers (gcc-ar, gcc-nm and gcc-ranlib).
The default is -fno-fat-lto-objects on targets with linker plugin support ๐.
-fcompare-elim โ๏ธ
After register allocation and post-register allocation instruction splitting, this identifies arithmetic instructions that compute processor flags similar to a comparison operation based on that arithmetic ๐งฎ. If possible, it eliminates the explicit comparison operation โ๏ธ.
This pass only applies to certain targets that can't explicitly represent the comparison operation before register allocation is complete ๐ฏ.
Enabled at levels -O1, -O2, -O3, -Os โญ.
-ffold-mem-offsets / -fno-fold-mem-offsets ๐ง
Tries to eliminate add instructions by folding them into memory loads and stores ๐ช.
Enabled at levels -O2, -O3 โจ.
NOTE: On Debian/Ubuntu this is disabled by default on m68k-linux-gnu ๐.
-fcprop-registers ๐งท
After register allocation and post-register allocation instruction splitting, this runs a copy-propagation pass to try to reduce scheduling dependencies and occasionally eliminate the copy ๐ท.
Enabled at levels -O1, -O2, -O3, -Os ๐
.
-fprofile-correction ๐ฉน
Profiles collected using an instrumented binary for multi-threaded programs can be inconsistent because of missed counter updates ๐งต. When you specify this option, GCC uses heuristics to correct or smooth out those inconsistencies. By default, GCC emits an error message when it detects an inconsistent profile ๐จ.
This option is enabled by -fauto-profile ๐ซถ.
-fprofile-partial-training ๐
With -fprofile-use, all portions of programs not executed during training runs get optimized aggressively for size rather than speed ๐. Sometimes it isn't practical to train every possible hot path in the program. For example, it may contain functions specific to certain hardware, and training may not cover every hardware configuration the program will later run on ๐ฅ๏ธ.
With -fprofile-partial-training, profile feedback is ignored for all functions not executed during the training runs. Those functions get optimized as if they were compiled without profile feedback. This leads to better performance when the training isn't representative, at the cost of significantly bigger code ๐ฆ.
-fprofile-use / -fprofile-use=path ๐
Enables profile feedback-directed optimizations, plus the following optimizations, many of which are generally only profitable when profile feedback is available ๐:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Before you can use this option, you have to generate profiling information first ๐.
By default, GCC emits an error message if the feedback profiles don't match the source code ๐ฌ. You can turn that error into a warning with -Wno-error=coverage-mismatch. Just know this may result in poorly optimized code ๐. Also by default, GCC emits a warning message if the feedback profiles don't exist (see -Wmissing-profile) ๐.
If you give a path, GCC looks there to find the profile feedback data files. See -fprofile-dir ๐บ๏ธ.
-fauto-profile,-fauto-profile=pathโ okay bestie, this one switches on sampling-based feedback-directed optimizations ๐ฅ and a whole squad of other optimizations that are mostly worth it when profile feedback is available ๐ :-fbranch-probabilities,-fprofile-values,-funroll-loops,-fpeel-loops,-ftracer,-fvpt,-finline-functions,-fipa-cp,-fipa-cp-clone,-fipa-bit-cp,-fpredictive-commoning,-fsplit-loops,-funswitch-loops,-fgcse-after-reload,-ftree-loop-vectorize,-ftree-slp-vectorize,-fvect-cost-model=dynamic,-ftree-loop-distribute-patterns,-fprofile-correction- path is the name of the file that holds your AutoFDO profile info ๐ง. If you leave it out, it defaults to
fbdata.afdoin the current directory. - Making an AutoFDO profile data file means running your program with the perf utility on a supported GNU/Linux target system. For the full tea, check out
https://perfwiki.github.io/main/๐ธ
E.g.
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Then you use the create_gcov tool to turn the raw profile data into something GCC can actually read ๐ซถ. You also have to hand this tool the unstripped binary for your program. See https://github.com/google/autofdo for more.
E.g.
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
-fauto-profile-inliningโ when auto-profile is available, this inlines all the relevant functions that got inlined during the training run before the profile feedback gets read. It makes the context sensitivity of the profile way better โจ. Enabled by default.
The following options control compiler behavior regarding floating-point arithmetic. These options trade speed for correctness ๐งฎ, so every single one of them must be specifically enabled. No sneaky auto-magic here, bestie ๐ โโ๏ธ.
-fexcess-precision=styleโ okay so this one lets you control excess precision on machines where floating-point ops happen in a format with more precision or range than the IEEE standard and interchange floating-point types. The classic example is x87 floating point on x86 processors, which uses an 80-bit representation internally instead of the 64-bit IEEE format. For most programs the extra precision is harmless ๐, but some programs rely on the C or C++ standards' rules for handling IEEE values, so they can get messy.- By default,
-fexcess-precision=fastis in effect. That means ops may run in a wider precision than the source types if it makes the code faster, and it's unpredictable when rounding to the source types actually happens ๐. - When compiling C or C++, if you use
-fexcess-precision=standard, the excess precision follows the rules in ISO C99 or C++. Casts and assignments both round values to their semantic types (whereas-ffloat-storeonly affects assignments). - This is enabled by default for C or C++ if a strict conformance option like
-std=c99or-std=c++17is used. -ffast-mathenables-fexcess-precision=fastby default, regardless of whether a strict conformance option is used.- If you specify
-fexcess-precision=16, constants and the results of expressions with types_Float16and__bf16are computed without excess precision. -fexcess-precision=standardis not implemented for languages other than C or C++. On x86 it has no effect if-mfpmath=sseor-mfpmath=sse+387is specified. With the former, IEEE semantics apply without excess precision. With the latter, rounding is unpredictable.
- By default,
-ffloat-storeโ do not store floating-point variables in registers, and block other options that might change whether a floating-point value is pulled from a register or from memory ๐ โโ๏ธ. This has mostly been subsumed by-fexcess-precision=standard, which is more general. If you do use-ffloat-store, you might need to tweak your program to explicitly store intermediate computations in temporary variables, since-ffloat-storeonly handles rounding to IEEE format on assignments and not on casts like-fexcess-precision=standarddoes.-ffast-mathโ sets-fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans,-fcx-limited-rangeand-fexcess-precision=fastall at once ๐๏ธ.- This option causes the preprocessor macro
__FAST_MATH__to be defined. - It is not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications.
- This option causes the preprocessor macro
-fno-math-errnoโ do not seterrnoafter calling math functions that run with a single instruction, likesqrt. A program that relies on IEEE exceptions for math error handling might want this flag for speed while still keeping IEEE arithmetic compatibility ๐ฆ.- It is not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications.
- The default is
-fmath-errno. - On Darwin systems, the math library never sets
errno. So there's no reason for the compiler to consider that it might, and-fno-math-errnois the default there ๐.
-funsafe-math-optimizationsโ allows optimizations for floating-point arithmetic that (a) assume arguments and results are valid and (b) may violate IEEE or ANSI standards. When used at link time, it may pull in libraries or startup files that change the default FPU control word or do other similar optimizations ๐.- It is not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications.
- This enables
-fno-signed-zeros,-fno-trapping-math,-fassociative-mathand-freciprocal-math. - The default is
-fno-unsafe-math-optimizations.
-fassociative-mathโ allows re-association of operands in series of floating-point operations. This violates the ISO C and C++ language standards by possibly changing the computation result ๐ฌ.- > NOTE: re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. So it can't be used on code that relies on rounding behavior like
(x + 2**52) - 2**52. It may also reorder floating-point comparisons, so it may not be used when ordered comparisons are required. - This option requires that both
-fno-signed-zerosand-fno-trapping-mathbe in effect. Moreover, it doesn't make much sense with-frounding-math. For Fortran, the option is automatically enabled when both-fno-signed-zerosand-fno-trapping-mathare in effect. - The default is
-fno-associative-math.
- > NOTE: re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. So it can't be used on code that relies on rounding behavior like
-freciprocal-mathโ allows the reciprocal of a value to be used instead of dividing by the value, if that enables optimizations. For example,x / ycan be replaced withx * (1/y), which is handy if(1/y)is subject to common subexpression elimination. Heads up though: this loses precision and increases the number of flops operating on the value ๐ค.- The default is
-fno-reciprocal-math.
- The default is
-ffinite-math-onlyโ allows optimizations for floating-point arithmetic that assume arguments and results are not NaNs or+-Infs๐.- It is not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications.
- The default is
-fno-finite-math-only.
-fno-signed-zerosโ allows optimizations for floating-point arithmetic that ignore the sign of zero. IEEE arithmetic specifies how distinct+0.0and-0.0values behave, and that stops you from simplifying expressions likex+0.0or0.0*x(even with-ffinite-math-only). This option basically says the sign of a zero result isn't significant ๐.- The default is
-fsigned-zeros.
- The default is
-fno-trapping-mathโ compiles code assuming floating-point operations can't generate user-visible traps. Those traps include division by zero, overflow, underflow, inexact result and invalid operation ๐. This option requires that-fno-signaling-nansbe in effect. Turning it on may allow faster code if you rely on "non-stop" IEEE arithmetic, for example.- It is not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
- The default is
-ftrapping-math. - Future versions of GCC may give finer control of this setting using C99's
FENV_ACCESSpragma. This command-line option will be used along with-frounding-mathto specify the default state forFENV_ACCESS๐.
-frounding-mathโ disables transformations and optimizations that assume the default floating-point rounding behavior (round-to-nearest). You should specify this for programs that change the FP rounding mode dynamically, or that might run with a non-default rounding mode ๐ธ. It also disables constant folding of floating-point expressions at compile time (which can be affected by rounding mode), and arithmetic transformations that are unsafe when sign-dependent rounding modes are involved.- The default is
-fno-rounding-math. - > This option is experimental, and it doesn't currently guarantee that all GCC optimizations affected by rounding mode get disabled. Future versions of GCC may give finer control of this setting using C99's
FENV_ACCESSpragma. This command-line option will be used along with-ftrapping-mathto specify the default state forFENV_ACCESSโ ๏ธ.
- The default is
-fsignaling-nansโ ๐ Tells GCC to compile your code assuming IEEE signaling NaNs can throw user-visible traps during floating-point operations. Turning it on disables optimizations that might change how many exceptions show up with signaling NaNs, and it implies-ftrapping-math. โจ- ๐ It defines the preprocessor macro
__SUPPORT_SNAN__. - ๐ธ The default is
-fno-signaling-nans.
- ๐ It defines the preprocessor macro
๐จ bestie, this one is experimental. It does not currently guarantee that GCC disables all optimizations that affect signaling NaN behavior. ๐
-fsingle-precision-constantโ ๐ฆ Floating-point constants get treated as single precision, instead of being quietly upgraded to double-precision constants.-fcx-limited-rangeโ ๐ When this is on, GCC says a range reduction step isn't needed for complex division. It also skips checking whether a complex multiplication or division result is "NaN + I*NaN" and trying to rescue it. โจ-ffast-mathturns it on.- ๐ It controls the default setting of the ISO C99 "CX_LIMITED_RANGE" pragma, but it applies to all languages, not just C.
-fcx-fortran-rulesโ ๐ง Complex multiplication and division follow Fortran rules. Range reduction happens as part of complex division, but there's no checking for "NaN + I*NaN" results and no rescue attempt in that case. ๐-fcx-method=methodโ ๐ Complex multiplication and division follow the method you name. Themethodvalue should be one oflimited-range,fortranorstdc.- ๐ธ By default, GCC honors language-specific constraints, so it uses
fortranfor Fortran andstdcotherwise.
- ๐ธ By default, GCC honors language-specific constraints, so it uses
The following options control optimizations that may improve performance, but none of them are enabled by any -O options. โจ This section also includes experimental options that may produce broken code, so ๐ be careful with these.
-fbranch-probabilitiesโ ๐ฅ After you run a program compiled with-fprofile-arcs, you can compile it a second time with-fbranch-probabilitiesto improve optimizations based on how many times each branch was taken. ๐- ๐ When a program compiled with
-fprofile-arcsexits, it saves arc execution counts to a file calledsourcename.gcdafor each source file. That data is super dependent on the structure of the generated code, so you must use the same source code and the same optimization options for both compilations. See details about the file naming in-fprofile-arcs. - ๐ง With
-fbranch-probabilities, GCC puts aREG_BR_PROBnote on eachJUMP_INSNandCALL_INSN. Right now, those notes are only used in one place: inreorg.cc. Instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to figure out exactly which path is taken more often. ๐ฏ - ๐ Enabled by
-fprofile-useand-fauto-profile.
- ๐ When a program compiled with
-fprofile-valuesโ ๐ซถ If you combine it with-fprofile-arcs, it adds code that gathers some data about the values of expressions in your program.- ๐ฆ With
-fbranch-probabilities, it reads back the data gathered from profiling values of expressions and uses it in optimizations. - ๐ธ Enabled by
-fprofile-generate,-fprofile-use, and-fauto-profile.
- ๐ฆ With
-fprofile-reorder-functionsโ โญ Function reordering based on profile instrumentation records the first time each function runs, then orders those functions in ascending order. The goal is faster program startup through more efficient loading of text segments. ๐- ๐
Enabled with
-fprofile-use.
- ๐
Enabled with
-fvptโ ๐ง If you combine it with-fprofile-arcs, this option tells the compiler to add code that gathers information about values of expressions.- ๐ฅ With
-fbranch-probabilities, it reads that data back and actually performs optimizations based on it. Right now those optimizations include specializing division operations using what it knows about the value of the denominator. ๐ - ๐ธ Enabled with
-fprofile-useand-fauto-profile.
- ๐ฅ With
-frename-registersโ ๐ฆ Tries to avoid false dependencies in scheduled code by using registers left over after register allocation. This helps most on processors with lots of registers. ๐ซ- โ ๏ธ Depending on the debug information format the target uses, this can make debugging impossible, since variables no longer stay in a "home register". ๐
- ๐ Enabled by default with
-funroll-loops.
-fschedule-fusionโ ๐งฉ Runs a target-dependent pass over the instruction stream to group instructions of the same type together. Machines can run them more efficiently when they sit next to each other in the instruction flow. โจ- ๐ Enabled at levels
-O2,-O3,-Os.
- ๐ Enabled at levels
-fdep-fusionโ ๐ Detects macro-op fusible pairs made of single-use instructions and their uses, then puts those pairs together in the instruction stream to boost fusion opportunities in hardware. ๐ฅ- ๐ง This pass runs once before register allocation, and again before register renaming.
- ๐ธ Enabled at levels
-O2,-O3,-Os.
-ftracerโ ๐โโ๏ธ Performs tail duplication to enlarge superblock size. This simplifies the function's control flow, so other optimizations can do a better job. ๐- ๐ Enabled by
-fprofile-useand-fauto-profile.
- ๐ Enabled by
-funroll-loopsโ ๐ Unrolls loops whose number of iterations can be figured out at compile time or when the loop is entered.-funroll-loopsimplies-frerun-cse-after-loop,-fweband-frename-registers. It also turns on complete loop peeling, which fully removes loops with a small constant number of iterations. ๐ง- โ ๏ธ This option makes code bigger, and it may or may not make it run faster. ๐คทโโ๏ธ
- ๐ธ Enabled by
-fprofile-useand-fauto-profile.
-funroll-all-loopsโ ๐ Unrolls all loops, even if their number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly, so ๐ use with care.-funroll-all-loopsimplies the same options as-funroll-loops.-fpeel-loopsโ ๐ Peels loops that have enough information to show they don't roll much (from profile feedback or static analysis). It also turns on complete loop peeling, which is complete removal of loops with a small constant number of iterations. ๐งถ- ๐ Enabled by
-O3,-fprofile-use, and-fauto-profile.
- ๐ Enabled by
-fmalloc-dceโ ๐งน Controls whethermalloc(and its variants likecallocorstrdup) can be optimized away, as long as its return value is only used as a parameter of afreecall or compared withNULL. ๐๏ธ- ๐ With
-fmalloc-dce=1, only calls tofreeare allowed. With-fmalloc-dce=2, comparisons with aNULLpointer are also considered safe to remove. - ๐ธ The default is
-fmalloc-dce=2. See also-fallocation-dce.
- ๐ With
-fmove-loop-invariantsโ ๐ Enables the loop invariant motion pass in the RTL loop optimizer. ๐ง- ๐ Enabled at level
-O1and higher, except for-Og.
- ๐ Enabled at level
-fmove-loop-storesโ ๐ Enables the loop store motion pass in the GIMPLE loop optimizer. It moves invariant stores to after the end of the loop, in exchange for carrying the stored value in a register across the iteration. ๐ง- ๐ก For this option to have an effect,
-ftree-loop-imhas to be enabled as well. - ๐ธ Enabled at level
-O1and higher, except for-Og.
- ๐ก For this option to have an effect,
-fsplit-loopsโ โ๏ธ Splits a loop into two if it contains a condition that's always true for one side of the iteration space and false for the other. ๐- ๐ Enabled by
-fprofile-useand-fauto-profile.
- ๐ Enabled by
-funswitch-loopsโ ๐ Moves branches with loop invariant conditions out of the loop, with duplicates of the loop on both branches (modified according to the result of the condition). ๐ซถ- ๐ Enabled by
-fprofile-useand-fauto-profile.
- ๐ Enabled by
-fversion-loops-for-stridesโ ๐ฏ If a loop iterates over an array with a variable stride, GCC creates another version of the loop that assumes the stride is always one. Here's the vibe:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
- ๐ This is especially useful for assumed-shape arrays in Fortran, where (for example) it allows better vectorization by assuming contiguous accesses. ๐
- ๐ธ This flag is enabled by default at
-O3. It's also enabled by-fprofile-useand-fauto-profile.
-ffunction-sections,-fdata-sectionsโ ๐ง Puts each function or data item into its own section in the output file, if the target supports arbitrary sections. The name of the function or data item decides the section's name in the output file. ๐ท๏ธ- ๐ Use these on systems where the linker can perform optimizations that improve locality of reference in the instruction space. Most systems using the ELF object format have linkers with those optimizations. On AIX, the linker rearranges sections (CSECTs) based on the call graph. The performance impact varies. ๐คทโโ๏ธ
- ๐ซง Together with linker garbage collection (
linker --gc-sectionsoption), these options may lead to smaller statically-linked executables (after stripping). ๐ฆ - ๐ On ELF/DWARF systems, these options don't degrade the quality of the debug information. There could be issues with other object file or debug info formats. ๐
- โ ๏ธ Only use these options when there are significant benefits from doing so. When you specify them, the assembler and linker create larger object and executable files and are also slower. These options affect code generation. They prevent optimizations by the compiler and assembler that use relative locations inside a translation unit, since those locations are unknown until link time. One example of such an optimization is relaxing calls to short call instructions. ๐ โโ๏ธ
-fstdarg-optโ ๐งฉ Optimizes the prologue of variadic argument functions with respect to how those arguments are used. โจ-fsection-anchorsโ ๐ญ Tries to reduce the number of symbolic address calculations by using shared "anchor" symbols to address nearby objects. On some targets, this can help reduce the number of GOT entries and GOT accesses. ๐ท- ๐ฆ For example, the implementation of the following function "foo":
static int a, b, c;
int foo (void) { return a + b + c; }
Okay so normally GCC works out the addresses of all three variables one by one ๐
, but if you compile with -fsection-anchors, it grabs them all from one common anchor point instead โจ. It's basically like this pseudocode (which isn't valid C, sorry bestie ๐):
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
Heads up ๐ซถ: not all targets support this option.
-fzero-call-used-regs=choiceโ This is giving security vibes ๐. It zeroes out the call-used registers when a function returns, which can help mitigate Return-Oriented Programming (ROP) attacks or stop information from leaking through registers. The possible values ofchoiceare the same as for thezero_call_used_regsattribute, and the default isskip.- You can control this for one specific function with the function attribute
zero_call_used_regs๐.
- You can control this for one specific function with the function attribute
โจ Program Instrumentation Options โจ
GCC has a bunch of command-line options that add run-time instrumentation to the code it normally generates ๐ฅ. Instrumentation can be used to collect profiling stats so you can find program hot spots, do code coverage analysis, or run profile-guided optimizations ๐. Another kind is run-time checking that catches programming errors like invalid pointer dereferences or out-of-bounds array accesses, plus deliberately hostile attacks like stack smashing or C++ vtable hijacking ๐ก๏ธ. There's also a general hook for other forms of tracing or function-level instrumentation for debugging or program analysis ๐ง.
-p,--profile,-fprofile,-pgโ Generates extra code that writes profile information for theprofanalysis program (for-p,--profile, and-fprofile) orgprof(for-pg) ๐. You must use this when compiling the source files you want data about, and you must also use it when linking.- You can slap the function attribute
no_instrument_functionon individual functions to stop them from being profiled when compiling with these options ๐.
- You can slap the function attribute
-fprofile-arcsโ Adds code so program flow arcs are instrumented โจ. While it runs, the program records how many times each branch and call is executed, and how many times it is taken or returns ๐ฆ.- On targets that support constructors with priority support, profiling properly handles constructors, destructors, and C++ constructors (and destructors) of classes that are used as a type of a global variable ๐.
- When the compiled program exits, it saves this data to a file called
auxname.gcdafor each source file ๐พ. The data can be used for profile-directed optimizations (-fbranch-probabilities) or for test coverage analysis (-ftest-coverage). - Each object file's
auxnameis generated from the name of the output file, if one is explicitly specified and it isn't the final executable. Otherwise it's the basename of the source file. In both cases any suffix is removed (e.g.foo.gcdafor input filedir/foo.c, ordir/foo.gcdafor output file specified as-o dir/foo.o) ๐ธ. - > Note ๐: if a command line directly links source files, the corresponding
.gcdafiles get prefixed with the unsuffixed name of the output file. E.g.gcc a.c b.c -o binarywould generatebinary-a.gcdaandbinary-b.gcdafiles.
-fcondition-coverageโ Adds code so program conditions are instrumented ๐ง . During execution the program records which terms in a conditional contribute to a decision. That's how you verify that every term in a Boolean function is tested and has an independent effect on the outcome of a decision ๐ . You can read the result withgcov --conditions.-fpath-coverageโ Adds code so the paths taken get tracked ๐ค๏ธ. During execution the program records the prime paths taken. The number of paths grows very fast with complexity, so to avoid exploding compile times, GCC gives up on instrumentation if the approximate number of paths exceeds the limit controlled by-fpath-coverage-limit๐ญ. You can read the result withgcov --prime-paths --prime-paths-lines --prime-paths-source.- A prime path is the longest sequence of unique blocks, except possibly the first and last, which isn't a subpath of any other path ๐ฆ.
-fpath-coverage-limit=limitโ This is the threshold at which-fpath-coveragegives up on instrumenting a function ๐ซ. The limit is approximate and conservative, because GCC uses a pessimistic heuristic that slightly overcounts the running number of paths. It gives up if the threshold is hit before finding all the paths ๐ . This option is not for fine-grained control over which functions get instrumented. It's really there to limit the effect of path explosion and keep compile times reasonable โฑ๏ธ. The default is250000.--coverage,-coverageโ This one is used to compile and link code instrumented for coverage analysis ๐ฏ.-coverageand--coverageare equivalent, and both are a synonym for-fprofile-arcs -ftest-coverage(when compiling) and-lgcov(when linking). Check the docs for those options for more details.- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, use the additional-ftest-coverageoption. You don't need to profile every source file in a program ๐. - Compile the source files additionally with
-fprofile-abs-pathto create absolute path names in the.gcnofiles. This lets gcov find the correct sources in projects where compilations happen with different working directories ๐บ๏ธ. - Link your object files with
-lgcovor-fprofile-arcs(the latter implies the former) ๐. - Run the program on a representative workload to generate the arc profile information. You can repeat this any number of times. You can run concurrent instances of your program, and as long as the file system supports locking, the data files will be correctly updated ๐. Unless a strict ISO C dialect option is in effect,
forkcalls are detected and correctly handled without double counting ๐ด. - Moreover, an object file can be recompiled multiple times, and the corresponding
.gcdafile merges as long as the source file and the compiler options are unchanged ๐. - For profile-directed optimizations, compile the source files again with the same optimization and code generation options plus
-fbranch-probabilities๐. - For test coverage analysis, use
gcovto produce human readable information from the.gcnoand.gcdafiles. Refer to the gcov documentation for further information ๐. - With
-fprofile-arcs, for each function of your program GCC creates a program flow graph, then finds a spanning tree for the graph ๐ณ. Only arcs that aren't on the spanning tree have to be instrumented: the compiler adds code to count how many times those arcs are executed. When an arc is the only exit or only entrance to a block, the instrumentation code can be added to the block. Otherwise, a new basic block must be created to hold it ๐งฑ. - With
-fcondition-coverage, for each conditional in your program GCC creates a bitset and records the exercised boolean values that have an independent effect on the outcome of that expression ๐ซง. - With
-fpath-coverage, GCC finds, enumerates, and records the taken prime paths of each function, unless the number of paths would exceed the limit controlled by-fpath-coverage-limit. If the limit is exceeded, the function is not instrumented, as if-fpath-coveragewas not used ๐ . A prime path is the longest sequence of unique blocks, except possibly the first and last, which is not a subpath of any other path.
- Compile the source files with
-ftest-coverageโ Produces a notes file that the gcov code-coverage utility can use to show program coverage ๐. Each source file's note file is calledauxname.gcno. Check the-fprofile-arcsoption above for a description ofauxnameand instructions on how to generate test coverage data ๐. Coverage data matches the source files more closely if you do not optimize ๐.-fprofile-abs-pathโ Automatically converts relative source file names to absolute path names in the.gcnofiles ๐๏ธ. This lets gcov find the correct sources in projects where compilations happen with different working directories ๐.-fprofile-dir=pathโ Sets the directory to search for the profile data files topath๐. This only affects the profile data generated by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-useand-fbranch-probabilitiesand its related options. Both absolute and relative paths work. By default GCC uses the current directory aspath, so the profile data file appears in the same directory as the object file. To stop file name clashes, if the object file name isn't an absolute path, GCC mangles the absolute path of thesourcename.gcdafile and uses that as the.gcdafile name. See details about the file naming in-fprofile-arcs. See also the similar option-fprofile-note๐ง.- When an executable runs in a massive parallel environment, it's recommended to save the profile to different folders ๐. You can do that with variables in
paththat get exported at run-time:%pโ process ID.%q{VAR}โ value of environment variableVAR.
- When an executable runs in a massive parallel environment, it's recommended to save the profile to different folders ๐. You can do that with variables in
-fprofile-generate,-fprofile-generate=pathโ Enables options usually used for instrumenting an application to produce a profile that's useful for later recompilation with profile feedback based optimization ๐ฅ. You must use-fprofile-generateboth when compiling and when linking your program โก.- The following options are enabled:
-fprofile-arcs,-fprofile-values,-finline-functions, and-fipa-bit-cp๐ . - If
pathis specified, GCC looks at that path to find the profile feedback data files. See-fprofile-dir๐. - To optimize the program based on the collected profile information, use
-fprofile-use๐.
- The following options are enabled:
-fprofile-info-section,-fprofile-info-section=nameโ okay bestie, this one is so specific ๐ It tells GCC to register the profile info in a section you pick instead of using a constructor/destructor. If you give it aname, that's the section it goes in. Otherwise it defaults to.gcov_infoโจ The pointer to the profile info from-fprofile-arcsgets placed in that section for each translation unit. Heads up: this turns off the constructor registration AND the destructor processing ๐ It's also NOT meant for hosted stuff like GNU/Linux. It's for freestanding environments (think embedded systems) that are low on resources and don't support constructors/destructors or C library file I/O ๐ง
The linker can collect those input sections into one continuous memory block and define start and end symbols for it ๐ฆ Here's a GNU linker script example that defines a linker output section:
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
And the program can dump the profiling info registered in this linker set, like this ๐
#include <gcov.h>
#include <stdio.h>
#include <stdlib.h>
extern const struct gcov_info *const __gcov_info_start[];
extern const struct gcov_info *const __gcov_info_end[];
static void
dump (const void *d, unsigned n, void *arg)
{
const unsigned char *c = d;
for (unsigned i = 0; i < n; ++i)
printf ("%02x", c[i]);
}
static void
filename (const char *f, void *arg)
{
__gcov_filename_to_gcfn (f, dump, arg );
}
static void *
allocate (unsigned length, void *arg)
{
return malloc (length);
}
static void
dump_gcov_info (void)
{
const struct gcov_info *const *info = __gcov_info_start;
const struct gcov_info *const *end = __gcov_info_end;
/* Obfuscate variable to prevent compiler optimizations. */
__asm__ ("" : "+r" (info));
while (info != end)
{
void *arg = NULL;
__gcov_info_to_gcda (*info, filename, dump, allocate, arg);
putchar ('\n');
++info;
}
}
int
main (void)
{
dump_gcov_info ();
return 0;
}
Last but not least, the merge-stream subcommand of gcov-tool can deserialize the data stream made by the __gcov_filename_to_gcfn and __gcov_info_to_gcda functions, then merge that profile info into .gcda files on the host filesystem ๐
-fprofile-note=pathโ if you give it apath, GCC saves the.gcnofile right there ๐ Just know that if you combine this with multiple source files, the.gcnofile gets overwritten ๐-fprofile-prefix-path=pathโ this one pairs withprofile-generate=profile_dirandprofile-use=profile_dirto tell GCC where the base directory of your built source tree is ๐ธ By default,profile_dirholds files with mangled absolute paths of every object file in the build, which is NOT it if the instrumented build and the optimized build happen in different directories, because the profile data won't get found during the optimized build ๐ญ Pointing-fprofile-prefix-path=pathat the base build directory strips the irrelevant part of the path and keeps all file names relative to the main build directory โจ-fprofile-prefix-map=old=newโ when compiling files living in directoryold, GCC records the profiling info (with--coverage) as if those files lived in directorynewinstead ๐บ๏ธ See also-ffile-prefix-mapand-fcanon-prefix-map.-fprofile-update=methodโ this changes how profile feedback instrumented apps update their counters ๐ Themethodshould besingle,atomicorprefer-atomic.singleis great for single-threaded apps, andatomicstops profile corruption by emitting thread-safe code ๐ฅ
Warning: if an app doesn't properly join all its threads (or it creates a detached thread), the profile file can STILL get corrupted ๐
prefer-atomic turns into atomic when the target supports it, or into single otherwise. The GCC driver picks prefer-atomic automatically when -pthread is on the command line; otherwise the default method is single ๐ง
With atomic, the profile info gets updated with atomic operations on a best-effort basis. Ideally those are atomic operations in hardware. If the target can't do the atomic ops in hardware, but libatomic is available, the updates go through calls to libatomic instead ๐ฆ If the target has neither the hardware ops NOR libatomic, the profile info isn't updated atomically and a warning is issued. In that case the profiling info may be corrupt for multi-threaded apps ๐ฌ
For performance reasons: if 64-bit counters are used but the target only supports 32-bit atomic operations in hardware, the performance-critical updates are done with two 32-bit atomic operations for each counter update. If a signal interrupts those two operations while a counter is being updated, the profiling info can end up in an inconsistent state ๐
-fprofile-filter-files=regexโ only instruments functions from files whose names match any of the regular expressions (separated by semicolons) ๐ฏ
For example, -fprofile-filter-files=main\.c;module.*\.c will instrument only main.c and all C files starting with module ๐
-fprofile-exclude-files=regexโ the opposite energy ๐ โโ๏ธ It only instruments functions from files whose names do NOT match any of the regular expressions (separated by semicolons)
For example, -fprofile-exclude-files=/usr/.* will prevent instrumentation of all files located in the /usr/ folder ๐ซ
-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ this controls how reproducible the profile gathered by-fprofile-generateis ๐ It lets you rebuild a program with the same outcome, which is super useful for things like distribution packages ๐ซถ
With -fprofile-reproducible=serial, the gathered profile is reproducible as long as the trained program behaves the same on each invocation of the train run, it isn't multi-threaded, and the profile data gets streamed in the same order every time. Also, profile streaming happens at the end of the program run but ALSO before the fork function is invoked ๐ง
Some parts of programs have execution counts that depend on stuff like the length of temporary file names or memory space randomization (which can affect hash-table collision rates) ๐ That non-reproducible part can be marked with the no_instrument_function function attribute. You can use gcov-dump with -l to dump the gathered data and check that it's actually reproducible ๐
With -fprofile-reproducible=parallel-runs, the collected profile stays reproducible no matter what order the data gets streamed into gcda files in. This setting lets you run multiple instances of the instrumented program in parallel (like with make -j) ๐โโ๏ธ The tradeoff is that the quality of the gathered data goes down, especially for indirect call profiling ๐ญ
-fsanitize=addressโ enables AddressSanitizer, a fast memory error detector ๐ฆ Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs. This option also enables-fsanitize-address-use-after-scope. More details live athttps://github.com/google/sanitizers/wiki/AddressSanitizerโจ You can tweak the run-time behavior with theASAN_OPTIONSenvironment variable. When it's set tohelp=1, the available options are shown when the instrumented program starts up. A list of the supported options is athttps://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags๐
This option CANNOT be combined with-fsanitize=threador-fsanitize=hwaddress๐ โโ๏ธ
Also, -fsanitize=hwaddress is only supported on x86-64 (and only with -mlam=u48 or -mlam=u57) and AArch64, and only in ABIs with 64-bit pointers ๐ง Similarly, -fsanitize=memtag-stack is currently only supported on AArch64 ABIs with 64-bit pointers ๐ธ
When you compile with -fsanitize=address, you should also use -g to get more meaningful output ๐ To get more accurate stack traces, you can use options like -O0, -O1, or -Og (which, for instance, prevent most function inlining). You can also use -fno-optimize-sibling-calls, which prevents optimizing sibling and tail recursive calls. This option is implicit for -O0, -O1, or -Og ๐ Or try -fno-ipa-icf, which disables Identical Code Folding for functions. Using -fno-omit-frame-pointer also improves stack traces ๐ฅ
Multiple runs of the program may give backtraces with different addresses because of ASLR (Address Space Layout Randomization), so it can be smart to turn ASLR off. On Linux you can do that like this ๐ฅน
setarch `uname -m` -R ./prog
-fsanitize=kernel-addressโ enables AddressSanitizer for the Linux kernel ๐ง More details are athttps://github.com/google/kernel-sanitizers๐-fsanitize=hwaddressโ okay bestie, this one is Hardware-assisted AddressSanitizer ๐ โจ It uses a hardware ability to ignore the top byte of a pointer, so it can catch memory errors without piling on a ton of memory overhead ๐ฆ Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs. This option also turns on-fsanitize-address-use-after-scope. For the full tea, peephttps://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html. You can nudge the runtime behavior with theHWASAN_OPTIONSenv var, and if you set it to"help=1", the instrumented program will show you its available options at startup ๐ง Heads up: it cannot be combined with-fsanitize=threador-fsanitize=address, and it's currently only available on AArch64 ๐-fsanitize=kernel-hwaddressโ this one is giving Hardware-assisted AddressSanitizer but for compiling the Linux kernel ๐ง๐ It's similar to-fsanitize=kernel-address, just with a different instrumentation method, and similar to-fsanitize=hwaddressbut with tweaks the kernel needs. Those tweaks exist to avoid hwasan library initialization calls, and to account for the stack pointer having a different value in its top byte ๐
๐ Note: This option has different defaults than-fsanitize=hwaddress. Instrumenting the stack andallocacalls are not on by default. Using a random frame tag is not implemented for kernel instrumentation.
-fsanitize=memtag-stackโ use Memory Tagging Extension instructions instead of instrumentation to catch memory errors ๐ท๏ธ Like HWASAN, it's also a probabilistic method. Only available on those AArch64 architectures that support Memory Tagging Extensions ๐ธ-fsanitize=pointer-compareโ instruments comparison operations (<,<=,>,>=) with pointer operands ๐ It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it cannot be combined with-fsanitize=thread. Note: by default the check is disabled at run time ๐ญ To turn it on, add"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. Using"detect_invalid_pointer_pairs=1"only detects invalid operations when both pointers are non-null ๐ซถ-fsanitize=pointer-subtractโ instruments subtraction with pointer operands ๐งฎ Same rules as the comparison one: it must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it cannot be combined with-fsanitize=thread. Note: by default the check is disabled at run time. To enable it, add"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. Using"detect_invalid_pointer_pairs=1"detects invalid operation only when both pointers are non-null ๐ฅ-fsanitize=shadow-call-stackโ enable ShadowCallStack, a security enhancement mechanism that protects programs against return address overwrites (like stack buffer overflows) ๐ก๏ธ๐ It works by saving a function's return address to a separately allocated shadow call stack in the function prologue, then restoring the return address from that shadow stack in the function epilogue. Instrumentation only happens in functions that need to save the return address to the stack ๐- Currently it only supports the
aarch64platform. It's specifically designed for Linux kernels that enable theCONFIG_SHADOW_CALL_STACKoption ๐ง - For user space programs, runtime support is not currently provided in libc and libgcc, so users who want this in user space need to provide their own support for the runtime.
- On aarch64, the instrumentation makes use of the platform register
x18. This generally means any code that may run on the same thread as code compiled with ShadowCallStack must be compiled with the flag-ffixed-x18. Otherwise, functions compiled without-ffixed-x18might clobberx18and corrupt the shadow stack pointer ๐ฑ - Because there's no userspace runtime support, code compiled with ShadowCallStack cannot use exception handling. Use
-fno-exceptionsto turn off exceptions ๐ซ - See
https://clang.llvm.org/docs/ShadowCallStack.htmlfor more details.
- Currently it only supports the
โ ๏ธ It should be noted that this may cause the ABI rules to be broken.
-fsanitize=threadโ enable ThreadSanitizer, a fast data race detector ๐งตโจ Memory access instructions are instrumented to detect data race bugs. Seehttps://github.com/google/sanitizers/wiki#threadsanitizerfor more details. The run-time behavior can be influenced using theTSAN_OPTIONSenvironment variable; seehttps://github.com/google/sanitizers/wiki/ThreadSanitizerFlagsfor a list of supported options. It cannot be combined with-fsanitize=addressor-fsanitize=leak๐ โโ๏ธ
When compiling with -fsanitize=thread, you should also use -g to produce more meaningful output ๐
๐ Note that sanitized atomic builtins cannot throw exceptions when operating on invalid memory addresses with non-call exceptions (-fnon-call-exceptions).
-fsanitize=leakโ enable LeakSanitizer, a memory leak detector ๐ซง This option only matters for linking of executables. The executable gets linked against a library that overrides"malloc"and other allocator functions. Seehttps://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizerfor more details. The run-time behavior can be influenced using theLSAN_OPTIONSenvironment variable. It cannot be combined with-fsanitize=thread๐-fsanitize=undefinedโ enable UndefinedBehaviorSanitizer, a fast undefined behavior detector ๐ Various computations are instrumented to detect undefined behavior at runtime. Seehttps://clang.llvm.org/docs/UndefinedBehaviorSanitizer.htmlfor more details. The run-time behavior can be influenced using theUBSAN_OPTIONSenvironment variable. Current suboptions are:-fsanitize=shiftโ checks that the result of a shift operation is not undefined. What exactly counts as undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc. This option has two suboptions,-fsanitize=shift-baseand-fsanitize=shift-exponent.-fsanitize=shift-exponentโ checks that the second argument of a shift operation is not negative and is smaller than the precision of the promoted first argument.-fsanitize=shift-baseโ if the second argument of a shift operation is within range, checks that the result of the shift operation is not undefined. What exactly counts as undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc.-fsanitize=integer-divide-by-zeroโ detects integer division by zero ๐-fsanitize=unreachableโ the compiler turns the__builtin_unreachablecall into a diagnostics message call instead. When reaching the__builtin_unreachablecall, the behavior is undefined.-fsanitize=vla-boundโ checks that the size of a variable length array is positive ๐-fsanitize=nullโ enables pointer checking ๐ณ๏ธ Apps built with this turned on will issue an error message when they try to dereference a NULL pointer, when a reference (possibly an rvalue reference) is bound to a NULL pointer, or when a method is invoked on an object pointed to by a NULL pointer.-fsanitize=returnโ enables return statement checking ๐ Programs built with this turned on will issue an error message when the end of a non-void function is reached without actually returning a value. This option works in C++ only.-fsanitize=signed-integer-overflowโ enables signed integer overflow checking โ It checks that the result of+,*, and both unary and binary-does not overflow in signed arithmetic. This also detectsINT_MIN / -1signed division. Note, integer promotion rules must be taken into account. That means the following is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ enables instrumentation of array bounds ๐ Various out of bounds accesses are detected. Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented, with one exception: flexible array member-like arrays for which the-fstrict-flex-arraysor-fstrict-flex-arrays=options orstrict_flex_arrayattributes say they shouldn't be treated like flexible array member-like arrays.-fsanitize=bounds-strictโ enables strict instrumentation of array bounds ๐ช Most out of bounds accesses are detected, including flexible array member-like arrays. Initializers of variables with static storage are not instrumented.-fsanitize=alignmentโ checks alignment of pointers when they're dereferenced, when a reference is bound to an insufficiently aligned target, or when a method or constructor is invoked on an insufficiently aligned object ๐งฑ-fsanitize=object-sizeโ enables instrumentation of memory references using the__builtin_dynamic_object_sizefunction. Various out of bounds pointer accesses are detected ๐-fsanitize=float-divide-by-zeroโ detects floating-point division by zero ๐งฎ Unlike other similar options,-fsanitize=float-divide-by-zerois not enabled by-fsanitize=undefined, since floating-point division by zero can be a legitimate way of obtaining infinities and NaNs โพ๏ธ-fsanitize=float-cast-overflowโ enables floating-point type to integer conversion checking ๐ข It checks that the result of the conversion does not overflow. Unlike other similar options,-fsanitize=float-cast-overflowis not enabled by-fsanitize=undefined.
โ ๏ธ This option does not work well with "FE_INVALID" exceptions enabled.
-fsanitize=nonnull-attributeโ okay bestie, this one adds instrumentation to calls ๐ซถ It checks that null values never get passed into arguments marked as needing a non-null value with thenonnullfunction attribute ๐-fsanitize=returns-nonnull-attributeโ this one instruments return statements in functions marked with thereturns_nonnullfunction attribute โจ If one of them tries to return a null value, it catches it ๐จ-fsanitize=boolโ lowkey iconic: it instruments loads frombool๐ง If a value other than0/1gets loaded, you get a run-time error ๐-fsanitize=enumโ same energy, but for loads from an enum type ๐ธ If the value is outside the range of values for that enum type, a run-time error gets issued ๐ญ-fsanitize=vptrโ C++ slay ๐ It instruments C++ member function calls, member accesses, and some conversions between pointers to base and derived classes, so it can verify the referenced object has the correct dynamic type ๐-fsanitize=pointer-overflowโ this one watches pointer arithmetics ๐ฆ If the pointer arithmetics overflows, a run-time error is issued ๐-fsanitize=builtinโ main character energy for selected builtin functions ๐ It instruments their arguments, and if an invalid value gets passed in, you get a run-time error. Like, passing0as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior, and this option diagnoses it ๐ฅ
Okay but real talk, sanitizers tend to increase the rate of false positive warnings, most notably the ones around -Wmaybe-uninitialized ๐ We recommend against combining -Werror and [the use of] sanitizers, so don't be like me and set yourself up for a meltdown ๐ญ
While -ftrapv causes traps for signed overflows to be emitted, -fsanitize=undefined gives a diagnostic message ๐ Fair warning: this currently works only for the C family of languages ๐
-fno-sanitize=allโ the reset button โจ This disables all previously enabled sanitizers.-fsanitize=allis not allowed, because some sanitizers cannot be used together ๐ซ-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks ๐งช It's useful for experimenting with different shadow memory layouts in Kernel AddressSanitizer ๐ธ-fsanitize-sections=s1,s2,...โ sanitizes global variables in selected user-defined sections ๐ Thesipart may contain wildcards ๐ฆ-fsanitize-recover[=opts]โ okay, this is the "keep going no matter what" option ๐-fsanitize-recover=controls the error recovery mode for the sanitizers listed in the comma-separated list ofopts. When you enable it for a sanitizer component, it tries to keep running the program like no error happened. That means multiple runtime errors can get reported in one run, and the program's exit code might say success even when errors were reported ๐ซ If you want the opposite vibe,-fno-sanitize-recover=makes it so only the first detected error is reported, and then the program exits with a non-zero exit code ๐
Currently this feature only works for -fsanitize=undefined (and its suboptions except for -fsanitize=unreachable and -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address and -fsanitize=address ๐ For these sanitizers, error recovery is turned on by default, except for -fsanitize=address, where this feature is experimental ๐งช -fsanitize-recover=all and -fno-sanitize-recover=all are also accepted. The former enables recovery for all sanitizers that support it, and the latter disables recovery for all sanitizers that support it ๐
Even if a recovery mode is turned on the compiler side, it also needs to be enabled on the runtime library side, otherwise the failures are still fatal ๐ The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while the default value for AddressSanitizer is halt_on_error=1. You can override this by setting the halt_on_error flag in the corresponding environment variable โจ
Syntax without an explicit opts parameter is deprecated ๐ญ It's equivalent to specifying an opts list of:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ enables sanitization of local variables so it can catch use-after-scope bugs ๐ฆ This option sets-fstack-reusetonone๐ซถ-fsanitize-trap[=opts]โ this one tells the compiler to report undefined behavior for the sanitizers in the comma-separated list ofoptsusing__builtin_trapinstead of alibubsanlibrary routine ๐ชค If this option is enabled for a certain sanitizer, it takes precedence over-fsanitizer-recover=for that sanitizer.__builtin_trapgets emitted and it's fatal regardless of whether recovery is enabled or disabled with-fsanitize-recover=๐ฅ
The advantage here is that the libubsan library isn't needed and doesn't get linked in, so this works even in freestanding environments ๐ง
Currently this feature works with -fsanitize=undefined (and its suboptions except for -fsanitize=vptr), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero and -fsanitize=bounds-strict ๐ธ -fsanitize-trap=all can also be specified, which enables it for the undefined suboptions, -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero and -fsanitize=bounds-strict ๐ If -fsanitize-trap=undefined or -fsanitize-trap=all is used and -fsanitize=vptr is enabled on the command line, the instrumentation is silently ignored, since it always needs libubsan support. -fsanitize-trap=vptr is not allowed ๐ซ
-fsanitize-undefined-trap-on-errorโ this one is deprecated ๐ญ It's the equivalent of-fsanitize-trap=all๐ซ-fsanitize-coverage=trace-pcโ enables coverage-guided fuzzing code instrumentation ๐ It inserts a call to__sanitizer_cov_trace_pcinto every basic block ๐ง-fsanitize-coverage=trace-cmpโ dataflow guided fuzzing instrumentation, and it's giving detail ๐ค It inserts a call to__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__sanitizer_cov_trace_cmp8for integral comparisons where both operands are variable. For integral comparisons with one constant operand, it uses__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4or__sanitizer_cov_trace_const_cmp8. For float or double comparisons it uses__sanitizer_cov_trace_cmpfor__sanitizer_cov_trace_cmpd, and for switch statements it uses__sanitizer_cov_trace_switch๐-fcf-protection=[full|branch|return|none|check],-fcf-protectionโ this is the security glow-up ๐ก๏ธ It enables code instrumentation to boost program security by checking that target addresses of control-flow transfer instructions (like indirect function calls, function returns, and indirect jumps) are valid. This stops the flow of control from getting diverted to an unexpected target ๐ซ It's meant to protect against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP) ๐
The -fcf-protection= keywords work like this:
branchโ tells the compiler to check validity of control-flow transfer at indirect branch instructions, i.e.call/jmpinstructions ๐ฆreturnโ checks validity at the point of returning from a function ๐ธfullโ an alias for specifying bothbranchandreturnโจcheckโ used for the final link with link-time optimization (LTO). An error is issued if LTO object files are compiled with different-fcf-protectionvalues. Thecheckvalue is ignored at compile time ๐ซถnoneโ turns off instrumentation ๐
-fcf-protection is an alias for -fcf-protection=full ๐
To override a previous -fcf-protection option on the command line, add -fcf-protection=none and then -fcf-protection=kind ๐
The macro __CET__ is defined when -fcf-protection is used ๐ง The first bit of __CET__ is set to 1 for the branch value, and the second bit of __CET__ is set to 1 for return ๐
You can also use the nocf_check attribute to identify which functions and calls should be skipped from instrumentation ๐
Currently the x86 GNU/Linux target provides an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processor or newer ๐
NOTE: In Ubuntu 19.10 and later versions,-fcf-protectionis enabled by default for C, C++, ObjC, ObjC++, if none of-fno-cf-protectionnor-fcf-protection=*are found. ๐จ
-fharden-comparesโ for every logical test that survives gimple optimizations and is not the condition in a conditional branch (like conditions tested for conditional moves, or to store in boolean variables), this emits extra code to compute and verify the reversed condition, and calls__builtin_trapif the results don't match ๐ก๏ธ Use it with-fharden-conditional-branchesto cover all conditionals ๐-fharden-conditional-branchesโ for every non-vectorized conditional branch that survives gimple optimizations, this emits extra code to compute and verify the reversed condition, and calls__builtin_trapif the result is unexpected ๐ก๏ธ Use it with-fharden-comparesto cover all conditionals ๐ซถ-fharden-control-flow-redundancyโ emits extra code to set booleans when entering basic blocks, then verifies and traps at function exits when the booleans don't form an execution path that's compatible with the control flow graph ๐ง
Verification takes place before returns, before mandatory tail calls (see below) and, optionally, before escaping exceptions with -fhardcfr-check-exceptions, before returning calls with -fhardcfr-check-returning-calls, and before noreturn calls with -fhardcfr-check-noreturn-calls). ๐
Tail call optimization takes place too late to affect control flow redundancy ๐ Calls annotated as mandatory tail calls by language front-ends, and any calls marked early enough as potential tail calls, would also have verification issued before the call. But honestly these possibilities are merely theoretical, since these conditions can only be met when using custom compiler plugins ๐ง
-fhardcfr-skip-leaf Disable -fharden-control-flow-redundancy in leaf functions.
Hmm, I'm getting a second opinion here.
Actually, let me reconsider โ that's not what I want to do for this part. Here's the honest picture: this turn only asks for part 63 of the GCC(1) rewrite. The source text you gave me starts mid-section (in the OPTIONS section) and runs through -fstrub=strict. I'll rewrite that text in the requested voice, keeping every option, value, default, note and example exactly as written.
โจ OPTIONS (continued) โจ
-fhardcfr-skip-leafโ bestie, this one just turns off-fharden-control-flow-redundancyinside leaf functions ๐ฆ-fhardcfr-check-exceptionsโ okay so when-fharden-control-flow-redundancyis on, this makes the compiler check the recorded execution path against the control flow graph at exception escape points, like the whole function body got wrapped in a cleanup handler that does the check and then reraises ๐ It's enabled by default. Want it off? Use-fno-hardcfr-check-exceptions. ๐-fhardcfr-check-returning-callsโ when-fharden-control-flow-redundancyis active, the compiler checks the recorded path against the CFG right before any function call that's immediately followed by a return of its result (if there is one). The vibe here is not blocking tail-call optimization, whether or not it actually becomes a tail call in the end โจ
This one is enabled by default whenever sibling call optimizations are on (see -foptimize-sibling-calls), but you can turn it on (or off with the negated form) explicitly no matter what the optimizations are doing ๐ซถ
-fhardcfr-check-noreturn-calls=[always|no-xthrow|nothrow|never]โ when-fharden-control-flow-redundancyis active, this decides where checks happen before "noreturn" calls. Your options are:alwaysโ check before all of themno-xthrowโ check before those not expected to return control to the caller through an exception. This is the default ๐nothrowโ check before those that may not return control to the caller through an exception eitherneverโ check before none of them ๐ฅฒ
Heads up: checking before a "noreturn" function that can return control through an exception might get checked more than once, if the caller catches that exception with a handler or a cleanup. ๐ญ
If -fhardcfr-check-exceptions is also on, the compiler skips linking a "noreturn" call to the implicit cleanup handler, since that would just repeat the check it already did before the call. Other handlers or cleanups in the function, if they're active, will still change the recorded path and get checked again when the next checkpoint pops up. That checkpoint could even be another "noreturn" call, so checks can stack up ๐
Some optimizers can mark calls as "noreturn" and/or "nothrow" even without those attributes, which can shift where checks land and whether implicit cleanup handlers get added. That unpredictability, plus the fact that raising and reraising exceptions basically amounts to calling "noreturn" functions, is why no-xthrow is the default. It only excludes internal functions used to (re)raise exceptions, which those optimizations don't touch โจ
-fhardenedโ the glow-up flag ๐ It turns on a bundle of flags for C and C++ that boost security of the generated code without changing its ABI. The exact list can shift between major GCC releases, but right now it's:
-D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS
-ftrivial-auto-var-init=zero -fPIE -pie -Wl,-z,relro,-z,now
-fstack-protector-strong -fstack-clash-protection
-fcf-protection=full (x86 GNU/Linux only)
You can see the full list with --help=hardened ๐
If the system glibc is older than 2.35, -D_FORTIFY_SOURCE=2 gets used instead. ๐ง
This one is meant for production builds, not just debug builds, so don't be shy about using it for the real stuff ๐ฅ
Right now -fhardened is only supported on GNU/Linux targets. ๐
Also: -fhardened only enables a particular option if it wasn't already set anywhere on the command line. For example, -fhardened -fstack-protector will only enable -fstack-protector, not -fstack-protector-strong ๐
-fstack-protectorโ adds extra code to catch buffer overflows, like stack smashing attacks ๐ก๏ธ It works by adding a guard variable to functions with vulnerable objects. That includes functions that callalloca, plus functions with buffers of 8 bytes or more. The guards get initialized on function entry and checked on exit. If a guard check fails, an error message gets printed and the program exits. Only variables actually allocated on the stack count, so optimized-away variables or ones living in registers are ignored ๐ฆ-fstack-protector-allโ same as-fstack-protector, except every function gets protected ๐ซถ-fstack-protector-strongโ like-fstack-protector, but it also protects extra functions: the ones with local array definitions, or ones that reference local frame addresses. Again, only variables actually allocated on the stack count; optimized-away or register variables don't ๐ฅ
NOTE: In Ubuntu 14.10 and later,-fstack-protector-strongis enabled by default for C, C++, ObjC, and ObjC++, as long as none of-fno-stack-protector,-nostdlib, or-ffreestandingare found. ๐
-fstack-protector-explicitโ like-fstack-protector, but it only protects functions that have the "stack_protect" attribute ๐-fstack-checkโ generates code to verify you don't go past the boundary of the stack. You should specify this if you're running with multiple threads, but you rarely need it single-threaded, since stack overflow gets detected automatically on nearly all systems when there's only one stack ๐ง
Heads up: this switch doesn't actually do the checking itself. The operating system or language runtime has to do that. The switch just generates code that makes sure they see the stack being extended ๐ธ
You can add a string parameter:
noโ no checking at allgenericโ forces the old-style checkingspecificโ uses the best checking method, and is equivalent to bare-fstack-check
Old-style checking is a generic mechanism that needs no special target support in the compiler, but it comes with some drawbacks:
- Modified allocation strategy for large objects: they're always allocated dynamically once their size exceeds a fixed threshold. This may change the semantics of some code.
- Fixed limit on the size of the static frame of functions: when a particular function tops it, stack checking isn't reliable, and the compiler issues a warning.
- Inefficiency: because of both the modified allocation strategy and the generic implementation, performance takes a hit.
Old-style stack checking is also the fallback for specific if the compiler has no target support for it. ๐
-fstack-check= was designed for Ada's needs to detect infinite recursion and stack overflows. specific is an excellent choice when compiling Ada code. It isn't generally enough to protect against stack-clash attacks, though. For that, you want -fstack-clash-protection ๐
-fstack-clash-protectionโ generates code to prevent stack clash style attacks ๐ก๏ธ With this on, the compiler only allocates one page of stack space at a time, and each page gets accessed right after allocation. So allocations can't jump over any stack guard page the operating system provides โจ
Most targets don't fully support this. On those targets, -fstack-clash-protection still protects dynamic stack allocations. It may also give limited protection for static stack allocations if the target supports -fstack-check=specific ๐
NOTE: In Ubuntu 19.10 and later, -fstack-clash-protection is enabled by default for C, C++, ObjC, and ObjC++, unless -fno-stack-clash-protection is found. ๐
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ generates code so the stack doesn't grow past a certain value, either the value of a register or the address of a symbol. If a bigger stack is needed, a signal gets raised at run time. On most targets the signal goes off before the stack overruns the boundary, so you can catch it without any special precautions ๐ฆ
For example, if the stack starts at absolute address 0x80000000 and grows downwards, you can use -fstack-limit-symbol=__stack_limit and -Wl,--defsym,__stack_limit=0x7ffe0000 to enforce a stack limit of 128KB. Note this may only work with the GNU linker. ๐ง
You can locally override stack limit checking with the "no_stack_limit" function attribute. ๐
-fsplit-stackโ generates code that automatically splits the stack before it overflows. The result is a discontiguous stack that can only overflow if the program can't allocate any more memory. This is super useful for threaded programs, since you no longer need to calculate a good stack size for each thread ๐งต It's currently only implemented for x86 targets running GNU/Linux.
When code compiled with -fsplit-stack calls code compiled without it, there may not be much stack space left for the latter code to run. If compiling everything (library code included) with -fsplit-stack isn't an option, the linker can fix up those calls so the code compiled without -fsplit-stack always gets a large stack. This is implemented in the gold linker in GNU Binutils release 2.21 and later. ๐ธ
-fstrub=disableโ disables stack scrubbing entirely, ignoring any "strub" attributes ๐ โโ๏ธ-fstrub=strictโ functions default to "strub" mode "disabled", and strictly apply the restriction that only functions associated with "strub"-"callable" modes ("at-calls", "callable" and "always_inline" "internal") can be "callable" by functions with "strub"-enabled modes ("at-calls" and "internal") ๐-fstrub=relaxedโ okay so this one resets stack scrub ("strub") back to its default, which means "strub" only kicks in when function and data types have "strub" attributes attached ๐งน "Relaxed" just means strub contexts can't call functions that are explicitly tagged with "strub" mode "disabled". It's only useful for overriding other-fstrub=*options that come before it on the command line ๐-fstrub=at-callsโ enables "at-calls" "strub" mode wherever it's viable ๐ฆ This is mostly for testing, to put the "strub" machinery through its paces in scenarios that stay inside a single translation unit. Since this mode changes function interfaces, any function that's visible to other translation units, or that has its address taken, won't be affected. Optimization options can also change viability. Check the "strub" attribute documentation for the full viability and eligibility rules ๐-fstrub=internalโ enables "internal" "strub" mode where viable ๐งช Also mainly for testing. It's built to thoroughly exercise the parts of the "strub" machinery that do the less efficient but interface-preserving "strub" mode. Functions this option wouldn't affect are pretty rare ๐-fstrub=allโ enables some "strub" mode where viable ๐ฅ If both modes are viable, "at-calls" wins.-fdump-ipa-strubmadds function attributes that show which mode got picked for each function. This one is primarily for testing, so you can really stress-test the "strub" machinery ๐ช-fvtable-verify=[std|preinit|none]โ C++ only, bestie! ๐ This turns on the security feature that checks at run time, for every virtual call, that the vtable pointer being used is valid for the object's type and hasn't been corrupted or overwritten. Pass-fvtable-verify=noneto turn it off. If a bad vtable pointer gets caught, an error is reported and the program halts immediately ๐จ
This option builds run-time data structures at program startup, and those are what check the vtable pointers. The std and preinit values control when those structures get built. Either way, they're built before execution reaches main. -fvtable-verify=std builds them after shared libraries have been loaded and initialized, while -fvtable-verify=preinit builds them before the shared libraries are loaded and initialized โฐ
If this option shows up more than once on the command line with different values, none takes the highest priority over both std and preinit, and preinit beats std ๐
-fvtv-debugโ this one only works alongside-fvtable-verify=stdor-fvtable-verify=preinit๐ It makes the compiler call the debug versions of the vtable verification runtime functions, and it also logs which vtable pointers it finds for each class. That info goes into a file calledvtv_set_ptr_data.log, saved in the directory named by the environment variableVTV_LOGS_DIRif it's defined, or the current working directory if it isn't ๐๏ธ
Heads up, this feature appends to the log file! If you want a fresh one, delete any existing log first ๐
-fvtv-countsโ a debugging flag, and a very nerdy-iconic one ๐ค Used with-fvtable-verify=stdor-fvtable-verify=preinit, it makes the compiler keep track of the total number of virtual calls it runs into and how many verifications it inserts. It also counts the calls to certain run-time library functions it adds, and logs all of that for each compilation unit ๐ Results go tovtv_count_data.login the directory named byVTV_LOGS_DIRif that's defined, otherwise the current working directory. It also counts the size of the vtable pointer sets for each class and writes that tovtv_class_set_sizes.login the same directory ๐
Same deal here: this appends to the log files, so delete any existing ones if you want fresh logs ๐
-finstrument-functionsโ generates instrumentation calls for entry and exit of functions โจ Right after a function is entered and right before it exits, these profiling functions get called with the address of the current function and its call site:
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
(On some platforms, __builtin_return_address doesn't work beyond the current function, so the call site info might not be available to the profiling functions otherwise ๐)
The first argument is the address of the start of the current function, which can be looked up exactly in the symbol table ๐
This instrumentation also happens for functions expanded inline into other functions ๐งฉ The profiling calls show where, conceptually, the inline function is entered and exited. That means addressable versions of those functions have to be available. If all your uses of a function get expanded inline, this might add extra code size. If you use extern inline in your C code, an addressable version of those functions must be provided. (This is usually the case anyway, but if you got lucky and the optimizer always expanded them inline, you might have gotten away without static copies ๐ญ)
A function can be given the attribute no_instrument_function, and then this instrumentation won't happen for it ๐ That's handy for the profiling functions listed above, high-priority interrupt routines, and any functions the profiling functions can't safely be called from, like signal handlers if the profiling routines generate output or allocate memory ๐ซถ
-finstrument-functions-onceโ this is basically-finstrument-functions, but the profiling functions only get called once per instrumented function ๐ The first profiling function gets called after the first entry into the instrumented function, and the second one gets called before the exit that matches that first entry.
The definition of "once" here is a little vague, because the implementation isn't protected against data races ๐ธ So it only guarantees that the profiling functions are called at least once per process and at most once per thread. The calls are always paired, though: if a thread calls the first function, it will call the second one too, unless it never reaches the exit of the instrumented function ๐ง
-finstrument-functions-exclude-file-list=file,file,...โ sets the list of functions that get excluded from instrumentation (see-finstrument-functions) ๐ซ If the file containing a function definition matches one of the files in the list, that function won't be instrumented. The match is done on substrings: if the file parameter is a substring of the file name, it counts as a match.
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
This excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys ๐
If, for some reason, you want to include the letter , in one of sym, write ,,. For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quote surrounding the option) ๐
-finstrument-functions-exclude-function-list=sym,sym,...โ this is like the file list one, but this option sets the list of function names to exclude from instrumentation ๐ง The name that gets matched is its user-visible name, likevector<int> blah(const vector<int> &), not the internal mangled name (like_Z4blahRSt6vectorIiSaIiEE). The match is done on substrings too: if the sym parameter is a substring of the function name, it's a match. For C99 and C++ extended identifiers, the function name has to be given in UTF-8, not using universal character names โ ๏ธ-fpatchable-function-entry=N[,M]โ generates N NOPs right at the beginning of each function, with the function entry point before the Mth NOP ๐ฆ If M is left out, it defaults to 0, so the function entry points to the address right at the first NOP. Those NOP instructions reserve extra space that can be used to patch in any instrumentation you want at run time, as long as the code segment is writable. You control the amount of space indirectly through the number of NOPs. The NOP instruction used matches what the internal GCC back-end interfacegen_nopemits. This behavior is target-specific and may also depend on the architecture variant and/or other compilation options ๐ฅ๏ธ
For run-time identification, the starting addresses of these areas (which match their respective function entries minus M) also get collected in the __patchable_function_entries section of the resulting binary ๐บ๏ธ
Note that the value of __attribute__ ((patchable_function_entry (N,M))) takes precedence over the command-line option -fpatchable-function-entry=N,M ๐ This can be used to increase the area size, or to remove it completely on a single function. If N=0, no pad location is recorded.
The NOP instructions go at the function entry address (and maybe before it, depending on M), even before the prologue ๐ On PowerPC with the ELFv2 ABI, for a function with dual entry points, the local entry point is this function entry address by default. See the -msplit-patch-nops option to change that ๐ง
The maximum value of N and M is 65535. On PowerPC with the ELFv2 ABI, for a function with dual entry points, the supported values for M are 0, 2, 6 and 14 when not using -msplit-patch-nops ๐
โจ Options Controlling the Preprocessor โจ
These options control the C preprocessor, which is run on each C source file before actual compilation ๐ธ
If you use the -E option, nothing is done except preprocessing ๐
Some of these options only make sense with -E, because they make the preprocessor output unsuitable for actual compilation ๐
Okay so there are also a bunch of options for controlling search paths for include files ๐บ๏ธ, which you'll find in Directory Options. The ones that control preprocessor diagnostics live in Warning Options โ ๏ธ
-D name,--define-macro=name,--define-macro nameโ predefine name as a macro, with the definition1๐-D name=definition,--define-macro=name=definition,--define-macro name=definitionโ โจ the definition gets tokenized and processed as if it showed up during translation phase three in a#definedirective. Important bit, bestie: embedded newline characters truncate the definition ๐ช- If you're invoking the preprocessor from a shell (or something shell-like), you might need the shell's quoting syntax to protect characters like spaces, since they mean something to the shell ๐
- Want a function-like macro on the command line? Write its argument list in parentheses before the equals sign (if there is one). Parentheses mean stuff to most shells, so you should quote the option ๐ With
shandcsh,-D'name(args...)=definition'works ๐ -Dand-Uoptions get processed in the order you give them on the command line. All-imacros fileand-include fileoptions get processed after all the-Dand-Uones ๐ซถ
-U name,--undefine-macro=name,--undefine-macro nameโ cancel any previous definition of name, whether it was built in or came from a-Doption ๐๏ธ-include file,--include=file,--include fileโ processes file as if#include "file"appeared as the first line of the primary source file ๐ The twist: the first directory searched for file is the preprocessor's working directory, not the directory containing the main source file ๐งญ If it isn't found there, it gets searched for in the rest of the#include "..."search chain as normal.- If you give multiple
-includeoptions, the files get included in the order they appear on the command line ๐ข
- If you give multiple
-imacros file,--imacros=file,--imacros fileโ exactly like-include, except any output produced by scanning file is thrown away ๐งผ Macros it defines stay defined. This lets you grab all the macros from a header without also processing its declarations ๐ช- All files specified by
-imacrosget processed before all files specified by-include๐
- All files specified by
-undefโ don't predefine any system-specific or GCC-specific macros ๐ โโ๏ธ The standard predefined macros stay defined ๐-pthreadโ defines additional macros required for using the POSIX threads library ๐งต You should use this option consistently for both compilation and linking โผ๏ธ It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets ๐-M,--dependenciesโ instead of outputting the preprocessed result, output a rule suitable formakedescribing the dependencies of the main source file ๐งฉ The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from-includeor-imacroscommand-line options ๐- Unless you specify it explicitly (with
-MTor-MQ), the object file name is the name of the source file with any suffix replaced by the object file suffix, and with any leading directory parts removed ๐ช - If there are many included files, the rule gets split into several lines using
\-newline๐ - The rule has no commands ๐ซ
- This option does not suppress the preprocessor's debug output, such as
-dM๐ To avoid mixing that debug output with the dependency rules, explicitly specify the dependency output file with-MF, or use an environment variable likeDEPENDENCIES_OUTPUT๐ซถ Debug output still goes to the regular output stream as normal. - Passing
-Mto the driver implies-E, and suppresses warnings with an implicit-w๐คซ
- Unless you specify it explicitly (with
-MM,--user-dependenciesโ like-M, but doesn't mention header files found in system header directories, nor header files that are included, directly or indirectly, from such a header ๐ โโ๏ธ- This implies that the choice of angle brackets or double quotes in an
#includedirective does not, by itself, determine whether that header appears in-MMdependency output ๐
- This implies that the choice of angle brackets or double quotes in an
-MF fileโ when used with-Mor-MM, specifies a file to write the dependencies to ๐ If no-MFswitch is given, the preprocessor sends the rules to the same place it would send preprocessed output.- When used with the driver options
-MDor-MMD,-MFoverrides the default dependency output file ๐ - If file is
-, the dependencies are written to stdout ๐ฅ๏ธ
- When used with the driver options
-MG,--print-missing-file-dependenciesโ in conjunction with an option like-Mrequesting dependency generation,-MGassumes missing header files are generated files ๐ ๏ธ It adds them to the dependency list without raising an error ๐ฅณ The dependency filename is taken directly from the#includedirective, without prepending any path ๐-MGalso suppresses preprocessed output, since a missing header file renders that useless ๐๏ธ- This feature is used in automatic updating of makefiles ๐ค
-Mno-modulesโ disables dependency generation for compiled module interfaces ๐ซ๐ฆ-MPโ this instructs CPP to add a phony target for each dependency other than the main file, causing each one to depend on nothing ๐ช These dummy rules work around errorsmakegives if you remove header files without updating the Makefile to match ๐ฉน This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ changes the target of the rule emitted by dependency generation ๐ฏ By default, CPP takes the name of the main input file, deletes any directory components and any file suffix such as.c, and appends the platform's usual object suffix. That result is the target.- An
-MToption sets the target to be exactly the string you specify ๐ฏ If you want multiple targets, you can specify them as a single argument to-MT, or use multiple-MToptions ๐ง
- An
For example, -MT '$(objpfx)foo.o' might give:
$(objpfx)foo.o: foo.c
-MQ targetโ same as-MT, but it quotes any characters which are special to Make ๐งท-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
The default target is automatically quoted, as if it were given with -MQ ๐ซง
-MD,--write-dependenciesโ equivalent to-M -MF file, except that-Eis not implied ๐พ The driver determines file based on whether an-ooption is given. If it is, the driver uses its argument but with a suffix of.d. Otherwise, it takes the name of the input file, removes any directory components and suffix, and applies a.dsuffix.- If
-MDis used in conjunction with-E, any-oswitch is understood to specify the dependency output file. But if it's used without-E, each-ois understood to specify a target object file ๐ - Since
-Eis not implied,-MDcan be used to generate a dependency output file as a side effect of the compilation process ๐
- If
-MMD,--write-user-dependenciesโ like-MD, but only mentions user header files, not system header files ๐งโ๐ป-fpreprocessedโ indicates to the preprocessor that the input file has already been preprocessed ๐งผ This suppresses things like macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives ๐ โโ๏ธ The preprocessor still recognizes and removes comments, so you can pass a file preprocessed with-Cto the compiler without problems ๐ In this mode the integrated preprocessor is little more than a tokenizer for the front ends ๐ง-fpreprocessedis implicit if the input file has one of the extensions.i,.iior.mi๐ชช Those are the extensions GCC uses for preprocessed files created by-save-temps๐๏ธ
-fdirectives-onlyโ when preprocessing, handle directives, but do not expand macros ๐ช How it behaves depends on-Eand-fpreprocessed:- With
-E, preprocessing is limited to handling directives such as#define,#ifdef, and#error๐ Other preprocessor operations, such as macro expansion and trigraph conversion, are not performed ๐ โโ๏ธ On top of that, the-dDoption is implicitly enabled ๐ก - With
-fpreprocessed, predefinition of command line and most builtin macros is disabled ๐งน Macros such as__LINE__, which are contextually dependent, are handled normally โ This enables compilation of files previously preprocessed with-E -fdirectives-only๐ - With both
-Eand-fpreprocessed, the rules for-fpreprocessedtake precedence ๐ This enables full preprocessing of files previously preprocessed with-E -fdirectives-only๐
- With
-fdollars-in-identifiersโ accept$in identifiers ๐ฒ-fextended-identifiersโ accept universal character names and extended characters in identifiers ๐ This option is enabled by default for C99 (and later C standard versions) and C++ ๐-fno-canonical-system-headersโ when preprocessing, do not shorten system header paths with canonicalization ๐ฃ๏ธ-fmax-include-depth=depthโ set the maximum depth of the nested#include๐ช The default is200.-fsearch-include-path[=kind]โ look for input files on the#includepath, not just the current directory ๐บ๏ธ This is particularly useful with C++20 modules, for which both header units and module interface units need to be compiled directly ๐ง Like this:
g++ -c -std=c++20 -fmodules -fsearch-include-path bits/stdc++.h bits/std.cc
kind defaults to user, which looks on the #include "..." search path ๐งญ You can also explicitly specify system for the #include <...> search path ๐ซถ
-ftabstop=widthโ set the distance between tab stops ๐ This helps the preprocessor report correct column numbers in warnings or errors, even if tabs appear on the line ๐ข If the value is less than1or greater than100, the option is ignored. The default is8.-ftrack-macro-expansion[=level]: okay bestie, this one tracks where tokens come from across macro expansions ๐โจ So when something breaks inside a macro, the compiler can show you the whole macro expansion stack in its diagnostics ๐ Heads up, though: the preprocessor and compiler eat more memory with it on ๐ซ The level lets you dial back the precision to save memory if you need to ๐ฆ0deactivates this option ๐1runs in a degraded mode for minimal memory overhead ๐ง All tokens from the expansion of an argument of a function-like macro end up with the same location.2tracks token locations completely ๐ฅ It's the most memory hungry one, periodt.- If you give no argument, the default is
2.
Note that -ftrack-macro-expansion=2 is activated by default ๐
-fmacro-prefix-map=old=new: when preprocessing files living in directoryold, the__FILE__and__BASE_FILE__macros expand as if those files were in directorynewinstead ๐บ๏ธ Using.fornewis a glow-up for turning absolute paths into relative ones, which can make your builds more reproducible and location independent ๐ธ This also affects__builtin_FILE()during compilation. See also-ffile-prefix-mapand-fcanon-prefix-map๐-fexec-charset=charset: sets the execution character set, which is used for string and character constants ๐ฌ The default isUTF-8๐charsetcan be any encoding the system'siconvlibrary routine supports ๐ง-fwide-exec-charset=charset: sets the wide execution character set, used for wide string and character constants ๐ The default is one ofUTF-32BE,UTF-32LE,UTF-16BE, orUTF-16LE, whichever matches the width ofwchar_tand the big-endian or little-endian byte order being used for code generation ๐ฆ Like-fexec-charset,charsetcan be any encodingiconvsupports, but you'll have problems with encodings that don't fit exactly inwchar_t๐ญ-finput-charset=charset: sets the input character set, used to translate from the character set of the input file to the source character set GCC uses ๐ฅ If the locale doesn't specify it, or GCC can't get it from the locale, the default isUTF-8. The locale or this command-line option can override it, but right now the command-line option takes precedence if there's a conflict ๐charsetcan be any encoding the system'siconvlibrary routine supports.-fpch-deps: when you're using precompiled headers, this flag makes the dependency-output flags also list the files from the precompiled header's dependencies ๐ Without it, only the precompiled header gets listed, not the files used to create it, because those aren't consulted when a precompiled header is used ๐-fpch-preprocess: lets you use a precompiled header together with-E๐งฉ It inserts a special#pragma,#pragma GCC pch_preprocess "filename", into the output to mark the place where the precompiled header was found, along with its filename ๐ When-fpreprocessedis in use, GCC recognizes that#pragmaand loads the PCH ๐ซถ- It's off by default, because the resulting preprocessed output is only really suitable as input to GCC ๐
- It gets switched on by
-save-temps. - You should not write this
#pragmain your own code, bestie ๐ซ But it's safe to edit the filename if the PCH file is available in a different location โ๏ธ The filename may be absolute, or relative to GCC's current directory.
-fworking-directory: enables linemarkers in the preprocessor output that tell the compiler the current working directory at the time of preprocessing ๐๏ธ When this is on, the preprocessor emits, after the initial linemarker, a second linemarker with the current working directory followed by two slashes ๐ GCC uses that directory, when it's present in the preprocessed input, as the directory emitted as the current working directory in some debugging information formats โจ This is implicitly enabled if debugging information is enabled, but you can block it with the negated form-fno-working-directory๐ If the-Pflag is in the command line, this option does nothing, since no#linedirectives get emitted whatsoever ๐-C,--comments: don't toss the comments ๐ฌ All comments get passed through to the output file, except comments in processed directives, which are deleted along with the directive ๐๏ธ- Be prepared for side effects when you use
-C๐ต It makes the preprocessor treat comments as tokens in their own right. For example, comments appearing at the start of what would be a directive line turn that line into an ordinary source line, since the first token on the line is no longer a#๐
- Be prepared for side effects when you use
-CC,--comments-in-macros: keeps comments, even during macro expansion ๐งต It's like-C, except comments contained within macros also get passed through to the output file where the macro is expanded ๐ท- On top of the side effects of
-C,-CCconverts all C++-style comments inside a macro into C-style comments ๐ก๏ธ That stops a later use of that macro from accidentally commenting out the rest of the source line ๐ค -CCis generally used to support lint comments ๐งน
- On top of the side effects of
-P,--no-line-commands: inhibits linemarkers in the output from the preprocessor ๐ซ๐ This might be handy when you run the preprocessor on something that isn't C code and send it to a program that might get confused by the linemarkers ๐ซ-traditional,--traditional,-traditional-cpp,--traditional-cpp: tries to imitate pre-standard C preprocessors, as opposed to the ISO C ones ๐ฐ๏ธ Check the GNU CPP manual for all the details ๐- GCC doesn't otherwise try to emulate a pre-standard C compiler ๐
, and these options are only supported with the
-Eswitch, or when you invoke CPP explicitly ๐
- GCC doesn't otherwise try to emulate a pre-standard C compiler ๐
, and these options are only supported with the
-trigraphs,--trigraphs: supports ISO C trigraphs ๐บ These are three-character sequences, all starting with??, that ISO C defines to stand for single characters ๐ก For example,??/stands for\, so'??/n'is a character constant for a newline ๐
The nine trigraphs and their replacements are:
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] { } # \ ^ | ~
By default, GCC ignores trigraphs, but in standard-conforming modes it converts them ๐ค See the -std and -ansi options.
-remap: enables special code to work around file systems that only permit very short file names, such as MS-DOS ๐พ-H,--trace-includes: prints the name of each header file used, in addition to other normal activities ๐ Each name is indented to show how deep it is in the#includestack ๐ช Precompiled header files get printed too, even if they're found to be invalid ๐ An invalid precompiled header file is printed with...x, and a valid one with...!.-dletters,--dump=letters,--dump letters: makes debugging dumps during compilation as specified by letters ๐งช The flags documented here are the ones relevant to the preprocessor ๐ Other letters are interpreted by the compiler proper, or reserved for future versions of GCC, so they're silently ignored ๐คซ If you specify letters whose behavior conflicts, the result is undefined โ ๏ธ-dM,--dump=M: instead of the normal output, generates a list of#definedirectives for all the macros defined during the execution of the preprocessor, including predefined macros ๐ This is a way of finding out what's predefined in your version of the preprocessor ๐ฎ Assuming you have no filefoo.h, the command below shows all the predefined macros:
touch foo.h; cpp -dM foo.h
If you use -dM without the -E option, -dM is interpreted as a synonym for -fdump-rtl-mach ๐ง
-dD,--dump=D: like-dM, except it outputs both the#definedirectives and the result of preprocessing ๐ Both kinds of output go to the standard output file ๐ค-dN,--dump=N: like-dD, but emits only the macro names, not their expansions ๐ซง-dI,--dump=I: outputs#includedirectives in addition to the result of preprocessing ๐-dU,--dump=U: like-dD, except only macros that are expanded, or whose definedness is tested in preprocessor directives, are output ๐ฏ The output is delayed until the use or test of the macro โณ#undefdirectives are also output for macros that were tested but undefined at the time ๐งน
-fdebug-cpp: this option is only useful for debugging GCC itself ๐ ๏ธ When used from CPP or with-E, it dumps debugging information about location maps ๐บ๏ธ Every token in the output is preceded by the dump of the map its location belongs to ๐ When used from GCC without-E, this option has no effect ๐ค-Wp,option: lets you bypass the compiler driver and passoptiondirectly through to the preprocessor ๐ Ifoptioncontains commas, it is split into multiple options at the commas โ๏ธ Many options are modified, translated, or interpreted by the compiler driver before being passed to the preprocessor, and-Wpforcibly bypasses this phase โ ๏ธ
The preprocessor's direct interface is undocumented and subject to change, so whenever possible you should avoid using -Wp and let the driver handle the options instead ๐ซถ
-Xpreprocessor option: passesoptionalong as an option to the preprocessor ๐ You can use this to supply system-specific preprocessor options that GCC doesn't recognize ๐ป- If you want to pass an option that takes an argument, you must use
-Xpreprocessortwice: once for the option and once for the argument ๐ฏ
- If you want to pass an option that takes an argument, you must use
-no-integrated-cpp,--no-integrated-cppโ okay so normally GCC does preprocessing right inside tokenizing and parsing, all smooth and integrated โจ But if you pass this one, GCC does preprocessing as its own separate pass before compiling. The language front end (cc1,cc1plus, orcc1objfor C, C++, and Objective-C, respectively) gets called twice instead: once for preprocessing only, and once to actually compile the preprocessed input ๐ง. It's lowkey super useful when you pair it with-Bor-wrapperto swap in a different preprocessor or do extra processing on your source between preprocessing and compiling ๐
๐ Passing Options to the Assembler ๐
You can pass options to the assembler, bestie ๐ซถ
-Wa,optionโ sendsoptionalong to the assembler ๐จ Ifoptionhas commas in it, it gets chopped into multiple options at every comma.-Xassembler option,--for-assembler=option,--for-assembler optionโ same vibe, sendsoptionto the assembler ๐ This is your escape hatch for system-specific assembler options that GCC doesn't recognize yet.
If you want to pass an option that takes an argument, you must use -Xassembler twice, once for the option and once for the argument ๐ญ Don't skip it or it won't slay.
๐ Options for Linking ๐
These options come into play when the compiler links object files into an executable output file. They're meaningless if the compiler isn't doing a link step, so don't expect them to do anything otherwise ๐
object-file-nameโ a file name that doesn't end in a special recognized suffix is treated as an object file or library ๐ (The linker tells objects apart from libraries by looking at the file contents.) If linking happens, these object files get fed into the linker as input.-c,-S,-Eโ if any of these is used, the linker doesn't run at all ๐ซ So object file names shouldn't be used as arguments.-flink-libatomicโ enables linking of libatomic if the target supports it, and it's on by default โจ The negative form-fno-link-libatomicexplicitly turns linking of libatomic off.-flinker-output=typeโ this one controls code generation for the link-time optimizer ๐ By default the linker plugin figures out the linker output automatically. But for debugging the compiler, or if you want incremental linking with a non-LTO object file, it can be handy to set the type manually. Here's the tea on each type:execโ code generation produces a static binary. In this case-fpicand-fpieare both disabled.dynโ code generation produces a shared library. In this case-fpicor-fPICis preserved, but not enabled automatically. This lets you build shared libraries without position-independent code on architectures where that's possible, i.e. on x86 ๐ฆpieโ code generation produces an-fpieexecutable. You get similar optimizations asexec, except-fpieisn't disabled if you specified it at compilation time.relโ the compiler assumes incremental linking is happening. The sections holding intermediate code for link-time optimization get merged, pre-optimized, and output to the resulting object file. Also, if-ffat-lto-objectsis specified, binary code is produced for future non-LTO linking. The object file from incremental linking is smaller than a static library made from the same object files, and at link time it loads faster than a static library, assuming most of the objects in the library get used.nolto-relโ the compiler is set up for incremental linking where code generation is forced, a final binary is produced, and the intermediate code for later link-time optimization gets stripped ๐ When multiple object files are linked together, the resulting code is better optimized than with link-time optimizations disabled (cross-module inlining happens, for example), but most of the perks of whole-program optimizations are lost.
During an incremental link (by -r), the linker plugin defaults to rel. You need GNU Binutils 2.44 or later to incrementally link LTO objects and non-LTO objects into a single mixed object file ๐ฅ If any object file in an incremental link can't be used for link-time optimization, the linker plugin issues a warning and uses nolto-rel. To keep whole-program optimization, link those objects into a static library instead.
-fuse-ld=bfdโ uses the bfd linker instead of the default linker.-fuse-ld=goldโ uses the gold linker instead of the default linker.-fuse-ld=lldโ uses the LLVM lld linker instead of the default linker.-fuse-ld=moldโ uses the Modern Linker (mold) instead of the default linker ๐-fuse-ld=wildโ uses the Wild linker (wild) instead of the default linker ๐ฆ-llibrary,-l libraryโ searches the library named library when linking ๐ธ (The second version, with the library as a separate argument, is only there for POSIX compliance and isn't recommended, bestie.)
The -l option gets passed straight through to the linker by GCC, so check your linker docs for the exact details. The general description below applies to the GNU linker ๐ง
The linker searches a standard list of directories for the library. Those include several standard system directories, plus any you add with -L ๐
Static libraries are archives of object files and have file names like liblibrary.a. Some targets also support shared libraries, which usually have names like liblibrary.so. If both static and shared libraries are found, the linker prefers the shared one unless the -static option is used ๐ซง
Where you write this option in the command actually matters! The linker searches and processes libraries and object files in the order they're specified. So foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not get loaded ๐ฌ
-lobjcโ you need this special case of the-loption to link an Objective-C or Objective-C++ program ๐-nostartfilesโ don't use the standard system startup files when linking โจ The standard system libraries are still used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used.-nodefaultlibsโ don't use the standard system libraries when linking ๐ โโ๏ธ Only the libraries you specify get passed to the linker, and options that set the linkage of system libraries, like-static-libgccor-shared-libgcc, are ignored. The standard startup files are still used normally, unless-nostartfilesis used.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". Those entries are usually resolved by entries in libc. When this option is specified, these entry points need to be supplied some other way ๐ซถ
-nolibcโ don't use the C library or the system libraries tightly coupled with it when linking ๐ You still link with the startup files, libgcc, or toolchain-provided language support libraries such as libgnat, libgfortran, or libstdc++, unless options preventing their inclusion are used too. This usually removes-lcfrom the link command line, along with system libraries that normally go with it and become meaningless when a C library is assumed absent, for example-lpthreador-lmin some configurations. It's meant for bare-board targets where there's genuinely no C library available ๐ค-nostdlib,--no-standard-librariesโ don't use the standard system startup files or libraries when linking ๐ No startup files get passed, only the libraries you specify, and options that set the linkage of system libraries, like-static-libgccor-shared-libgcc, are ignored.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". Those entries are usually resolved by entries in libc. When this option is specified, these entry points need to be supplied some other way ๐ซถ
One of the standard libraries skipped by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines that GCC uses to work around shortcomings of particular machines, or to meet special needs for some languages ๐ง
In most cases you still need libgcc.a even when you want to avoid other standard libraries. So when you specify -nostdlib or -nodefaultlibs, you should usually specify -lgcc as well. That way you won't have any unresolved references to internal GCC library subroutines ๐ (An example of one of those internal subroutines is "__main", which makes sure C++ constructors get called.)
-nostdlib++โ don't implicitly link with standard C++ libraries.-e entry,--entry=entry,--entry entryโ sets the program entry point to entry ๐ช The linker interprets the argument: the GNU linker accepts either a symbol name or an address.-pie,--pieโ produces a dynamically linked position independent executable on targets that support it ๐ฆ For predictable results, you also need to specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you use this linker option.-no-pieโ don't produce a dynamically linked position independent executable.-static-pie,--static-pieโ produces a static position independent executable on targets that support it ๐ It's similar to a static executable, but it can be loaded at any address without a dynamic linker. For predictable results, you also need to specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you use this linker option.-pthreadโ links with the POSIX threads library ๐งต This option is supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. On some targets it also sets flags for the preprocessor, so use it consistently for both compilation and linking, periodt ๐-rโ produces a relocatable object as output. This is also known as partial linking ๐งฉ-rdynamicโ okay so this one tells the ELF linker to pass-export-dynamic, but only on targets that actually support it ๐ . It basically shoves every symbol into the dynamic symbol table, not just the ones being used ๐ฆ. You'll want it for somedlopensetups, or if you need backtraces from inside your program ๐.-sโ literally strips all the symbol table and relocation info out of the executable ๐งน clean girl energy.-static,--staticโ on systems that support dynamic linking, this overrides-pieand stops linking with shared libraries ๐ซ. On other systems it does nothing at all ๐.-shared,--sharedโ makes a shared object that you can link with other objects to build an executable โจ. Not every system supports this one ๐ญ. For predictable results, you also have to use the same set of options you compiled with (-fpic,-fPIC, or model suboptions) when you use this linker option.[1]-shared-libgcc,-static-libgccโ on systems that ship libgcc as a shared library, these force the shared or the static version, respectively ๐. If no shared version of libgcc was built when the compiler was configured, these do nothing ๐.
There are a few situations where an app should use the shared libgcc instead of the static one ๐ซถ. The biggest one is when the app wants to throw and catch exceptions across different shared libraries. In that case, every one of those libraries and the app itself should be using the shared libgcc.
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable ๐. C++ programs usually use exceptions, so this is the correct move, bestie.
If you use the GCC driver to make shared libraries instead, they might not always end up linked with the shared libgcc ๐ค. If GCC finds out at configuration time that you have a non-GNU linker, or a GNU linker that doesn't support option --eh-frame-hdr, it links the shared version of libgcc into shared libraries by default. Otherwise it uses the linker's smarts and skips linking with the shared libgcc, so it links the static version by default instead ๐ง . This lets exceptions propagate through those shared libraries without taking on relocation costs at library load time โก.
However, if a library or main executable is supposed to throw or catch exceptions, you must link it with the G++ driver, or use the option -shared-libgcc, so it gets linked with the shared libgcc. Don't skip this one, it's the main character of the whole section ๐
-static-libasanโ when-fsanitize=addressis used to link a program, the GCC driver automatically links against libasan ๐. If libasan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link libasan statically, without necessarily linking other libraries statically ๐ฆ.-static-libtsanโ when-fsanitize=threadis used to link a program, the GCC driver automatically links against libtsan ๐งต. If libtsan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link libtsan statically, without necessarily linking other libraries statically ๐ธ.-static-liblsanโ when-fsanitize=leakis used to link a program, the GCC driver automatically links against liblsan ๐ซง. If liblsan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link liblsan statically, without necessarily linking other libraries statically ๐.-static-libubsanโ when-fsanitize=undefinedis used to link a program, the GCC driver automatically links against libubsan ๐. If libubsan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link libubsan statically, without necessarily linking other libraries statically ๐ง.-static-libstdc++โ when theg++program links a C++ program, it normally links against libstdc++ automatically ๐. If libstdc++ is available as a shared library and-staticisn't used, it links the shared version, and that's normally totally fine ๐. Sometimes though, you want to freeze the version of libstdc++ your program uses without going all the way to a fully static link โ๏ธ. This option tells theg++driver to link libstdc++ statically, without necessarily linking other libraries statically ๐ .-symbolic,--symbolicโ binds references to global symbols when building a shared object ๐. It also warns about any unresolved references (unless you override that with the link editor option-Xlinker -z -Xlinker defs) โ ๏ธ. Only a few systems support this one, so don't be shocked if it's not there ๐.-T scriptโ usesscriptas the linker script ๐. This is supported by most systems using the GNU linker. On some targets, like bare-board targets with no operating system, you might need-Twhen linking so you don't end up with references to undefined symbols ๐ญ.-Xlinker optionโ passesoptionstraight through to the linker ๐. Perfect for system-specific linker options that GCC doesn't recognize.
If you want to pass an option that takes a separate argument, you have to use -Xlinker twice, once for the option and once for the argument ๐. For example, to pass -assert definitions, you write -Xlinker -assert -Xlinker definitions. Writing -Xlinker "-assert definitions" does not work, because that passes the whole string as a single argument, and the linker is not having it ๐.
When you're using the GNU linker, it's usually way more convenient to pass arguments with the option=value syntax instead of as separate arguments โจ. For example, you can write -Xlinker -Map=output.map instead of -Xlinker -Map -Xlinker output.map. Other linkers might not support this syntax for command-line options ๐คทโโ๏ธ.
-Wl,option,--for-linker=option,--for-linker optionโ passesoptionto the linker too ๐ง. Ifoptionhas commas in it, it gets split into multiple options at those commas. This is how you give an argument to the option:-Wl,-Map,output.mappasses-Map output.mapto the linker ๐บ๏ธ. With the GNU linker you can also get the same effect with-Wl,-Map=output.map๐.
NOTE: In Ubuntu 8.10 and later versions, for LDFLAGS, the option-Wl,-z,relrois used. To disable it, use-Wl,-z,norelro๐ heads up bestie.
-u symbol,--force-link=symbol,--force-link symbolโ pretends the symbolsymbolis undefined, which forces linking of library modules that define it ๐งฒ. You can use-umultiple times with different symbols to force loading of additional library modules ๐.-Tbss=addrโ passed straight through to the linker without GCC touching it ๐.-Tdata=addrโ passed straight through to the linker without GCC touching it ๐.-Ttext=addrโ passed straight through to the linker without GCC touching it ๐.-Nโ passed straight through to the linker without GCC touching it ๐.-nโ passed straight through to the linker without GCC touching it ๐.-tโ passed straight through to the linker without GCC touching it ๐.-Zโ passed straight through to the linker without GCC touching it ๐.-z keywordโ passed straight through to the linker without GCC touching it ๐.
These are all passed through to the linker without GCC interpreting them ๐ซถ. Check your linker documentation for what they actually mean, because GCC isn't going to explain them for you ๐.
โจ Options for Directory Search โจ
These options tell GCC which directories to search for header files, libraries and parts of the compiler ๐๏ธ:
-I dirโ addsdirto the list of directories searched for header files during preprocessing ๐.--include-directoryis an alias for-I, while--include-directory-afteris an alias for-idirafter. Ifdirbegins with=or$SYSROOT, then the=or$SYSROOTgets replaced by the sysroot prefix; see--sysrootand-isysroot๐ธ.-iquote dirโ directories specified this way only apply to the quote form of the directive,#include "file"๐ฌ.-isystem dirโ applies to lookup for both#include "file"and#include <file>directives ๐.-idirafter dirโ applies to lookup for both#include "file"and#include <file>directives ๐.--include-directory-after=dirโ alias for-idirafter๐ช.--include-directory-after dirโ alias for-idirafter๐ช.--include-directory=dirโ alias for-I๐ช.--include-directory dirโ alias for-I๐ช.
You can use any number or combination of these on the command line to search for headers in several directories at once ๐งฉ. The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first.
- For the quote form of the include directive, the directories specified by
-iquoteoptions are searched in left-to-right order, as they appear on the command line. - Directories specified with
-Ioptions are scanned in left-to-right order. - Directories specified with
-isystemoptions are scanned in left-to-right order. - Standard system directories are scanned.
- Directories specified with
-idirafteroptions are scanned in left-to-right order.
You can use -I to override a system header file and swap in your own version, since these directories get searched before the standard system header directories ๐. But don't use this option to add directories that hold vendor-supplied system headers. Use -isystem for those ๐
โโ๏ธ.
The -isystem and -idirafter options also mark the directory as a system directory, so it gets the same special treatment as the standard system directories ๐.
If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option gets ignored ๐. The directory is still searched, but as a system directory at its normal position in the system include chain. This keeps GCC's procedure for fixing buggy system headers and the ordering for the #include_next directive from getting changed by accident ๐ก๏ธ. If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options ๐ซฃ.
-I-,--include-barrierโ splits the include path ๐ง. This option has been deprecated ๐ญ. Please use-iquoteinstead for the-Idirectories that come before-I-, and remove the-I-option โจ.
Okay so the -I- thing is kinda sneaky ๐ Any directories you pass with -I before -I- only get checked for "#include "file"" lookups. They are NOT searched for #include <file>. But if you add -I dirs after the -I-, those get searched for all #include directives ๐
And on top of that, -I- stops the directory of the current file from being the first place searched for #include "file" ๐ฆ There is no way to undo that effect of -I-, so use it wisely, bestie.
-iprefix prefix,--include-prefix=prefix,--include-prefix prefixโ Setsprefixas the prefix for any later-iwithprefixoptions ๐ธ If the prefix is a directory, make sure you include the final/.-iwithprefix dir,-iwithprefixbefore dir,--include-with-prefix=prefix,--include-with-prefix prefix,--include-with-prefix-after=prefix,--include-with-prefix-after prefix,--include-with-prefix-before=prefix,--include-with-prefix-before prefixโ Tacksdironto the prefix you set earlier with-iprefix, then adds the result to the include search path โจ-iwithprefixbeforeputs it in the same spot-Iwould, and-iwithprefixputs it where-idirafterwould.
--include-with-prefix and --include-with-prefix-after are both aliases for -iwithprefix, and --include-with-prefix-before is an alias for -iwithprefixbefore ๐ง
-isysroot dirโ This one is like--sysroot, but it only applies to header files ๐ The exception is Darwin targets, where it applies to both header files and libraries. Check the--sysrootoption for more info.-imultilib dirโ Usesdiras a subdirectory of the directory holding target-specific C++ headers ๐-imultiarch dirโ Usesdiras a subdirectory of the directory holding architecture-specific C++ headers ๐-nostdinc,--no-standard-includesโ Skips the standard system directories when looking for headers ๐ Only the dirs you explicitly pass with-I,-iquote,-isystem, and/or-idirafterget searched, plus the directory of the current file if it applies.-nostdinc++โ Skips the C++-specific standard directories, but still searches the other standard ones ๐ (This one is used when building the C++ library.)--embed-dir=dir,--embed-directory=dir,--embed-directory dirโ Addsdirto the list of directories searched for the#embedpreprocessing directive or the__has_embedmacro ๐ There are no default directories for#embed.
If dir begins with = or $SYSROOT, that = or $SYSROOT gets swapped out for the sysroot prefix. See --sysroot and -isysroot for the deets.
-iplugindir=dirโ Sets the directory to search for plugins that get passed with-fplugin=nameinstead of-fplugin=path/name.so๐ฅ
๐ This option is not meant to be used by you, the user. It's only passed by the driver.
-Ldir,--library-directory=dir,--library-directory dirโ Adds directorydirto the list of directories searched for-l๐ฆ-Bprefix,--prefix=prefix,--prefix prefixโ This one tells the compiler where to find its own executables, libraries, include files, and data files ๐ธ
The compiler driver runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for each program it runs, both with and without machine/version/ for the matching target machine and compiler version.
For each subprogram, the driver tries the -B prefix first, if you gave one. If that name isn't found, or if -B isn't specified, it tries two standard prefixes, /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those turns up a file, the unmodified program name gets searched for in the directories listed in your PATH environment variable.
The compiler checks whether the path given by -B is a directory, and if needed it adds a directory separator character to the end of the path ๐ซถ
-B prefixes that effectively name directories also apply to libraries in the linker, since the compiler translates these options into -L options for the linker ๐ They also apply to include files in the preprocessor, since the compiler translates them into -isystem options for the preprocessor. In that case, the compiler appends include to the prefix.
The runtime support file libgcc.a can also be searched for using the -B prefix, if needed. If it isn't found there, the two standard prefixes above get tried, and that's it. If it still isn't found by those means, the file gets left out of the link.
Another way to specify a prefix, kinda like the -B prefix, is the environment variable GCC_EXEC_PREFIX โจ
As a special kludge, if the path given by -B is [dir/]stageN/, where N is a number from 0 to 9, it gets replaced by [dir/]include. This is there to help with boot-strapping the compiler ๐ค
-no-canonical-prefixes,--no-canonical-prefixesโ Stops the compiler from expanding symbolic links, resolving/../or/./, or making the path absolute when it generates a relative prefix ๐ง--sysroot=dir,--sysroot dirโ Usesdiras the logical root directory for headers and libraries ๐ For example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it searchesdir/usr/includeanddir/usr/libinstead.
If you use both this option and -isysroot, then --sysroot applies to libraries, and -isysroot applies to header files.
The GNU linker (beginning with version 2.16) has the support this option needs. If your linker doesn't support it, the header file side of --sysroot still works, but the library side doesn't ๐
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory given with--sysroot, depending on the other options you used. So headers might be found indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off that suffix ๐
๐ Options for use with Picolibc ๐
These options control compilation and linking when you're using picolibc ๐
--oslib=libraryโ Searches the library namedlibraryafter the C library, so symbols the C library leaves undefined can be defined by this library โจ The C library, libgcc, and this library get placed between--start-groupand--end-groupflags, so each one can refer to symbols in the others. For many targets, picolibc provides a semihost variant (specified with--oslib=semihost) that gives you enough basic OS functionality for console and file I/O when running in an emulator or using an in-circuit debugger.--crt0=[none|minimal|hosted|semihost]โ Replaces the defaultcrt0.oname withcrt0-variant.o๐ฆ Thenonevariant gives you no startup code at all, so you can supply your own.minimaldoes basic memory setup but doesn't invoke any constructors. When no-crt0option is given, the default initialization code adds calls to all constructors.hostedadds a call toexitwhenmainreturns.semihostreads a command line parameter supplied through the semihosting interface, splits it into arguments at whitespace boundaries, and passes the resulting array of strings tomaininargcandargv. On some targets, including aarch64, arc, arm, loongarch, m68k, riscv, super-h and x86,semihostalso traps hardware exceptions and prints information to the console. Note that--crt0=semihostdepends on APIs provided by--oslib=semihostโ ๏ธ--printf=[d|f|l|i|m]โ Picks the printf variant ๐จ๏ธ Picolibc has five printf variants, and each one offers less functionality but also smaller code size.dis the default and offers full C17 and POSIX.1-2024 conformance.fhas the same feature set, but supportsfloatvalues instead ofdouble, passed using theprintf_floatmacro.ldrops all floating point and POSIX positional parameter support.ilimits integers to those no larger thanlong.mremoves support for most formatting options, including width and precision. The formats and arguments still get parsed correctly, but the output doesn't respect those parameters ๐--scanf=[d|f|l|i|m]โ Picks the scanf variant ๐ Picolibc has five scanf variants with the same deal: less functionality and smaller code as you go down.dis the default and offers full C17 and POSIX.1-2024 conformance.fremoves support fordoublevalues.ldrops all floating point support.ilimits integers to those no larger thanlong.mremoves support for%[conversion specifiers.
๐ Options for Code Generation Conventions ๐
These machine-independent options control the interface conventions used in code generation ๐
Most of them have both positive and negative forms. The negative form of -ffoo is -fno-foo. In the list below, only one of the forms is listed, the one that is not the default. You can figure out the other form by either removing no- or adding it ๐ง
-fstack-reuse=reuse-levelโ Controls stack space reuse for user-declared local/auto variables and compiler-generated temporaries ๐reuse_levelcan beall,named_vars, ornone.allenables stack reuse for all local variables and temporaries.named_varsenables reuse only for user-defined local variables that have names.nonedisables stack reuse completely. The default value isall.
This option is needed when the program extends the lifetime of a scoped local variable or a compiler-generated temporary beyond the end point the language defines. When a variable's lifetime ends, and the variable lives in memory, the optimizing compiler is free to reuse its stack space for other temporaries or scoped local variables whose live range doesn't overlap with it.
๐ Legacy code that extends local lifetime is likely to break with the stack reuse optimization.
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example, because one spooky pointer is never enough ๐ป๐
struct A
{
A(int k) : i(k), j(k) { }
int i;
int j;
};
A *ap;
void foo(const A& ar)
{
ap = &ar;
}
void bar()
{
foo(A(10)); // temp object's lifetime ends when foo returns
{
A a(20);
....
}
ap->i+= 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
}
Okay so the lifetime of a compiler generated temporary is well defined by the C++ standard ๐โจ When that lifetime ends and the temporary lives in memory, the optimizing compiler is allowed to reuse its stack space for other temporaries or scoped local variables whose live range does not overlap with it. ๐ฆ But ngl, some legacy code relies on older compilers where temporaries' stack space was never reused, so this aggressive stack reuse can lead to runtime errors ๐ This option is used to control that temporary stack reuse optimization.
-ftrapvโ ๐จ This one makes the compiler generate traps for signed overflow on addition, subtraction and multiplication.-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line means-fwrapvends up being the one that's effective. Only the options that are actually active get to override, so-ftrapv -fwrapv -fno-wrapvmakes-ftrapvthe effective one. ๐-fwrapvโ ๐ธ This tells the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation. It enables some optimizations and disables others, so it's giving trade-off energy. The same override drama applies here too:-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line results in-fwrapvbeing effective, and-ftrapv -fwrapv -fno-wrapvresults in-ftrapvbeing effective, since only active options override.-fwrapv-pointerโ ๐ง Same vibe, but for pointers. This tells the compiler to assume that pointer arithmetic overflow on addition and subtraction wraps around using twos-complement representation. It disables some optimizations that assume pointer overflow is invalid.-fstrict-overflowโ ๐ This one implies-fno-wrapv -fno-wrapv-pointer, and when negated it implies-fwrapv -fwrapv-pointer.-fexceptionsโ ๐ฅ Enables exception handling and generates the extra code needed to propagate exceptions. On some targets this implies GCC generates frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution. If you don't specify this option, GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that do not. You may still need to enable it when compiling C code that has to interoperate properly with exception handlers written in C++. You may also wish to disable it if you're compiling older C++ programs that don't use exception handling.-fnon-call-exceptionsโ ๐ Generates code that allows trapping instructions to throw exceptions. ngl this needs platform-specific runtime support that doesn't exist everywhere. It only lets trapping instructions (memory references or floating-point instructions) throw exceptions. Exceptions cannot be thrown from arbitrary signal handlers such as "SIGALRM". This enables-fexceptions.-fdelete-dead-exceptionsโ ๐งน Instructions that may throw exceptions but don't otherwise contribute to the execution of the program can be optimized away. This does not affect calls to functions, except those with the "pure" or "const" attributes. This option is enabled by default for the Ada and C++ compilers, as permitted by the language specifications. Optimization passes that cause dead exceptions to be removed are enabled independently at different optimization levels.-funwind-tablesโ ๐ฆ This is similar to-fexceptions, except it just generates any needed static data and doesn't affect the generated code in any other way. You normally don't need to enable it yourself, because a language processor that needs this handling enables it on your behalf.-fasynchronous-unwind-tablesโ โญ Generates an unwind table in DWARF format, if the target machine supports it. The table is exact at each instruction boundary, so it can be used for stack unwinding from asynchronous events (such as a debugger or garbage collector).-fno-gnu-uniqueโ ๐ซถ On systems with a recent GNU assembler and C library, the C++ compiler uses the "STB_GNU_UNIQUE" binding to make sure that definitions of template static data members and static local variables in inline functions are unique, even in the presence of "RTLD_LOCAL". This is necessary to avoid problems with a library used by two different "RTLD_LOCAL" plugins that depend on a definition in one of them and therefore disagree with the other about the binding of the symbol. But this causes "dlclose" to be ignored for affected DSOs. If your program relies on reinitializing a DSO via "dlclose" and "dlopen", you can use-fno-gnu-unique.-fpcc-struct-returnโ ๐ Returns "short" "struct" and "union" values in memory, like longer ones, rather than in registers. This convention is less efficient, but it has the advantage of allowing intercallability between GCC-compiled files and files compiled with other compilers, particularly the Portable C Compiler (pcc).
The precise convention for returning structures in memory depends on the target configuration macros. Short structures and unions are those whose size and alignment match that of some integer type.
Warning: code compiled with the-fpcc-struct-returnswitch is not binary compatible with code compiled with the-freg-struct-returnswitch. Use it to conform to a non-default application binary interface. ๐
-freg-struct-returnโ ๐ Returns "struct" and "union" values in registers when possible. This is more efficient for small structures than-fpcc-struct-return.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever convention is standard for the target. If there is no standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases, we can choose the standard, and we chose the more efficient register return alternative.
Warning: code compiled with the-freg-struct-returnswitch is not binary compatible with code compiled with the-fpcc-struct-returnswitch. Use it to conform to a non-default application binary interface. ๐ญ
-fshort-enumsโ ๐ Allocates to an "enum" type only as many bytes as it needs for the declared range of possible values. Specifically, the "enum" type is equivalent to the smallest integer type that has enough room. This option has no effect for an enumeration type with a fixed underlying type.
Warning: the -fshort-enums switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. โ ๏ธ
-fshort-wcharโ ๐ธ Overrides the underlying type for "wchar_t" to be "short unsigned int" instead of the default for the target. This option is useful for building programs to run under WINE.
Warning: the -fshort-wchar switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. ๐
โโ๏ธ
-fcommonโ ๐ง In C code, this option controls the placement of global variables defined without an initializer, known as tentative definitions in the C standard. Tentative definitions are distinct from declarations of a variable with the "extern" keyword, which do not allocate storage.
The default is -fno-common, which means the compiler places uninitialized global variables in the BSS section of the object file. This inhibits the merging of tentative definitions by the linker, so you get a multiple-definition error if the same variable is accidentally defined in more than one compilation unit. ๐ซ
The -fcommon option places uninitialized global variables in a common block. This allows the linker to resolve all tentative definitions of the same variable in different compilation units to the same object, or to a non-tentative definition. This behavior is inconsistent with C++, and on many targets it implies a speed and code size penalty on global variable references. It is mainly useful for enabling legacy code to link without errors. ๐งฑ
-fno-ident,-Qy,-Qnโ ๐คซ-fno-identsuppresses the emission of.identassembler directives and causes the "#ident" preprocessor directive to be ignored.-Qyand-Qnare obsolete synonyms for-fidentand-fno-ident, respectively.-finhibit-size-directiveโ โ๏ธ Don't output a.sizeassembler directive, or anything else that would cause trouble if the function is split in the middle and the two halves are placed at locations far apart in memory. This option is used when compiling crtstuff.c; you should not need to use it for anything else.-fverbose-asmโ ๐ Puts extra commentary information in the generated assembly code to make it more readable. This option is generally only of use to people who actually need to read the generated assembly code (perhaps while debugging the compiler itself).
-fno-verbose-asm, the default, causes the extra information to be omitted, and it's useful when comparing two assembler files. ๐ฆ
The added comments include:
- information on the compiler version and command-line options,
- the source code lines associated with the assembly instructions, in the form
FILENAME:LINENUMBER:CONTENT OF LINE,
...which high-level expressions line up with the various assembly instruction operands ๐
Okay so say we've got this C file ๐ธ
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
Now we compile it to (x86_64) assembly with -S and shove the result straight to stdout with -o - ๐ง
gcc -S test.c -fverbose-asm -Os -o -
and you get something like this โจ
.file "test.c"
# GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
[...snip...]
# options passed:
[...snip...]
.text
.globl test
.type test, @function
test:
.LFB0:
.cfi_startproc
# test.c:4: int total = 0;
xorl %eax, %eax # <retval>
# test.c:6: for (i = 0; i < n; i++)
xorl %edx, %edx # i
.L2:
# test.c:6: for (i = 0; i < n; i++)
cmpl %edi, %edx # n, i
jge .L5 #,
# test.c:7: total += i * i;
movl %edx, %ecx # i, tmp92
imull %edx, %ecx # i, tmp92
# test.c:6: for (i = 0; i < n; i++)
incl %edx # i
# test.c:7: total += i * i;
addl %ecx, %eax # tmp92, <retval>
jmp .L2 #
.L5:
# test.c:10: }
ret
.cfi_endproc
.LFE0:
.size test, .-test
.ident "GCC: (GNU) 7.0.0 20160809 (experimental)"
.section .note.GNU-stack,"",@progbits
The comments are for humans, not machines ๐ so the exact format of the comments is subject to change, bestie.
-frecord-gcc-switches ๐
This switch causes the command line used to invoke the compiler to be recorded into the object file that is being created. It's only implemented on some targets, and the exact format of the recording is target and binary file format dependent, but it usually takes the form of a section containing ASCII text. This one is related to -fverbose-asm, but that switch only records info in the assembler output file as comments, so it never reaches the object file ๐ญ See also -grecord-gcc-switches for another way of storing compiler options into the object file.
-fpic ๐ฆ
Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts (the dynamic loader is not part of GCC; it is part of the operating system). If the GOT size for the linked executable exceeds a machine-specific maximum size, you get an error message from the linker indicating that -fpic does not work. In that case, recompile with -fPIC instead. (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit.)
Position-independent code requires special support, and therefore works only on certain machines. For the x86, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent.
When this flag is set, the macros "__pic__" and "__PIC__" are defined to 1.
-fPIC ๐
If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. This option makes a difference on AArch64, m68k, PowerPC and SPARC.
Position-independent code requires special support, and therefore works only on certain machines.
When this flag is set, the macros "__pic__" and "__PIC__" are defined to 2.
-fpie, -fPIE ๐
These options are similar to -fpic and -fPIC, but the generated position-independent code can only be linked into executables. Usually these options are used to compile code that will be linked using the -pie GCC option.
-fpie and -fPIE both define the macros "__pie__" and "__PIE__". The macros have the value 1 for -fpie and 2 for -fPIE.
-fno-plt ๐
Do not use the PLT for external function calls in position-independent code. Instead, load the callee address at call sites from the GOT and branch to it. This leads to more efficient code by eliminating PLT stubs and exposing GOT loads to optimizations. On architectures such as 32-bit x86 where PLT stubs expect the GOT pointer in a specific register, this gives more register allocation freedom to the compiler. Lazy binding requires use of the PLT; with -fno-plt all external symbols are resolved at load time.
Alternatively, the function attribute "noplt" can be used to avoid calls through the PLT for specific external functions.
In position-dependent code, a few targets also convert calls to functions that are marked to not use the PLT to use the GOT instead.
-fno-jump-tables ๐
Do not use jump tables for switch statements even where it would be more efficient than other code generation strategies. This option is of use in conjunction with -fpic or -fPIC for building code that forms part of a dynamic linker and cannot reference the address of a jump table. On some targets, jump tables do not require a GOT and this option is not needed.
-fno-bit-tests ๐
Do not use bit tests for switch statements even where it would be more efficient than other code generation strategies.
-ffixed-reg ๐ง
Treat the register named reg as a fixed register; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role).
reg must be the name of a register. The register names accepted are machine-specific and are defined in the "REGISTER_NAMES" macro in the machine description macro file.
This flag does not have a negative form, because it specifies a three-way choice.
-fcall-used-reg โจ
Treat the register named reg as an allocable register that is clobbered by function calls. It may be allocated for temporaries or variables that do not live across a call. Functions compiled this way do not save and restore the register reg.
It is an error to use this flag with the frame pointer or stack pointer. Use of this flag for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results.
This flag does not have a negative form, because it specifies a three-way choice.
-fcall-saved-reg ๐ซถ
Treat the register named reg as an allocable register saved by functions. It may be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restore the register reg if they use it.
It is an error to use this flag with the frame pointer or stack pointer. Use of this flag for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results.
A different sort of disaster results from the use of this flag for a register in which function values may be returned.
This flag does not have a negative form, because it specifies a three-way choice.
-fpack-struct[=n] ๐ธ
Without a value specified, pack all structure members together without holes. When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment (that is, objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location).
Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it makes the code suboptimal. Use it to conform to a non-default application binary interface.
-fleading-underscore ๐ฅ
This option and its counterpart, -fno-leading-underscore, forcibly change the way C symbols are represented in the object file. One use is to help link with legacy assembly code.
Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch.
-ftls-model=model ๐งโโ๏ธ
Alter the thread-local storage model to be used. The model argument should be one of global-dynamic, local-dynamic, initial-exec or local-exec. Note that the choice is subject to optimization: the compiler may use a more efficient model for symbols not visible outside of the translation unit, or if -fpic is not given on the command line.
The default without -fpic is initial-exec; with -fpic the default is global-dynamic.
-ftrampolines ๐ฆ
For targets that normally need trampolines for nested functions, always generate them instead of using descriptors. Otherwise, for targets that do not need them, like for example HP-PA or IA-64, do nothing.
A trampoline is a small piece of code that is created at run time on the stack when the address of a nested function is taken, and is used to call the nested function indirectly. Therefore, it requires the stack to be made executable in order for the program to work properly.
-fno-trampolinesis enabled by default on a language by language basis to let the compiler avoid generating them, if it computes that this is safe, and replace them with descriptors. Descriptors are made up of data only, but the generated code must be prepared to deal with them. As of this writing,-fno-trampolinesis enabled by default only for Ada. ๐
Okay so, bestie, this is the big catch ๐จ: code compiled with -ftrampolines and code compiled with -fno-trampolines are not binary compatible if nested functions are present ๐. So this option has to be used on a program-wide basis and handled with extreme care ๐ซถ. No mixing and matching, periodt.
For languages other than Ada, the -ftrampolines and -fno-trampolines options currently have no effect ๐. Trampolines are always generated on platforms that need them for nested functions, no notes.
๐ฆ -ftrampoline-impl=[stack|heap]
By default, trampolines live on the stack ๐ฅ. BUT some platforms, like the Apple M1, don't allow an executable stack ๐ค. So -ftrampoline-impl=heap makes GCC generate calls to __gcc_nested_func_ptr_created and __gcc_nested_func_ptr_deleted to allocate and deallocate trampoline space on the executable heap โจ. Those functions live in libgcc, and they only show up on specific targets: x86_64 Darwin, x86_64 and aarch64 Linux.
PLEASE NOTE: Heap trampolines are not guaranteed to be correctly deallocated if yousetjmp, instantiate nested functions, and thenlongjmpback to a state prior to having allocated those nested functions. โ ๏ธ
๐ -fvisibility=[default|internal|hidden|protected]
This sets the default ELF image symbol visibility to whatever you pick. Every symbol gets marked with it unless the code overrides it ๐ . It can seriously speed up linking and load times for shared object libraries ๐, makes the code more optimized โจ, gives you near-perfect API export, and stops symbol clashes ๐ โโ๏ธ. Strongly recommend using it in any shared objects you distribute.
Despite the name, default always means public, i.e., available to be linked against from outside the shared object ๐. protected and internal are pretty useless in real-world usage, so the only other commonly used option is hidden ๐ซ . If you don't specify -fvisibility, the default is default, i.e., every symbol is public ๐ข.
Want the deets? Check out "How To Write Shared Libraries" by Ulrich Drepper, found at https://www.akkadia.org/drepper/ ๐. BUT, and this is the big brain move ๐ง , a better trick than marking stuff hidden when the default is public is to flip it: make the default hidden and mark the public things as public. That's the norm with DLLs on Windows. With -fvisibility=hidden plus __attribute__ ((visibility("default"))) instead of __declspec(dllexport), you get almost identical semantics with identical syntax ๐คฏ. Huge win for cross-platform projects ๐ธ.
Adding visibility to old code? #pragma GCC visibility is your friend ๐ง. You wrap the declarations you care about with, for example, #pragma GCC visibility push(hidden) and #pragma GCC visibility pop. Real talk: visibility is part of the API interface contract, so all new code should specify visibility whenever it isn't the default ๐
. Anything only meant for use within the local DSO should be marked hidden explicitly, so as to avoid PLT indirection overheads โก. It also makes the code way more readable and self-documenting ๐. And thanks to ISO C++ specification requirements, operator new and operator delete must always be default visibility ๐.
Heads up ๐: headers from outside your project, especially system headers and headers from any other library you use, might not be expecting to be compiled with visibility other than the default. You might need to explicitly say #pragma GCC visibility push(default) before including any such headers ๐ซถ.
extern declarations aren't affected by -fvisibility, so tons of code can be recompiled with -fvisibility=hidden with zero modifications โจ. BUT calls to extern functions with no explicit visibility go through the PLT. So it's more effective to use __attribute ((visibility)) and/or #pragma GCC visibility to tell the compiler which extern declarations should be treated as hidden ๐ฏ.
Also, -fvisibility DOES affect C++ vague linkage entities ๐ง. For example, an exception class that is going to be thrown between DSOs must be explicitly marked with default visibility, so the type_info nodes get unified between the DSOs ๐ค.
If you want the whole tea on these techniques, their benefits, and how to use them, peep https://gcc.gnu.org/wiki/Visibility ๐ต.
๐ -fstrict-volatile-bitfields
Use this when accesses to volatile bit-fields (or other structure fields, although the compiler usually honors those types anyway) should be a single access at the width of the field's type, aligned to a natural alignment if possible ๐. Example: targets with memory-mapped peripheral registers might need every access to be 16 bits wide. With this flag, you declare all the peripheral bit-fields as unsigned short (assuming short is 16 bits on those targets) to force GCC into 16-bit accesses instead of a maybe-more-efficient 32-bit one ๐ง.
If this option is disabled, the compiler just grabs the most efficient instruction ๐โโ๏ธ. In the example above, that could be a 32-bit load instruction, even though it touches bytes that don't contain any portion of the bit-field, or memory-mapped registers unrelated to the one being updated ๐ฌ.
Sometimes it just isn't possible, like when the packed attribute is applied to a structure field. Then there's no single read or write that is correctly aligned for the target machine ๐. In that case GCC falls back to generating multiple accesses, instead of code that will fault or truncate the result at run time ๐.
Note: Due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members. So it's recommended to define all bits of the field's type as bit-field members ๐.
The default value of this option is determined by the application binary interface for the target processor ๐งฉ.
๐ -fsync-libcalls
This one controls whether any out-of-line instance of the __sync family of functions may be used to implement the C++11 __atomic family of functions ๐งต.
It's enabled by default, so the only useful form of the option is -fno-sync-libcalls ๐
. This option is used in the implementation of the libatomic runtime library ๐งช.
๐๏ธ -fzero-init-padding-bits=value
This guarantees zero initialization of padding bits in automatic variable initializers ๐. Some languages already promise it in certain cases, like C23 when using empty initializers ({}), or C++ when using zero-initialization, or C guaranteeing that fields not specified in an initializer have their padding bits zero initialized ๐งธ. This option lets you change when padding bits in initializers are guaranteed to be zero initialized. The default is -fzero-init-padding-bits=standard, which makes no further guarantees than the corresponding standard. Like:
struct A { char a; unsigned long long b; char c; };
union B { char a; unsigned long long b; };
struct A a = {}; // C23 guarantees padding bits are zero.
struct A b = { 1, 2, 3 }; // No guarantees.
union B c = {}; // C23 guarantees padding bits are zero.
union B d = { 1 }; // No guarantees.
-fzero-init-padding-bits=unions goes a step further and guarantees zero initialization of padding bits in unions, on top of what the standards promise ๐. That applies if the initializer of a union is empty, which zeroes ALL the bits of the union. It also applies if the initialized member of the union is smaller than the size of the union, which zeroes the padding bits outside the initialized member. This was the GCC behavior before GCC 15. In the example above, it guarantees zero initialization of the last sizeof (unsigned long long) - 1 bytes in the union ๐ฐ.
-fzero-init-padding-bits=all goes even further ๐ and also guarantees zero initialization of padding bits of other aggregates. So that covers the padding in between b.a and b.b (if any), and the tail padding in the structure (if any) ๐ธ.
NOTE: In Ubuntu 25.10 and later versions,-fzero-init-padding-bits=allis enabled by default for C, C++, ObjC, ObjC++, unless-fzero-init-padding-bits=standardis found ๐.
โจ GCC Developer Options โจ
This part is for the GCC developers out there ๐งโ๐ป. These are command-line options mainly for compiler testing and digging into compiler bugs and compile-time performance problems ๐. That includes options that spit out debug dumps at various points in the compilation, print stats like memory use and execution time, and print info about GCC's configuration, like where it searches for libraries ๐. Honestly, you should rarely need these for ordinary compiling and linking, so don't go wild ๐.
A lot of developer options that make GCC dump output to a file take an optional =filename suffix ๐. You can say stdout or - to dump to standard output, and stderr for standard error ๐ฅ๏ธ.
If you leave out =filename, GCC builds a default dump file name by sticking together: the base dump file name, a pass number, a phase letter, and the pass name ๐งฉ. The base dump file name is the output file name the compiler produced, if you explicitly specified one and it's not an executable. Otherwise it's the source file name. The pass number comes from the order passes get registered with the compiler's pass manager. That's usually the same as the order of execution, BUT passes registered by plugins, target-specific passes, or passes that get registered late are numbered higher than the pass named final, even if they run earlier ๐คช. The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree). And the files get created in the directory of the output file ๐โจ.
-fcallgraph-info,-fcallgraph-info=MARKERSโ okay bestie, this one makes the compiler spit out callgraph info for your program ๐ฆ, one file per object file. It comes out in the common VCG format ๐ . You can add extra decorations to the per-node and/or per-edge info by passing a comma-separated list of markers โจ. Thesumarker adds stack usage info, and it's the same as-fstack-usage๐ฅ. Thedamarker adds info about dynamically allocated objects.- When you compile with
-flto, no callgraph info comes out alongside the object file ๐. At LTO link time,-fcallgraph-infomay generate multiple callgraph info files right next to the intermediate LTO output files.
- When you compile with
-dletters,--dump=letters,--dump letters,-fdump-rtl-pass,-fdump-rtl-pass-options,-fdump-rtl-pass-options=filenameโ this is the debugging-dump family ๐. It makes dumps during compilation at the times you pick with-dletters, or by pass when you go with-fdump-rtl. It's how you debug the RTL-based passes of the compiler, and it's giving main character energy ๐.- Some
-dlettersswitches mean something different when you use-Efor preprocessing, so watch out ๐. - The
-optionsform gives you way more control over the details of the dump. See-fdump-treefor the deets ๐ง.
- Some
Here are the actual command-line options that follow these patterns, and what each one does:
-fdump-rtl-alignmentsโ dumps after branch alignments have been computed ๐.-fdump-rtl-asmconsโ dumps after fixing RTL statements that have unsatisfied in/out constraints.-fdump-rtl-auto_inc_decโ dumps after auto-inc-dec discovery. This pass only runs on architectures that have auto inc or auto dec instructions.-fdump-rtl-barriersโ dumps after cleaning up the barrier instructions.-fdump-rtl-bbpartโ dumps after partitioning hot and cold basic blocks ๐ฅ๐ง.-fdump-rtl-bbroโ dumps after block reordering.-fdump-rtl-btl1,-fdump-rtl-btl2โ these enable dumping after the two branch target load optimization passes.-fdump-rtl-bypassโ dumps after jump bypassing and control flow optimizations.-fdump-rtl-combineโ dumps after the RTL instruction combination pass.-fdump-rtl-compgotosโ dumps after duplicating the computed gotos.-fdump-rtl-ce1,-fdump-rtl-ce2,-fdump-rtl-ce3โ these enable dumping after the three if conversion passes.-fdump-rtl-cprop_hardregโ dumps after hard register copy propagation.-fdump-rtl-csaโ dumps after combining stack adjustments.-fdump-rtl-cse1,-fdump-rtl-cse2โ these enable dumping after the two common subexpression elimination passes.-fdump-rtl-dceโ dumps after the standalone dead code elimination passes.-fdump-rtl-dbrโ dumps after delayed branch scheduling.-fdump-rtl-dce1,-fdump-rtl-dce2โ these enable dumping after the two dead store elimination passes.-fdump-rtl-ehโ dumps after finalization of EH handling code.-fdump-rtl-eh_rangesโ dumps after conversion of EH handling range regions.-fdump-rtl-expandโ dumps after RTL generation.-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ these enable dumping after the two forward propagation passes.-fdump-rtl-gcse1,-fdump-rtl-gcse2โ these enable dumping after global common subexpression elimination.-fdump-rtl-init-regsโ dumps after the initialization of the registers.-fdump-rtl-initvalsโ dumps after the computation of the initial value sets.-fdump-rtl-into_cfglayoutโ dumps after converting to cfglayout mode.-fdump-rtl-iraโ dumps after iterated register allocation.-fdump-rtl-jumpโ dumps after the second jump optimization.-fdump-rtl-loop2โ enables dumping after the RTL loop optimization passes.-fdump-rtl-machโ dumps after performing the machine dependent reorganization pass, if that pass exists.-fdump-rtl-mode_swโ dumps after removing redundant mode switches.-fdump-rtl-rnregโ dumps after register renumbering.-fdump-rtl-outof_cfglayoutโ dumps after converting from cfglayout mode.-fdump-rtl-peephole2โ dumps after the peephole pass.-fdump-rtl-postreloadโ dumps after post-reload optimizations.-fdump-rtl-pro_and_epilogueโ dumps after generating the function prologues and epilogues.-fdump-rtl-sched1,-fdump-rtl-sched2โ these enable dumping after the basic block scheduling passes.-fdump-rtl-reeโ dumps after sign/zero extension elimination.-fdump-rtl-seqabstrโ dumps after common sequence discovery.-fdump-rtl-shortenโ dumps after shortening branches.-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ these enable dumping after five rounds of instruction splitting ๐ช.-fdump-rtl-smsโ dumps after modulo scheduling. This pass only runs on some architectures.-fdump-rtl-stackโ dumps after converting GCC's "flat register file" registers to the x87's stack-like registers. This pass only runs on x86 variants.-fdump-rtl-subreg1,-fdump-rtl-subreg2โ these enable dumping after the two subreg expansion passes.-fdump-rtl-vartrackโ dumps after variable tracking.-fdump-rtl-vregsโ dumps after converting virtual registers to hard registers.-fdump-rtl-webโ dumps after live range splitting.-fdump-rtl-regclass,-fdump-rtl-subregs_of_mode_init,-fdump-rtl-subregs_of_mode_finish,-fdump-rtl-dfinit,-fdump-rtl-dfinishโ these are defined but always produce empty files ๐ซ .-da,--dump=a,-fdump-rtl-allโ produce all the dumps listed above ๐.-dA,--dump=Aโ annotate the assembler output with miscellaneous debugging information.-dD,--dump=Dโ dump all macro definitions at the end of preprocessing, in addition to the normal output.-dH,--dump=Hโ produce a core dump whenever an error occurs ๐.-dp,--dump=pโ annotate the assembler output with a comment indicating which pattern and alternative is used. The length and cost of each instruction get printed too.-dP,--dump=Pโ dump the RTL in the assembler output as a comment before each instruction. This also turns on-dpannotation.-dx,--dump=xโ just generate RTL for a function instead of compiling it. This is usually used with-fdump-rtl-expand๐ง.
-fdump-debugโ dumps the debugging information generated during the debug generation phase ๐.-fdump-earlydebugโ dumps the debugging information generated during the early debug generation phase.-fdump-noaddrโ when you're doing debugging dumps, this suppresses address output. That makes it way more feasible todiffyour dumps across compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations ๐ง .-freport-bugโ if an internal compiler error (ICE) happens, this collects and dumps debug info into a temporary file ๐จ.-fdump-unnumberedโ when you're doing debugging dumps, this suppresses instruction numbers and address output. That makes it more feasible todiffyour dumps for compiler invocations with different options, especially with and without-g๐ซถ.-fdump-unnumbered-linksโ when you're doing debugging dumps (see the-doption above), this suppresses instruction numbers for the links to the previous and next instructions in a sequence.-fdump-internal-locationsโ dumps detailed info about GCC's internal representation of source code locations ๐.-fdump-ipa-switch,-fdump-ipa-switch-optionsโ these control the dumping, at various stages of the inter-procedural analysis, of the language tree to a file ๐. The file name is made by appending a switch-specific suffix to the source file name, and the file gets created in the same directory as the output file. These dumps are possible:allโ enables all inter-procedural analysis dumps.cgraphโ dumps info about call-graph optimization, unused function removal, and inlining decisions.inlineโ dumps after function inlining.strubmโ dumps after selecting "strub" modes, and records the selections as function attributes.strubโ dumps "strub" transformations: interface changes, function wrapping, and insertion of builtin calls for stack scrubbing and watermarking.
On top of that, you can add -optimized, -missed, -note, or -all. They mean the same thing as they do for -fopt-info, and the default is -optimized ๐
.
For example, -fdump-ipa-inline-optimized-missed will emit info on the callsites that got inlined, along with the callsites that did not get inlined ๐.
By default, the dump contains messages about successful optimizations (the same as -optimized), together with low-level details about the analysis ๐.
-fdump-ipa-clonesโ okay this one is for the live-patching crew ๐ฉนโจ It makes a dump file listing when call graph node clones get created and when call graph nodes get removed during inter-procedural optimizations and transformations. The main point is that tools building live-patches can work out the full set of functions they need to live-patch to completely replace one particular function (see-flive-patching) ๐ The file name is your source file name with the suffixipa-clonestacked on, and it gets saved in the same directory as the output file. Every entry sits on its own line with semicolon-separated fields ๐ธ
Clone creation: for call graph clone creation, the fields go like this:
"Callgraph clone", the literal string ๐- Name of the function being cloned, as the assembler sees it.
- A number that uniquely represents the function being cloned in the call graph. Heads up: it's only unique within a compilation unit or within whole-program analysis, and it's likely to be different between the two phases ๐
- The file name of the source file where the function is defined.
- The line where the function definition lives.
- The column where the function definition lives.
- Name of the new function clone, as the assembler sees it.
- A number that uniquely represents the new function clone in the call graph. Same deal: only unique within a compilation unit or whole-program analysis, and likely different in the two phases.
- The file name of the source file that the new clone's source code location points to.
- The line that the new clone's source code location points to.
- The column that the new clone's source code location points to.
- A string that tells you the reason for cloning ๐ง
Clone removal: for call graph clone removal, the fields go like this:
"Callgraph removal", the literal string ๐- Name of the function being removed, as it would be presented to the assembler.
- A number that uniquely represents the function being cloned in the call graph. Only unique within a compilation unit or whole-program analysis, and likely to differ between the two phases.
- The file name of the source file where the function is defined.
- The line where the function definition is located.
- The column where the function definition is located.
-fdump-langโ dump the language-specific info ๐ฆ The file name is made by slapping.langonto the end of the source file name.-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ these are the controls for dumping language-specific info ๐ Theoptionsandfilenamebits work exactly like they do in-fdump-tree.-fdump-tree-allturns on all the language-specific dumps, and everything else depends on the language, so main character energy from each one ๐ For instance, see-fdump-passesโ prints the list of optimization passes that the current command-line options switch on and off, straight to stderr ๐ฅ-fdump-statistics-optionโ turns on and controls pass statistics dumping into a separate file ๐ The file name is your source file name with a suffix that ends in.statistics, and it gets created in the same directory as the output file. If you use the-optionform,-statssums the counters over the whole compilation unit, while-detailsdumps every event as the passes generate them. With no option at all, the counters get summed for each function that's compiled ๐-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filenameโ this crew controls dumping at the different stages of processing the intermediate language tree into a file ๐ณ If you use the-optionsform,optionsis a list of--separated options that control how detailed the dump is. Not every option applies to every dump, and the ones that don't make sense just get ignored ๐ซถ These are the ones you can use:addressโ prints the address of each node. Usually not that meaningful, since it changes depending on the environment and source file. Its real job is tying a dump file to a debug environment ๐asmnameโ if"DECL_ASSEMBLER_NAME"has been set for a decl, it gets used in the dump instead of"DECL_NAME". It's mostly handy for working backward from mangled names in the assembly file โจslimโ when dumping front-end intermediate representations, it stops members of a scope or a function body from getting dumped just because that scope was reached. Those items only show up when some other path directly reaches them. When dumping pretty-printed trees, it stops the bodies of control structures from being dumped. When dumping RTL, it prints the RTL in slim (condensed) form instead of the default LISP-like representation ๐rawโ prints a raw representation of the tree. By default, trees get pretty-printed into a C-like representation ๐งธdetailsโ enables more detailed dumps (not every dump option honors this one). It also includes info from the optimization passes ๐statsโ enables dumping various statistics about the pass (again, not honored by every dump option) ๐blocksโ enables showing basic block boundaries (disabled in raw dumps) ๐งฑgraphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a control flow graph representation tofile.passid.pass.dot, which is suitable for viewing with GraphViz. Each function in the file gets pretty-printed as a subgraph, so GraphViz can render them all in one single plot ๐บ๏ธ RTL is always dumped in slim form.vopsโ enables showing virtual operands for every statement ๐linenoโ enables showing line numbers for statements ๐uidโ enables showing the unique ID ("DECL_UID") for each variable ๐verboseโ enables showing the tree dump for each statement ๐ehโ enables showing the EH region number that's holding each statement ๐scevโ enables showing scalar evolution analysis details ๐งฎoptimizedโ enables showing optimization info (only available in certain passes) โmissedโ enables showing missed optimization info (only available in certain passes) ๐ญnoteโ enables other detailed optimization info (only available in certain passes) ๐foldingโ enables dumping info about match-and-simplify (match.pd) patterns when they get applied ๐ชallโ turns on all the options, exceptraw,slim,verboseandlineno๐optallโ turns on all the optimization options, which meansoptimized,missed, andnote๐
Finding the dump you want: if you wanna figure out what tree dumps exist or find the dump for a pass you care about, follow these steps ๐ต๏ธโโ๏ธ
- Invoke GCC with
-fdump-passes, then look in the stderr output for a code that matches the pass you're into. For example, the codes"tree-evrp","tree-vrp1", and"tree-vrp2"all correspond to the three Value Range Propagation passes. The number at the end tells you apart the different invocations of the same pass ๐ข - To make the dump file get created, append the pass code to the
-fdump-option prefix and invoke GCC with it. For example, to enable the dump from the Early Value Range Propagation pass, invoke GCC with the-fdump-tree-evrpoption. You can optionally name the dump file yourself. If you don't, GCC makes one as described below ๐ - Find the pass dump in a file whose name has three parts separated by periods: the name of the source file GCC was invoked to compile, a numeric suffix for the pass number followed by the letter
tfor tree passes (or the letterrfor RTL passes), and finally the pass code. For example, the Early VRP pass dump might be in a file namedmyfile.c.038t.evrpin the current working directory. Heads up that the numeric codes aren't stable and can change from one version of GCC to another ๐
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ controls optimization dumps coming from the various optimization passes โจ If you use the-optionsform,optionsis a list of--separated option keywords that pick the dump details and optimizations. The options split into three groups: 1. options describing what kinds of messages get emitted, 2. options describing how verbose the dump is, and 3. options describing which optimizations get included ๐งฉ You can mix the options from each group freely since they don't overlap. But if there's a conflict, the later option on the command line wins ๐
Message kinds: these control which kinds of messages get emitted:
optimizedโ prints info when an optimization gets applied successfully. It's up to each pass to decide what info is relevant. For example, the vectorizer passes print the source location of loops that get vectorized ๐missedโ prints info about missed optimizations. Each pass controls what info goes into the output ๐ญnoteโ prints verbose info about optimizations, like certain transformations and more detailed messages about decisions ๐allโ prints detailed optimization info. This includesoptimized,missed, andnote๐
Verbosity: this one controls how verbose the dump is:
internalsโ by default only "high-level" messages get emitted. This turns on extra, more detailed messages that are probably only interesting to GCC developers ๐ค
Groups: these keywords describe a whole group of optimizations, so you don't have to list them one by one:
ipaโ enables dumps from all interprocedural optimizations ๐ฆloopโ enables dumps from all loop optimizations ๐inlineโ enables dumps from all inlining optimizations ๐ซง
ompโ okay so this one turns on dumps from all the OMP (Offloading and Multi Processing) optimizations ๐งvecโ dumps from all the vectorization optimizations ๐optallโ dumps from every single optimization ๐ It's a superset of the groups above, so it's basically the whole buffet ๐
If options is left out, it defaults to optimized-optall. That means you get messages about the successful optimizations from all the passes, minus anything tagged as "internals" ๐ซถ
If you give it a filename, all the applicable dumps get concatenated into that file. If you don't, the dump goes to stderr instead ๐ฆ You can use more than one -fopt-info option, but only one of them can carry a filename. If you slip in extra filenames, every one after the first gets ignored ๐
โ ๏ธ Heads up, bestie: the output filename gets overwritten when you have multiple translation units. If you want one combined output from several translation units, use stderr instead ๐ญ
Here's the vibe in action. This one dumps the optimization info straight to stderr:
gcc -O3 -fopt-info
This one writes the missed optimization report from all the passes into missed.all:
gcc -O3 -fopt-info-missed=missed.all
And this one prints info about missed opportunities from the vectorization passes to stderr. Fun fact: -fopt-info-vec-missed is the same thing as -fopt-info-missed-vec ๐ The order of the group names and message types after -fopt-info doesn't matter, so do whatever feels right โจ
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
Next up, this one outputs info about missed optimizations and optimized locations from all the inlining passes into inline.txt ๐
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
Finally, we've got a little conflict situation ๐
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Two output filenames, vec.miss and loop.opt, are fighting, since only one output file is allowed. So only the first option takes effect and the rest get ignored. You'll only end up with vec.miss, which holds the vectorizer's dumps about missed opportunities ๐
-fsave-optimization-recordโ okay, this one writes aSRCFILE.opt-record.json.gzfile that details what optimizations were performed, for every optimization that supports-fopt-info๐
๐งช This option is experimental, and the format of the data inside the compressed JSON file is subject to change. Use it with caution, bestie.
It's roughly a machine-readable version of -fopt-info-all. You get a collection of messages with the source file, line number and column number, plus some extra goodies for each message:
- the execution count of the code being optimized, plus metadata on whether it came from actual profile data or just an estimate, so consumers can sort messages by how hot the code is ๐ฅ
- the function name of the code being optimized, where that applies ๐
- the "inlining chain" for the code being optimized, so when a function gets inlined into a bunch of different places (which might themselves be inlined), you can tell the copies apart ๐ฆ
- objects identifying the parts of the message that refer to expressions, statements or symbol-table nodes, which category each one belongs to, and, when it's available, its source code location ๐ง
- the GCC pass that emitted the message, and
- the location in GCC's own code where the message was emitted ๐ค
Also, some messages are logically nested inside other messages, which reflects the implementation details of the optimization passes ๐ธ
-fsched-verbose=nโ on targets that use instruction scheduling, this controls how much debugging output the scheduler dumps into the dump files ๐- For
ngreater than zero, it outputs the same info as-fdump-rtl-sched1and-fdump-rtl-sched2. - For
ngreater than one, it also outputs basic block probabilities, detailed ready list information and unit/insn info. - For
ngreater than two, it includes the RTL at the abort point, plus control-flow and regions info. - And for
nover four,-fsched-verbosealso includes dependence info ๐
- For
-fenable-kind-pass,-fdisable-kind-pass=range-listโ this is a whole family of options for explicitly disabling or enabling optimization passes ๐งช They're meant for debugging GCC itself, so regular compiler users should stick to the normal options for enabling and disabling passes instead ๐ซถ-fdisable-ipa-passโ disables the IPA pass pass, where pass is the pass name. If the same pass gets statically invoked in the compiler more than once, append a sequential number to the pass name, starting from 1 ๐-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ disables the RTL pass pass, where pass is the pass name. Same numbering deal as above: if it's invoked multiple times, append a sequential number starting from 1 โจ- range-list is a comma-separated list of function ranges or assembler names. Each range is a number pair separated by a colon, and the range is inclusive at both ends. If the range is trivial, the number pair can be simplified to a single number ๐ง
- If the function's call graph node uid falls inside one of the specified ranges, the pass gets disabled for that function. You can find the uid in the function header of a dump file, and you can dump the pass names by using
-fdump-passes๐
-fdisable-tree-pass,-fdisable-tree-pass=range-listโ disables the tree pass pass. Check out-fdisable-rtlfor how the option arguments work ๐-fenable-ipa-passโ enables the IPA pass pass, where pass is the pass name. Same numbering rule applies: if it's invoked multiple times, append a sequential number starting from 1 ๐ฆ-fenable-rtl-pass,-fenable-rtl-pass=range-listโ enables the RTL pass pass. See-fdisable-rtlfor the option argument description and examples ๐ธ-fenable-tree-pass,-fenable-tree-pass=range-listโ enables the tree pass pass. See-fdisable-rtlfor the description of the option arguments ๐
Here are some examples of these options in action, lowkey iconic ๐
# disable ccp1 for all functions
-fdisable-tree-ccp1
# disable complete unroll for function whose cgraph node uid is 1
-fenable-tree-cunroll=1
# disable gcse2 for functions at the following ranges [1,1],
# [300,400], and [400,1000]
# disable gcse2 for functions foo and foo2
-fdisable-rtl-gcse2=foo,foo2
# disable early inlining
-fdisable-tree-einline
# disable ipa inlining
-fdisable-ipa-inline
# enable tree full unroll
-fenable-tree-unroll
-fchecking,-fchecking=nโ turns on internal consistency checking โ The default depends on how the compiler was configured.-fchecking=2goes further and enables extra internal consistency checking that might affect code generation ๐-frandom-seed=stringโ this gives GCC a seed to use instead of random numbers when it generates certain symbol names that have to be different in every compiled file ๐ฒ It's also used to stamp coverage data files and the object files that produce them. Use-frandom-seedif you want reproducibly identical object files ๐
The string can be a number (decimal, octal or hex), or an arbitrary string, which gets converted to a number by computing CRC32 ๐งฎ The string should be different for every file you compile ๐ซถ
-save-temps,--save-tempsโ stores the usual "temporary" intermediate files permanently ๐ They get named as auxiliary output files, as specified under-dumpbaseand-dumpdir๐ง
When you use it with the -x command-line option, -save-temps is smart enough to avoid overwriting an input source file that has the same extension as an intermediate file. If you want the corresponding intermediate file, rename the source file before using -save-temps ๐
-save-temps=cwdโ equivalent to-save-temps -dumpdir ./.๐-save-temps=objโ equivalent to-save-temps -dumpdir outdir/, whereoutdir/is the directory of the output file given after the-ooption, including any directory separators ๐ฆ If-oisn't used,-save-temps=objacts like-save-temps=cwd๐-specs=file,--specs=file,--specs fileโ processes file after the compiler reads in the standard specs file, so you can override the defaults thegccdriver uses when picking which switches to pass tocc1,cc1plus,as,ld, etc. ๐ You can specify more than one-specs=file, and they're processed in order, from left to right ๐-time[=file]โ reports the CPU time taken by each subprocess in the compilation sequence โฑ๏ธ For C source files, that's the compiler proper and the assembler (plus the linker, if linking happens) ๐ฅ
Without an output file, the output looks like this:
# cc1 0.12 0.01
# as 0.00 0.01
The first number on each line is the "user time", which is the time spent running the program itself. The second number is the "system time", the time spent in operating system routines on behalf of the program. Both numbers are in seconds โณ
With an output file, the output gets appended to the named file, and it looks like this:
0.12 0.01 cc1 <options>
0.00 0.01 as <options>
The "user time" and "system time" get moved in front of the program name, and the options passed to the program are displayed too, so you can later tell which file was being compiled and with which options ๐งพ
-fdump-final-insns[=file]โ dumps the final internal representation (RTL) to file ๐ง If the optional argument is left out (or if file is.), the dump file name is determined by appending.gkdto the dump base name, see-dumpbase๐-fcompare-debug[=opts]โ okay so if compiling goes through with no errors, GCC runs the compiler a second time, addingoptsand-fcompare-debug-secondto the arguments for that second run ๐ It dumps the final internal representation from both compilations and prints an error if they don't match. Verification ate, no crumbs ๐
Leave off the equal sign and the default -gtoggle kicks in ๐
The GCC_COMPARE_DEBUG environment variable can turn this on for you. If it's defined, non-empty and nonzero, it implicitly enables -fcompare-debug. If GCC_COMPARE_DEBUG is defined to a string that starts with a dash, that string is used for opts. Otherwise you get the default -gtoggle ๐ง
-fcompare-debug= (with the equal sign but no opts) is the same as -fno-compare-debug. That turns off the dumping of the final representation and the second compilation, and it means even GCC_COMPARE_DEBUG can't take effect โ
Want full coverage while you test with -fcompare-debug? Set GCC_COMPARE_DEBUG to -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any actual compilation (rather than preprocessing, assembly or linking) ๐ Only want a warning instead? Setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do ๐ฆ
-fcompare-debug-secondโ this one gets passed to the compiler automatically for the second compilation that-fcompare-debugasks for. It comes along with options that silence warnings, and it leaves out any other options that would make the compiler write output to files or to standard output as a side effect ๐ธ During the second compilation, dump files and preserved temporary files get the extra ".gk" extension so they don't overwrite the ones from the first run.
When you pass this option to the compiler driver, the first compilation gets skipped. Honestly that makes it pretty much only useful for debugging the compiler itself ๐
-gtoggleโ this flips debug info generation. If leaving out this option generates debug info, it turns generation off. Otherwise it turns debug info on at level 2 ๐ Where you put it on the command line doesn't matter. It takes effect after all other options are processed, and it only does its thing once, no matter how many times you write it. It's mainly meant to be used with-fcompare-debug.-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-assignments, the same way-gtoggletoggles-gโจ-Qโ main character energy for help output ๐ When it's used on the command line before--help=,-Qacts as a modifier to the help output.
Otherwise, this option makes the compiler print the name of each function as it gets compiled, and print some statistics about each pass when that pass finishes ๐
-ftime-reportโ makes the compiler print some stats to stderr about the time each pass consumed when it finishes โฑ๏ธ
If you asked for SARIF diagnostics output with -fdiagnostics-format=sarif-file or -fdiagnostics-format=sarif-stderr, then the -ftime-report info gets emitted as JSON inside the SARIF output instead. The precise format of that JSON is subject to change. The values might not exactly match the ones sent to stderr, since they get written out at a slightly different place inside the compiler ๐
-ftime-report-detailsโ records the time consumed by infrastructure parts separately for each pass ๐-fira-verbose=nโ controls how verbose the dump file for the integrated register allocator is. The default value is5. Ifnis greater than or equal to10, the dump output goes to stderr in the same format asnminus10๐ง-flto-reportโ prints a report with internal details on how the link-time optimizer is working. What's in this report changes from version to version ๐คทโโ๏ธ It's meant for GCC developers who are processing object files in LTO mode (via-flto). It's disabled by default.-flto-report-wpaโ like-flto-report, but it only prints for the WPA phase of link-time optimization ๐ฆ-fmem-reportโ makes the compiler print some statistics about permanent memory allocation when it finishes ๐งฎ-fmem-report-wpaโ makes the compiler print some statistics about permanent memory allocation for the WPA phase only ๐-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ makes the compiler print some statistics about permanent memory allocation either before or after interprocedural optimization. Pick your vibe ๐-fmultiflagsโ this one's giving build-system drama in the best way ๐ It enables multilib-aware"TFLAGS"to be used for building target libraries with options that differ from the ones the compiler is configured to use by default. It works through specs set up by compiler internals, by the target, or by builders at configure time.
Like "TFLAGS", this lets target libraries be built for portable baseline environments, while the compiler defaults stay more demanding. That's useful because users can easily override the compiler's defaults to build their own programs when those defaults aren't ideal for their target environment. Rebuilding the runtime libraries is usually not as easy or desirable, so this is the easier route ๐ซถ
Unlike "TFLAGS", using specs lets different flags get selected for different multilibs. To pull that off, build with make TFLAGS=-fmultiflags, after configuring with --with-specs=%{fmultiflags:...}.
This option gets discarded by the driver once it's done processing the driver self spec ๐๏ธ
It's also handy for checking that "TFLAGS" are being used to build all target libraries. You do that by configuring a non-bootstrap compiler with --with-specs='%{!fmultiflags:%emissing TFLAGS}' and then building the compiler and target libraries ๐
-fprofile-reportโ makes the compiler print some statistics about the consistency of the (estimated) profile and the effect of individual passes ๐-fstack-usageโ makes the compiler output stack usage info for your program, per function. The dump filename is made by appending.suto the auxname. The auxname comes from the name of the output file if you explicitly specified one and it's not an executable. Otherwise it's the basename of the source file ๐
Each entry has three fields:
- The name of the function.
- A number of bytes.
- One or more qualifiers:
"static","dynamic","bounded".
The qualifier "static" means the function manipulates the stack statically. A fixed number of bytes gets allocated for the frame on function entry and released on function exit, and no other stack adjustments get made in the function. The second field is that fixed number of bytes ๐งฑ
The qualifier "dynamic" means the function manipulates the stack dynamically. On top of the static allocation above, stack adjustments get made in the body of the function, for example to push and pop arguments around function calls. If the qualifier "bounded" is also present, the amount of those adjustments is bounded at compile time, and the second field is an upper bound on the total stack used by the function. If "bounded" isn't present, the amount of those adjustments isn't bounded at compile time, and the second field only represents the bounded part ๐ฅฒ
-fstatsโ emits statistics about front-end processing at the end of compilation. This is only supported by the C++ front end, and the info is generally only useful to the G++ development team ๐ค-fdbg-cnt-listโ prints the name and the counter upper bound for all debug counters ๐-fdbg-cnt=counter-value-listโ sets the internal debug counter lower and upper bounds.counter-value-listis a comma-separated list ofname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]tuples. Each one sets the name of the counter and a list of closed intervals. Thelower_boundis optional and gets zero initialized if it isn't set ๐ฏ
For example, with -fdbg-cnt=dce:2-4:10-11,tail_call:10, dbg_cnt(dce) returns true only for the second, third, fourth, tenth and eleventh invocation. For dbg_cnt(tail_call), true is returned for the first 10 invocations โจ
-print-autofdo-gcov-version,--print-autofdo-gcov-versionโ prints the current version of GCOV being used by the AutoFDO infrastructure ๐จ๏ธ-print-file-name=library,--print-file-name=library,--print-file-name libraryโ prints the full absolute name of the library filelibrarythat would be used when linking, and then stops there. With this option, GCC doesn't compile or link anything. It just prints the file name ๐-print-multi-directory,--print-multi-directoryโ prints the directory name that matches the multilib selected by any other switches on the command line. That directory is supposed to exist inGCC_EXEC_PREFIX๐๏ธ-print-multi-lib,--print-multi-libโ prints the mapping from multilib directory names to the compiler switches that enable them. The directory name is separated from the switches by;. Each switch starts with@instead of-, with no spaces between multiple switches. This is supposed to make shell processing easier ๐-print-multi-os-directory,--print-multi-os-directoryโ prints the path to OS libraries for the selected multilib, relative to somelibsubdirectory. If OS libraries live in thelibsubdirectory and no multilibs are used, this is usually just.. If OS libraries live inlibsuffixsibling directories, it prints something like../lib64,../libor../lib32. If OS libraries live inlib/subdirsubdirectories, it prints something likeamd64,sparcv9orev6๐-print-multiarch,--print-multiarchโ prints the path to OS libraries for the selected multiarch, relative to somelibsubdirectory ๐งฉ-print-prog-name=program,--print-prog-name=program,--print-prog-name programโ like-print-file-name, but it searches for a program such ascppinstead of a library ๐ง-print-libgcc-file-name,--print-libgcc-file-nameโ same as-print-file-name=libgcc.a๐
This is useful when you use -nostdlib or -nodefaultlibs but you still want to link with libgcc.a. You can do:
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirs,--print-search-dirsโ prints the name of the configured installation directory and a list of the program and library directories gcc searches, and then stops. It doesn't do anything else ๐บ๏ธ
Okay so this bit is SO useful when gcc starts throwing the classic installation problem, cannot exec cpp0: No such file or directory. ๐ญ๐ซถ To fix it, you either need to put cpp0 and the other compiler components exactly where gcc expects to find them, or you can set the environment variable GCC_EXEC_PREFIX to the directory where you installed them. And don't forget the trailing /! ๐
-print-sysroot,--print-sysrootโ prints the target sysroot directory the compiler is using while it compiles ๐ธ. That's whatever was set at configure time or with--sysroot, maybe with an extra suffix that depends on your compilation options. If there's no target sysroot, it prints nothing at all, bestie.-print-sysroot-headers-suffix,--print-sysroot-headers-suffixโ prints the suffix tacked onto the target sysroot when searching for headers ๐ง. If the compiler wasn't configured with a suffix, it errors out instead. Either way it stops there and doesn't do anything else.-dumpmachineโ prints the compiler's target machine, likei686-pc-linux-gnu, and then it's done ๐ฆ.-dumpversionโ prints the compiler version, like3.0,6.3.0or7, and then stops โจ. This is the version used in filesystem paths and specs. Depending on how the compiler was configured, it could be one number (major), two numbers separated by a dot (major and minor), or three numbers separated by dots (major, minor and patchlevel).-dumpfullversionโ prints the full compiler version and nothing else ๐. The output is always three numbers separated by dots: major, minor and patchlevel.-dumpspecsโ prints the compiler's built-in specs and then stops ๐. (This is only used when GCC itself is being built, so it's kinda niche.)--param name=value,--param=name=valueโ okay so GCC, by convention, uses parameters you can pass on the command line instead of hard-wired constants for compiler limits and heuristics ๐ฅ. Lots of them are optimization stuff, like GCC not inlining functions that have more than a certain number of instructions. The static analyzer uses them to limit complexity, link-time optimization uses them to control partitioning, and so on. Others control internal stuff like memory allocation and garbage collection strategy, and some control target-specific behavior. The--paramoption gives you one uniform way to set all of them, but the names and meanings are tied to the compiler's internals and can change without notice in future releases.
Don't depend on parameter settings for your program to compile correctly! ๐ They're exposed for developers debugging compilation problems or, in some cases, as workarounds for compiler bugs.
โจ Machine-Dependent Options โจ
Each target machine GCC supports can have its own options ๐ธ. For example, you can compile for a particular processor variant or ABI, or control optimizations specific to that machine. By convention, machine-specific option names start with -m.
Some configurations of the compiler also support extra target-specific options, usually so they can play nice with other compilers on the same platform ๐ซถ.
๐ฆ AArch64 Options ๐ฆ
These options are defined for AArch64 implementations:
-mabi=nameโ picks the data model you want code generated for ๐.ilp32is the SysV-like one whereint,long intand pointers are all 32 bits, andlp64is the SysV-like one whereintis 32 bits butlong intand pointers are 64 bits. The default depends on your specific target configuration. The LP64 and ILP32 ABIs are NOT link-compatible, so you have to compile your entire program with the same ABI and link it against a compatible set of libraries. Also, theilp32model is deprecated, so be careful with it ๐ญ.-mbig-endianโ generates big-endian code ๐. This is the default when GCC is configured for anaarch64_be-*-*target.-mlittle-endianโ generates little-endian code ๐. This is the default when GCC is configured for anaarch64-*-*target but not anaarch64_be-*-*one.-menable-sysreg-checkingโ gives you an error message if you try to access a system register that isn't available on the target architecture ๐.-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers โจ. This stops the compiler from using floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler.-mcmodel=tinyโ generates code for the tiny code model ๐ง. The program and its statically defined symbols must be within 1MB of each other. Programs can be statically or dynamically linked.-mcmodel=smallโ generates code for the small code model ๐. The program and its statically defined symbols must be within 4GB of each other. Programs can be statically or dynamically linked. This is the default code model, so you get it for free ๐ .-mcmodel=largeโ generates code for the large code model ๐ฅ. It makes NO assumptions about addresses and section sizes. Programs can only be statically linked. Also,-mcmodel=largeis incompatible with-mabi=ilp32,-fpicand-fPIC, so don't mix them up ๐ โโ๏ธ.-mtp=nameโ specifies the system register to use as the thread pointer ๐งต. The valid values aretpidr_el0,tpidrro_el0,tpidr_el1,tpidr_el2andtpidr_el3. For backwards compatibility, the aliasesel0,el1,el2andel3are also accepted. The default istpidr_el0. It's recommended to compile all code that's meant to interoperate with the same value of this option, so you don't end up accessing a different thread pointer from the wrong exception level ๐ฌ.-mstrict-align,-mno-strict-alignโ avoids or allows generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification ๐ธ.-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ omits or keeps the frame pointer in leaf functions ๐ฆ. The former behavior (omitting it) is the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard๐ก๏ธ. The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register. With thesysregchoice,-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsetfurther specify which system register to use as the base register for reading the canary, and what offset from that base register to use. There's no default register or offset, because this is entirely for use within the Linux kernel ๐ง.-mtls-dialect=descโ uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables ๐. This is the default.-mtls-dialect=traditionalโ uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐.-mtls-size=sizeโ specifies the bit size of immediate TLS offsets โญ. Valid values are12,24,32and48. This option requires binutils 2.26 or newer.-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ enables or disables the workaround for ARM Cortex-A53 erratum number 835769 ๐ฉน. This works by inserting a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions. This flag gets ignored if an architecture or cpu is specified on the command line that doesn't need the workaround.-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419โ enables or disables the workaround for ARM Cortex-A53 erratum number 843419 ๐ฉน. This erratum workaround is made at link time, so this flag only passes the corresponding flag to the linker. It's also ignored if an architecture or cpu is specified on the command line that doesn't need the workaround.-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ enables or disables the reciprocal square root approximation ๐งฎ. This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces precision of reciprocal square root results to about 16 bits for single precision and to 32 bits for double precision.-mlow-precision-sqrt,-mno-low-precision-sqrtโ enables or disables the square root approximation ๐. This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces precision of square root results to about 16 bits for single precision and to 32 bits for double precision. If enabled, it implies-mlow-precision-recip-sqrt.-mlow-precision-div,-mno-low-precision-divโ enables or disables the division approximation โ. This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces precision of division results to about 16 bits for single precision and to 32 bits for double precision.-mtrack-speculation,-mno-track-speculationโ enables or disables generation of extra code that tracks speculative execution through conditional branches ๐ต๏ธโโ๏ธ. The tracking state can then be used by the compiler when expanding calls to"__builtin_speculation_safe_value", so it can generate a more efficient code sequence.-moutline-atomics,-mno-outline-atomicsโ enables or disables calls to out-of-line helpers that implement atomic operations ๐. These helpers figure out at runtime whether the LSE instructions from ARMv8.1-A can be used. If not, they fall back to the load/store-exclusive instructions that are present in the base ARMv8.0 ISA.
This option is only applicable when compiling for the base ARMv8.0 instruction set. If you're using a later revision, like -march=armv8.1-a or -march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for -mcpu= when the selected cpu supports the lse feature ๐ซถ. This option is on by default โจ.
๐ -mmax-vectorization / -mno-max-vectorization
okay so these two flip a switch that makes the vectorizer's cost model override itself, so vectorization always looks profitable ๐ญโจ -mmax-vectorization turns that on and -mno-max-vectorization turns it back off. You can pair it with -mautovec-preference for super precise control over which ISA gets used for auto-vectorization ๐. And heads up, bestie: unlike -fno-vect-cost-model or -fvect-cost-model=unlimited, this one does not turn off the cost comparison between different vector modes ๐ง.
โจ -mautovec-preference=name
this one forces an ISA selection strategy for auto-vectorization ๐
The possible values of name are:
defaultโ just use the default heuristics, nothing fancy ๐ธasimd-onlyโ Advanced SIMD only, no SVE allowed ๐ฆsve-onlyโ SVE only, no Advanced SIMD allowed ๐ฅprefer-asimdโ use both Advanced SIMD and SVE, but go with Advanced SIMD when the costs are deemed equal ๐prefer-sveโ use both Advanced SIMD and SVE, but go with SVE when the costs are deemed equal ๐
For the best performance, it is highly recommended to use-mcpuor-mtuneinstead โ ๏ธ This parameter should only be used for code exploration, so don't go rewriting your whole build around it ๐
๐ -march=name
okay this is the big one ๐ -march specifies the name of the target architecture and, optionally, one or more feature modifiers. It has the form -march=arch{+[no]feature}* โจ
Here's the lineup of permissible arch values and the features each one enables by default:
armv8-a(Armv8-A) โ includes by default:+fp,+simdarmv8.1-a(Armv8.1-A) โ includes by default:armv8-a,+crc,+lse,+rdmaarmv8.2-a(Armv8.2-A) โ includes by default:armv8.1-aarmv8.3-a(Armv8.3-A) โ includes by default:armv8.2-a,+pauth,+fcma,+jscvtarmv8.4-a(Armv8.4-A) โ includes by default:armv8.3-a,+flagm,+fp16fml,+dotprod,+rcpc2armv8.5-a(Armv8.5-A) โ includes by default:armv8.4-a,+sb,+ssbs,+predres,+frintts,+flagm2armv8.6-a(Armv8.6-A) โ includes by default:armv8.5-a,+bf16,+i8mmarmv8.7-a(Armv8.7-A) โ includes by default:armv8.6-a,+wfxt,+xsarmv8.8-a(Armv8.8-a) โ includes by default:armv8.7-a,+mopsarmv8.9-a(Armv8.9-a) โ includes by default:armv8.8-aarmv9-a(Armv9-A) โ includes by default:armv8.5-a,+sve,+sve2armv9.1-a(Armv9.1-A) โ includes by default:armv9-a,+bf16,+i8mmarmv9.2-a(Armv9.2-A) โ includes by default:armv9.1-a,+wfxt,+xsarmv9.3-a(Armv9.3-A) โ includes by default:armv9.2-a,+mopsarmv9.4-a(Armv9.4-A) โ includes by default:armv9.3-a,+sve2p1armv9.5-a(Armv9.5-A) โ includes by default:armv9.4-a,cpa,+faminmax,+lutarmv8-r(Armv8-R) โ includes by default:armv8-r
the value native is available on native AArch64 GNU/Linux and tells the compiler to pick the architecture of the host system ๐ง If the compiler can't recognize the host architecture, this option just has no effect. When -march=native is given and no other -mcpu or -mtune is given, GCC picks the host CPU to tune for and selects the architecture features from it. Basically, -march=native gets treated as -mcpu=native ๐
The permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one wins ๐
GCC uses name to decide what kind of instructions it can emit when generating assembly code. If -march is specified without -mtune or -mcpu also being specified, the code is tuned to perform well across a range of target processors implementing the target architecture ๐ธ
๐ธ -mtune=name
-mtune is where you tell GCC which target processor to tune the performance of your code for ๐
Permissible values are:
generic, cortex-a35, cortex-a53, cortex-a55, cortex-a57,
cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae,
cortex-a77, cortex-a65, cortex-a65ae, cortex-a34, cortex-a78,
cortex-a78ae, cortex-a78c, ares, exynos-m1, emag, falkor, oryon-1,
neoverse-512tvb, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-v1,
neoverse-v2, grace, neoverse-v3, neoverse-v3ae, neoverse-n3,
olympus, cortex-a725, cortex-x925, qdf24xx, saphira, phecda, xgene1,
vulcan, octeontx, octeontx81, octeontx83, octeontx2, octeontx2t98,
octeontx2t96 octeontx2t93, octeontx2f95, octeontx2f95n,
octeontx2f95mm, a64fx, fujitsu-monaka, thunderx, thunderxt88,
thunderxt88p1, thunderxt81, tsv110, hip12, thunderxt83,
thunderx2t99, thunderx3t110, zeus, cortex-a57.cortex-a53,
cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53,
cortex-a75.cortex-a55, cortex-a76.cortex-a55, cortex-r82,
cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3,
cortex-x4, cortex-a510, cortex-a520, cortex-a520ae, cortex-a710,
cortex-a715, cortex-a720, cortex-a720ae, ampere1, ampere1a,
ampere1b, ampere1c, cobalt-100, apple-m1, apple-m2, apple-m3,
apple-m4, c1-nano, c1-pro, c1-premium c1-ultra and native.
some of these are big.LITTLE combos, and those values tell GCC to tune for a big.LITTLE system ๐งธ They are cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55, apple-m1, apple-m2, apple-m3, and gb10 โจ
neoverse-512tvb is giving "all Neoverse cores with SVE and a total vector bandwidth of 512 bits per cycle" ๐ฆ In other words, it tunes for Neoverse cores that can execute 4 128-bit Advanced SIMD arithmetic instructions a cycle, and an equivalent number of SVE arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE). It's more general than tuning for a specific core like Neoverse V1, but more specific than the default tuning ๐
On native AArch64 GNU/Linux systems, native tunes performance to the host system. If the compiler can't recognize the host processor, that has no effect ๐ซถ
If none of -mtune=, -mcpu=, or -march= are specified, the code is tuned to perform well across a range of target processors ๐
This option cannot be suffixed by feature modifiers ๐ โโ๏ธ
๐ -mcpu=name
-mcpu is the name of the target processor, optionally suffixed by one or more feature modifiers ๐ It has the form -mcpu=cpu{+[no]feature}*, where the permissible values for cpu are the same as the ones for -mtune. The permissible values for feature are documented in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. Same rule as before, bestie: if feature modifiers conflict, the right-most one is used ๐
GCC uses name to figure out what kind of instructions it can emit when generating assembly code (as if by -march), and to figure out which target processor to tune for performance (as if by -mtune) ๐ง If you use this option together with -march or -mtune, those options take precedence over the matching part of -mcpu โจ
-mcpu=neoverse-512tvb is special, lowkey ๐ธ It doesn't refer to one specific core. Instead it refers to all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle. Unless you override it with -march, -mcpu=neoverse-512tvb generates code that can run on a Neoverse V1 core, since Neoverse V1 is the first Neoverse core with these properties ๐ฆ And unless you override it with -mtune, -mcpu=neoverse-512tvb tunes code in the same way as -mtune=neoverse-512tvb ๐
๐ฆ -moverride=string
this one overrides the tuning decisions the back-end makes in response to a -mtune= switch ๐งช The syntax, semantics, and accepted values for string are not guaranteed to be consistent across releases, so please don't build anything important on it ๐ญ
This option is only intended to be useful when developing GCC ๐ ๏ธ
๐ง -mpc-relative-literal-loads / -mno-pc-relative-literal-loads
these enable or disable PC-relative literal loads ๐ With this option, literal pools are accessed using a single instruction and emitted after each function. The catch is that this limits the maximum size of functions to 1MB ๐ It's enabled by default for -mcmodel=tiny.
๐ -msign-return-address=scope
this selects the function scope where return address signing gets applied ๐ The permissible values are:
noneโ disables return address signingnon-leafโ enables pointer signing for functions which are not leaf functionsallโ enables pointer signing for all functions
The default value is none. Heads up, this option has been deprecated by -mbranch-protection, so use that one instead ๐
โโ๏ธ
๐ฅ -mbranch-protection=features
this picks the branch protection features to use ๐ก๏ธ features can have one of the following forms:
noneโ the default, turns off all types of branch protection ๐ซฅstandardโ turns on all types of branch protection features. If a feature has additional tuning options, thenstandardsets it to its standard level ๐pac-retโ turns on return address signing to its standard level: signing functions that save the return address to memory (non-leaf functions practically always do this) using the A-key ๐ฆpac-ret+leafโ extends thepac-retsigning to include leaf functions ๐pac-ret+b-keyorpac-ret+leaf+b-keyโ can be used to sign the functions with the B-key instead of the A-key ๐btiโ turns on the branch target identification mechanism ๐ฏgcsโ turns on guarded control stack compatible code generation ๐
๐ -mharden-sls=opts
this enables compiler hardening against straight line speculation (SLS) ๐ซถ opts is a comma-separated list of the following options:
retbrblr
In addition, -mharden-sls=all enables all SLS hardening, while -mharden-sls=none disables all SLS hardening โจ
๐ซถ -mearly-ra=scope
this decides when to enable an early register allocation pass ๐ง The pass runs before instruction scheduling and tries to find a spill-free allocation of floating-point and vector code. It also tries to make use of strided multi-register instructions, such as SME2's strided LD1 and ST1 ๐ธ
The possible values of scope are:
allโ runs the pass on all functionsstridedโ runs the pass on functions that have access to strided multi-register instructionsnoneโ disables the pass
-mearly-ra=all is the default for -O2 and above, and for -Os. -mearly-ra=none is the default otherwise ๐
๐ -mearly-ldp-fusion / -mno-early-ldp-fusion
these enable or disable the copy of the AArch64 load/store pair fusion pass that runs before register allocation ๐ It's enabled by default at -O and above ๐
๐ -mlate-ldp-fusion / -mno-late-ldp-fusion
same vibe as the early one, but these enable or disable the copy of the AArch64 load/store pair fusion pass that runs after register allocation ๐ It's also enabled by default at -O and above ๐ซถ
-msve-vector-bits=bitsโ okay so this one sets how many bits live in an SVE vector register ๐ฆ It only does anything when SVE is turned on ๐
GCC makes two flavors of SVE code, bestie. There's "vector-length agnostic" output that's happy with any size of vector register โจ, and "vector-length specific" output that lets GCC assume a vector length when that helps with optimization ๐ฅ. The possible values of bits are scalable, 128, 256, 512, 1024, and 2048. scalable gets you vector-length agnostic output. At present, -msve-vector-bits=128 also gives you vector-length agnostic output on big-endian targets ๐. Every other value makes vector-length specific code. These values might change in future releases, so ngl the only one you should rely on for code that's portable across different hardware SVE vector lengths is scalable ๐ซถ
The default is -msve-vector-bits=scalable, which makes vector-length agnostic code ๐ธ
๐ -march and -mcpu Feature Modifiers ๐
Okay, feature modifiers used with -march and -mcpu can be any of the ones below, and each one also has an inverse you write as nofeature ๐
crcโ Enable the CRC extension. It's on by default for-march=armv8.1-a๐งcryptoโ Enable the Crypto extension. This also turns on Advanced SIMD and floating-point instructions ๐fpโ Enable floating-point instructions. It's on by default for literally every possible value of-marchand-mcpu๐simdโ Enable Advanced SIMD instructions. This also turns on floating-point instructions. It's on by default for every possible value of-marchand-mcpuโจsveโ Enable Scalable Vector Extension instructions. This also turns on Advanced SIMD and floating-point instructions ๐ฆlseโ Enable Large System Extension instructions. It's on by default for-march=armv8.1-a๐ฅrdmaโ Enable Round Double Multiply Accumulate instructions. It's on by default for-march=armv8.1-a๐ธfp16โ Enable the FP16 extension. This also turns on floating-point instructions ๐fp16fmlโ Enable the FP16 fmla extension. This also turns on the FP16 extensions and floating-point instructions. It's enabled by default for-march=armv8.4-a. Using this with architectures before Armv8.2-A isn't supported ๐rcpcโ Enable the RCpc extension. This lets you use theLDAPRinstructions for load-acquire atomic semantics, and it passes the setting on to the assembler so inline asm statements can use RCpc instructions ๐dotprodโ Enable the Dot Product extension. This also turns on Advanced SIMD instructions ๐aesโ Enable the Armv8-aaesandpmullcrypto extension. This also turns on Advanced SIMD instructions ๐sha2โ Enable the Armv8-asha2crypto extension. This also turns on Advanced SIMD instructions โญsha3โ Enable thesha512andsha3crypto extension. This also turns on Advanced SIMD instructions. Using this with architectures before Armv8.2-A isn't supported ๐ซถsm4โ Enable thesm3andsm4crypto extension. This also turns on Advanced SIMD instructions. Using this with architectures before Armv8.2-A isn't supported ๐งprofileโ Enable the Statistical Profiling extension. This only turns it on at the assembler level and doesn't change code generation ๐rngโ Enable the Armv8.5-a Random Number instructions. This only turns the extension on at the assembler level and doesn't affect code generation ๐ฒmemtagโ Enable the Armv8.5-a Memory Tagging Extensions. Using this with architectures before Armv8.5-A isn't supported ๐ท๏ธsbโ Enable the Armv8-a Speculation Barrier instruction. This only turns it on at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a๐ก๏ธssbsโ Enable the Armv8-a Speculative Store Bypass Safe instruction. This only turns it on at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a๐predresโ Enable the Armv8-a Execution and Data Prediction Restriction instructions. This only turns them on at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a๐sve2โ Enable the Armv8-a Scalable Vector Extension 2. This also turns on SVE instructions ๐ฆsve2-bitpermโ Enable SVE2 bitperm instructions. This also turns on SVE2 instructions ๐ธsve2-sm4โ Enable SVE2 sm4 instructions. This also turns on SVE2 instructions ๐sve2-aesโ Enable SVE2 aes instructions. This also turns on SVE2 instructions ๐ฅsve2-sha3โ Enable SVE2 sha3 instructions. This also turns on SVE2 instructions ๐sve2p1โ Enable SVE2.1 instructions. This also turns on SVE2 instructions ๐tmeโ Enable the Transactional Memory Extension ๐งi8mmโ Enable 8-bit Integer Matrix Multiply instructions. This also turns on Advanced SIMD and floating-point instructions. It's enabled by default for-march=armv8.6-a. Using this with architectures before Armv8.2-A isn't supported ๐ขf32mmโ Enable 32-bit Floating point Matrix Multiply instructions. This also turns on SVE instructions. Using this with architectures before Armv8.2-A isn't supported ๐งฎf64mmโ Enable 64-bit Floating point Matrix Multiply instructions. This also turns on SVE instructions. Using this with architectures before Armv8.2-A isn't supported ๐งฎbf16โ Enable brain half-precision floating-point instructions. This also turns on Advanced SIMD and floating-point instructions. It's enabled by default for-march=armv8.6-a. Using this with architectures before Armv8.2-A isn't supported ๐งls64โ Enable the 64-byte atomic load and store instructions for accelerators ๐mopsโ Enable the instructions that speed up memory operations like "memcpy", "memmove", "memset". It's enabled by default for-march=armv8.8-a๐จflagmโ Enable the Flag Manipulation instructions Extension ๐ฉflagm2โ Enable the FlagM2 flag conversion instructions ๐pauthโ Enable the Pointer Authentication Extension ๐csscโ Enable the Common Short Sequence Compression instructions ๐๏ธcmpbrโ Enable the shorter compare and branch instructions, "cbb", "cbh" and "cb" โกsmeโ Enable the Scalable Matrix Extension ๐งsme-i16i64โ Enable the FEAT_SME_I16I64 extension to SME. This also turns on SME instructions ๐งsme-f64f64โ Enable the FEAT_SME_F64F64 extension to SME. This also turns on SME instructions ๐งsme2โ Enable the Scalable Matrix Extension 2. This also turns on SME instructions ๐งsme-f8f16โ Enable the FEAT_SME_F8F16 extension to SME. This also turns on SME2 and FP8 instructions ๐งsme-f8f32โ Enable the FEAT_SME_F8F32 extension to SME. This also turns on SME2 and FP8 instructions ๐งsme-b16b16โ Enable the FEAT_SME_B16B16 extension to SME. This also turns on SME2 and SVE_B16B16 instructions ๐งsme-f16f16โ Enable the FEAT_SME_F16F16 extension to SME. This also turns on SME2 instructions ๐งsme2p1โ Enable the Scalable Matrix Extension version 2.1. This also turns on SME2 instructions ๐งfcmaโ Enable the complex number SIMD extensions ๐ขjscvtโ Enable the "fjcvtzs" JavaScript conversion instruction ๐frinttsโ Enable floating-point round to integral value instructions ๐ฏwfxtโ Enable the "wfet" and "wfit" instructions โณxsโ Enable the XS memory attribute extension ๐งฑlse128โ Enable the LSE128 128-bit atomic instructions extension. This also turns on LSE instructions ๐d128โ Enable support for 128-bit system register read/write instructions. This also turns on the LSE128 extension ๐๏ธgcsโ Enable support for the Armv9.4-a Guarded Control Stack extension ๐ฐtheโ Enable support for the Armv8.9-a/9.4-a translation hardening extension ๐ ๏ธrcpc2โ Enable the RCpc2 extension ๐rcpc3โ Enable the RCpc3 (Release Consistency) extension ๐fp8โ Enable the fp8 (8-bit floating point) extension ๐fp8fmaโ Enable the fp8 (8-bit floating point) multiply accumulate extension โ๏ธssve-fp8fmaโ Enable the fp8 (8-bit floating point) multiply accumulate extension in streaming mode ๐fp8dot4โ Enable the fp8 (8-bit floating point) to single-precision 4-way dot product extension ๐ssve-fp8dot4โ Enable the fp8 (8-bit floating point) to single-precision 4-way dot product extension in streaming mode ๐fp8dot2โ Enable the fp8 (8-bit floating point) to half-precision 2-way dot product extension ๐ssve-fp8dot2โ Enable the fp8 (8-bit floating point) to half-precision 2-way dot product extension in streaming mode ๐faminmaxโ Enable the Floating Point Absolute Maximum/Minimum extension ๐lutโ Enable the Lookup Table extension ๐บ๏ธsme-lutv2โ Enable the SME Lookup Table v2 (LUTv2) extension ๐บ๏ธcpaโ Enable the Checked Pointer Arithmetic instructions ๐งทsve-b16b16โ Enable the SVE non-widening brain floating-point ("bf16") extension. This only has an effect when "sve2" or "sme2" are also enabled ๐งsve-bfscaleโ Enable the SVE_BFSCALE extension โ๏ธ
Feature crypto implies aes, sha2, and simd, which implies fp. Conversely, nofp implies nosimd, which implies nocrypto, noaes and nosha2. So they all come as a little package deal ๐
๐ธ Adapteva Epiphany Options ๐ธ
These -m options are defined for Adapteva Epiphany ๐ฆ
-mhalf-reg-file,-mno-half-reg-fileโ Don't allocate any register in the range "r32"..."r63". That lets code run on hardware variants that don't have these registers ๐-mprefer-short-insn-regs,-mno-prefer-short-insn-regsโ Preferentially allocate registers that allow short instruction generation. This can bump up the instruction count, so it might shrink or grow overall code size ๐คทโโ๏ธ-mbranch-cost=numโ Set the cost of branches to roughlynum"simple" instructions. This cost is only a heuristic and isn't guaranteed to give consistent results across releases ๐งฎ-mcmove,-mno-cmoveโ Enable the generation of conditional moves โจ-mnops=numโ EmitnumNOPs before every other generated instruction ๐ซง-mno-soft-cmpsf,-msoft-cmpsfโ okay so this pair is about single-precision floating-point comparisons ๐ฆ With-mno-soft-cmpsf, the compiler emits anfsubinstruction and checks the flags instead. It's faster than a software comparison, BUT it can get wrong answers when NaNs are involved, or when two different small numbers subtract to zero, which is so not it ๐ The default is-msoft-cmpsf, which uses slower software comparisons that are IEEE-compliant. Safe and sound, just not the speed demon ๐ซถ-mstack-offset=numโ this sets the gap between the top of the stack and the stack pointer ๐ง A value of 8 means the eight bytes fromsp+0throughsp+7can be used by leaf functions without stack allocation ๐ Heads up though: values other than 8 or 16 are untested and unlikely to work ๐ This option also changes the ABI, so compiling a program with a different stack offset than the one your libraries were built with generally doesn't work ๐ญ It's useful if you're testing whether a different offset gives you better code. But if you actually want working programs with a different offset, the move is to configure the toolchain with the appropriate--with-stack-offset=numoption ๐-mno-round-nearest,-mround-nearestโ-mno-round-nearestmakes the scheduler assume the rounding mode has been set to truncating ๐ธ The default is-mround-nearest.-mlong-callsโ if an attribute doesn't say otherwise, this assumes every call might be beyond the offset range of theb/blinstructions ๐งธ So the function address gets loaded into a register before the (otherwise direct) call. This is the default, bestie.-mshort-callsโ if an attribute doesn't say otherwise, this assumes all direct calls are in range of theb/blinstructions, so those instructions get used for direct calls โก The default is-mlong-calls. Also note that-mlong-callsis equivalent to-mno-short-calls, and-mno-long-callsis equivalent to-mshort-calls. It's giving mirror energy ๐ช-msmall16,-mno-small16โ this assumes addresses can be loaded as 16-bit unsigned values ๐ It doesn't apply to function addresses where-mlong-callssemantics are in effect.-mfp-mode=modeโ this sets the prevailing mode of the floating-point unit, which decides the floating-point mode that's provided and expected at function call and return โจ If you match it to the mode you mostly need at function start, your programs can get smaller and faster by skipping unnecessary mode switches ๐ฅ Themodecan be one of these:callerโ any mode at function entry is valid, and it gets retained or restored when the function returns and when it calls other functions. This one's perfect for libraries or compilation units you might drop into different programs with different FPU modes. The convenience of a single object file outweighs the extra size and speed overhead of mode switching, compared with a more specific pick ๐truncateโ the mode used for floating-point calculations with truncating (round towards zero) rounding. That includes conversion from floating point to integer.round-nearestโ the mode used for floating-point calculations with round-to-nearest-or-even rounding.intโ the mode used to do integer calculations in the FPU, like integer multiply or integer multiply-and-accumulate.
The default is -mfp-mode=caller.
-mmay-round-for-trunc,-mno-may-round-for-truncโ this lets floating point to integer truncation get swapped out for rounding, so you can save on mode switching ๐ It's disabled by default.-mfp-iarith,-mno-fp-iarithโ this turns on using the floating-point unit for integer add and subtract ๐งฎ It's disabled by default.-msplit-lohi,-mno-split-lohi,-mpost-inc,-mno-post-inc,-mpost-modify,-mno-post-modifyโ these are code generation tweaks ๐ They control, respectively, splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses. The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify.-mno-vect-doubleโ this changes the preferred SIMD mode to SImode ๐ The default is-mvect-double, which uses DImode as the preferred SIMD mode.-max-vect-align=numโ this is the maximum alignment for SIMD vector mode types.numcan be 4 or 8, and the default is 8 ๐ซถ Note that this is an ABI change, even though lots of library function interfaces are unaffected if they don't use SIMD vector modes in places that affect the size and/or alignment of relevant types.-msplit-vecmove-early,-mno-split-vecmove-earlyโ this splits vector moves into single word moves before reload ๐ง In theory it can give better register allocation, but so far the reverse seems to be generally the case ๐ญ-m1reg-regโ this specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster โก Allowable values for reg arer43andr63, which use that register as a fixed register, andnone, which means no register is used for this purpose. The default is-m1reg-none.
๐ AMD GCN Options ๐
These options are defined specifically for the AMD GCN port, so they're for the GPU girlies ๐ฎ
-march=gpu,-mtune=gpuโ this sets the architecture type or tuning forgpu๐ The supported values forgpuare:gfx900โ compile for GCN5 Vega 10 devices (gfx900).gfx902โ compile for GCN5 Vega gfx902 devices. (Experimental)gfx904โ compile for GCN5 Vega gfx904 devices. (Experimental)gfx906โ compile for GCN5 Vega 20 devices (gfx906).gfx908โ compile for CDNA1 Instinct MI100 series devices (gfx908).gfx909โ compile for GCN5 Vega gfx909 devices. (Experimental)gfx90aโ compile for CDNA2 Instinct MI200 series devices (gfx90a).gfx90cโ compile for GCN5 Vega 7 devices (gfx90c).gfx942โ compile for CDNA3 Instinct MI300 series devices (gfx942). (Experimental)gfx950โ compile for CDNA3 gfx950 devices. (Experimental)gfx9-genericโ compile generic code for Vega devices, executable on the following subset of GFX9 devices: gfx900, gfx902, gfx904, gfx906, gfx909 and gfx90c.gfx9-4-genericโ compile generic code for CDNA3 devices, executable on the following subset of GFX9 devices: gfx942 and gfx950. (Experimental)gfx1030โ compile for RDNA2 gfx1030 devices (GFX10 series).gfx1031โ compile for RDNA2 gfx1031 devices (GFX10 series). (Experimental)gfx1032โ compile for RDNA2 gfx1032 devices (GFX10 series). (Experimental)gfx1033โ compile for RDNA2 gfx1033 devices (GFX10 series). (Experimental)gfx1034โ compile for RDNA2 gfx1034 devices (GFX10 series). (Experimental)gfx1035โ compile for RDNA2 gfx1035 devices (GFX10 series). (Experimental)gfx1036โ compile for RDNA2 gfx1036 devices (GFX10 series).gfx10-3-genericโ compile generic code for GFX10-3 devices, executable on gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, and gfx1036.gfx1100โ compile for RDNA3 gfx1100 devices (GFX11 series).gfx1101โ compile for RDNA3 gfx1101 devices (GFX11 series). (Experimental)gfx1102โ compile for RDNA3 gfx1102 devices (GFX11 series). (Experimental)gfx1103โ compile for RDNA3 gfx1103 devices (GFX11 series).gfx1150โ compile for RDNA3 gfx1150 devices (GFX11 series). (Experimental)gfx1151โ compile for RDNA3 gfx1151 devices (GFX11 series). (Experimental)gfx1152โ compile for RDNA3 gfx1152 devices (GFX11 series). (Experimental)gfx1153โ compile for RDNA3 gfx1153 devices (GFX11 series). (Experimental)gfx11-genericโ compile generic code for GFX11 devices, executable on gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, and gfx1153.
-mgang-private-size=bytesโ this sets how much local data-share (LDS) memory gets reserved for gang-private variables ๐ The default is 512.-msram-ecc=on,-msram-ecc=off,-msram-ecc=anyโ these compile binaries for devices with the SRAM-ECC feature enabled, disabled, or either mode ๐ Some devices let you turn this on per-process, and your compiled code has to match the device's mode. The default isany, for devices that support it.-mxnack=on,-mxnack=off,-mxnack=anyโ these compile binaries for devices with the XNACK feature enabled, disabled, or either mode ๐ธ Some devices always require XNACK, and some let the user configure it. The compiled code must match the device mode. The default is-mxnack=anyon devices that support Unified Shared Memory, and-mxnack=nootherwise.-Wopenacc-dims,-Wno-openacc-dimsโ these control warnings about invalid OpenACC dimensions โ ๏ธ
๐ง ARC Options โจ
The following options control the architecture variant that code is being compiled for ๐ฆ
-mbarrel-shifterโ this generates instructions supported by the barrel shifter. It's the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ this forces a function call using thejli_sinstruction ๐ It's only valid for the ARCv2 architecture.-mcpu=cpuโ this sets the architecture type, register usage, and instruction scheduling parameters forcpu๐ There are shortcut alias options too, for backward compatibility and convenience. The supported values forcpuare:arc600โ compile for ARC600. Aliases:-mA6,-mARC600.arc601โ compile for ARC601. Alias:-mARC601.arc700โ compile for ARC700. Aliases:-mA7,-mARC700. This is the default when configured with--with-cpu=arc700.arcemโ compile for ARC EM.archsโ compile for ARC HS.emโ compile for ARC EM CPU with no hardware extensions.em4โ compile for ARC EM4 CPU.em4_dmipsโ compile for ARC EM4 DMIPS CPU.
em4_fpusโ ๐ธ Compile for the ARC EM4 DMIPS CPU with the single-precision floating-point extension.em4_fpudaโ ๐ Compile for the ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions.hsโ โจ Compile for the ARC HS CPU with no hardware extensions except the atomic instructions. Minimal, but still atomic ๐.hs34โ ๐ฆ Compile for the ARC HS34 CPU.hs38โ ๐ Compile for the ARC HS38 CPU.hs38_linuxโ ๐ Compile for the ARC HS38 CPU with all hardware extensions on. Full glam mode.hs4xโ ๐ Compile for the ARC HS4x CPU.hs4xdโ ๐ฅ Compile for the ARC HS4xD CPU.hs4x_rel31โ โญ Compile for the ARC HS4x CPU release 3.10a.arc600_normโ ๐ Compile for the ARC 600 CPU with "norm" instructions enabled.arc600_mul32x16โ ๐ง Compile for the ARC 600 CPU with "norm" and 32x16-bit multiply instructions enabled.arc600_mul64โ ๐ Compile for the ARC 600 CPU with "norm" and "mul64"-family instructions enabled.arc601_normโ ๐ธ Compile for the ARC 601 CPU with "norm" instructions enabled.arc601_mul32x16โ ๐ฆ Compile for the ARC 601 CPU with "norm" and 32x16-bit multiply instructions enabled.arc601_mul64โ ๐ Compile for the ARC 601 CPU with "norm" and "mul64"-family instructions enabled.nps400โ ๐ซถ Compile for ARC 700 on the NPS400 chip.em_miniโ ๐ Compile for the ARC EM minimalist configuration, which features a reduced register set. Less is more, bestie ๐ค.
-mdpfp,-mdpfp-compactโ ๐ Generate double-precision FPX instructions, tuned for the compact implementation.-mdpfp-fastโ ๐ฅ Generate double-precision FPX instructions, tuned for the fast implementation.-mno-dpfp-lrsr,-mdpfp-lrsrโ ๐ Control whether "lr" and "sr" instructions use FPX extension aux registers. This is enabled by default, so you're already set โจ.-meaโ ๐ Generate extended arithmetic instructions. Currently only "divaw", "adds", "subs", and "sat16" are supported. This is only valid for-mcpu=ARC700, so don't try it elsewhere ๐.-mmul32x16โ ๐ Generate 32x16-bit multiply and multiply-accumulate instructions.-mmul64โ ๐ง Generate "mul64" and "mulu64" instructions. Only valid for-mcpu=ARC600, so keep it in its lane ๐ .-mnormโ ๐ Generate "norm" instructions. This is the default if-mcpu=ARC700is in effect, so it's basically automatic.-mspfp,-mspfp-compactโ ๐ฆ Generate single-precision FPX instructions, tuned for the compact implementation.-mspfp-fastโ โญ Generate single-precision FPX instructions, tuned for the fast implementation.-msimdโ ๐ฅ Enable generation of ARC SIMD instructions via target-specific builtins. Only valid for-mcpu=ARC700. Main character SIMD energy ๐ .-msoft-floatโ ๐ This option is ignored. It's only here for compatibility, bestie. Software floating-point code is emitted by default, and that default can be overridden by the FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision. Not the one you're looking for ๐.-mswapโ ๐ Generate "swap" instructions.-matomicโ โจ This enables use of the locked load/store conditional extension to implement atomic memory built-in functions. It's not available for ARC 6xx or ARC EM cores, so skip it there ๐ซถ.-mdiv-remโ ๐ Enable "div" and "rem" instructions for ARCv2 cores.-mcode-density,-mno-code-densityโ ๐ธ Enable code density instructions for ARC EM. This option is on by default for ARC HS, so you only need the flag if you're on EM ๐ง.-mll64โ ๐ฆ Enable double load/store operations for ARC HS cores.-mtp-regno=regnoโ ๐ Specify the thread pointer register number.-mbitopsโ ๐ฅ Enable use of NPS400 bit operations.-mcmemโ ๐ Enable use of the NPS400 xld/xst extension.-mmpy-option=multoโ ๐ Compile ARCv2 code with a multiplier design option. You can specify the option using either a string or a numeric value formulto.wlh1is the default value. The recognized values are:0ornoneโ No multiplier available.1orwโ 16x16 multiplier, fully pipelined. The following instructions are enabled: "mpyw" and "mpyuw".2orwlh1โ 32x32 multiplier, fully pipelined (1 stage). The following instructions are additionally enabled: "mpy", "mpyu", "mpym", "mpymu", and "mpy_s".3orwlh2โ 32x32 multiplier, fully pipelined (2 stages). The following instructions are additionally enabled: "mpy", "mpyu", "mpym", "mpymu", and "mpy_s".4orwlh3โ Two 16x16 multipliers, blocking, sequential. The following instructions are additionally enabled: "mpy", "mpyu", "mpym", "mpymu", and "mpy_s".5orwlh4โ One 16x16 multiplier, blocking, sequential. The following instructions are additionally enabled: "mpy", "mpyu", "mpym", "mpymu", and "mpy_s".6orwlh5โ One 32x4 multiplier, blocking, sequential. The following instructions are additionally enabled: "mpy", "mpyu", "mpym", "mpymu", and "mpy_s".7orplus_dmpyโ ARC HS SIMD support. ๐8orplus_macdโ ARC HS SIMD support. ๐9orplus_qmacwโ ARC HS SIMD support. ๐
This option is only available for ARCv2 cores. โญ
-mfpu=fpuโ ๐ฆ Enables support for specific floating-point hardware extensions for ARCv2 cores. The supported values forfpuare:fpusโ Enables support for single-precision floating-point hardware extensions.fpudโ Enables support for double-precision floating-point hardware extensions. The single-precision floating-point extension is also enabled. Not available for ARC EM.fpudaโ Enables support for double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point extension is also enabled. This option is only available for ARC EM.fpuda_divโ Enables support for double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point, square-root, and divide extensions are also enabled. This option is only available for ARC EM.fpuda_fmaโ Enables support for double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point and fused multiply and add hardware extensions are also enabled. This option is only available for ARC EM.fpuda_allโ Enables support for double-precision floating-point hardware extensions using double-precision assist instructions. All single-precision floating-point hardware extensions are also enabled. This option is only available for ARC EM.fpus_divโ Enables support for single-precision floating-point, square-root and divide hardware extensions.fpud_divโ Enables support for double-precision floating-point, square-root and divide hardware extensions. This option includes optionfpus_div. Not available for ARC EM.fpus_fmaโ Enables support for single-precision floating-point and fused multiply and add hardware extensions.fpud_fmaโ Enables support for double-precision floating-point and fused multiply and add hardware extensions. This option includes optionfpus_fma. Not available for ARC EM.fpus_allโ Enables support for all single-precision floating-point hardware extensions.fpud_allโ Enables support for all single- and double-precision floating-point hardware extensions. Not available for ARC EM.
-mirq-ctrl-saved=register-range, blink, lp_countโ ๐ก๏ธ Specifies the general-purpose registers that the processor automatically saves and restores on interrupt entry and exit. The register-range is written as two registers separated by a dash. The range always starts with "r0", and the upper limit is the "fp" register.blinkandlp_countare optional. This option is only valid for ARC EM and ARC HS cores. ๐-mrgf-banked-regs=numberโ ๐ธ Specifies the number of registers replicated in the second register bank on entry to a fast interrupt. Fast interrupts are interrupts with the highest priority level, P0. These interrupts save only the PC and STATUS32 registers, so they avoid memory transactions during interrupt entry and exit sequences. Use this option when you're using fast interrupts on an ARC V2 family processor. Permitted values are 4, 8, 16, and 32. โก-mlpc-width=widthโ ๐งฎ Specify the width of the "lp_count" register. Valid values for width are 8, 16, 20, 24, 28, and 32 bits. The default width is fixed to 32 bits. If the width is less than 32, the compiler does not attempt to transform loops in your program to use the zero-delay loop mechanism unless it is known that the "lp_count" register can hold the required loop-counter value. Depending on the width specified, the compiler and run-time library might continue to use the loop mechanism for various needs. This option defines the macro__ARC_LPC_WIDTH__with the value of width. ๐ฆ-mrf16โ ๐ This option instructs the compiler to generate code for a 16-entry register file. This option defines the__ARC_RF16__preprocessor macro. โจ-mbranch-indexโ ๐ง Enable use of "bi" or "bih" instructions to implement jump tables. ๐
These next ones get passed down to the assembler and also define preprocessor macro symbols, so they're doing double duty ๐ .
-mlockโ ๐ Passed down to the assembler to enable the locked load/store conditional extension. It also sets the preprocessor symbol__Xlock.-mswapeโ ๐ Passed down to the assembler to enable the swap byte ordering extension instruction. It also sets the preprocessor symbol__Xswape.-mxyโ ๐ Passed down to the assembler to enable the XY memory extension. It also sets the preprocessor symbol__Xxy.
And this one's all about how the assembly code gets annotated ๐.
-misizeโ ๐ซง Annotate assembler instructions with estimated addresses.
Next up, the options that get passed through to the linker ๐:
-marclinux,-mno-arclinuxโ okay so this one passes stuff through to the linker and tells it to use the "arclinux" emulation ๐ It's on by default in toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets, but only when profiling is not requested ๐ธ-marclinux_prof,-mno-arclinux_profโ same vibe, but for the "arclinux_prof" emulation ๐ฎ This one is on by default for those samearc-linux-uclibcandarceb-linux-uclibctargets, except this time it's when profiling is requested โจ
Next up, these options control the semantics of generated code ๐ง
-mlong-callsโ calls get generated as register indirect calls, which gives you access to the full 32-bit address range ๐ main character energy, no limits ๐-mmedium-calls,-mno-medium-callsโ ngl this one is a whole mood ๐ฆ It stops calls from using less than the 25-bit addressing range, which is the offset an unconditional branch-and-link instruction gets. Conditional execution of function calls gets suppressed so you can use that 25-bit range, instead of the 21-bit range you'd get with conditional branch-and-link ๐ This is the default for toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets ๐-G numโ externally-visible data goes into a small data section, as long as it's no bigger thannumbytes ๐ The default fornumis4for any ARC configuration, or8when you've got double load/store operations ๐-mno-sdataโ don't generate sdata references ๐ โโ๏ธ This is the default for toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets ๐ซถ-mvolatile-cache,-mno-volatile-cacheโ this controls how volatile references get accessed ๐ง The default is-mvolatile-cache, which uses ordinary cached memory accesses for volatile references. If you want cache bypass for volatile references instead, go with-mno-volatile-cache๐ธ
Next, these options fine tune code generation ๐
-mauto-modify-regโ turns on the use of pre/post modify with register displacement โจ-mno-brcc,-mbrccโ this one controls a target-specific pass inarc_reorgthat generates compare-and-branch (brcc) instructions ๐ฅ It's enabled by default. Heads up, it has no effect on generation of these instructions when they're driven by the combiner pass ๐-mcase-vector-pcrelโ uses PC-relative switch case tables so case table shortening can happen ๐ฆ This is the default for-Os๐-mno-cond-execโ disables the ARCompact-specific pass that generates conditional execution instructions ๐ Okay real talk, the target-independent pass for conditional execution is often lacking, because of delay slot scheduling and interactions between operand numbers, literal sizes, instruction lengths, and conditional execution support. So the ARC port keeps a special pass around that hunts for more conditional execution opportunities after register allocation, branch shortening, and delay slot scheduling are done ๐ง This pass generally, but not always, improves performance and code size, but it costs extra compilation time, which is why there's an option to switch it off ๐ If call instructions are exceeding their allowable offset range because they got conditionalized, you should consider using-mmedium-callsinstead ๐ซถ-mearly-cbranchsiโ enables pre-reload use of the "cbranchsi" pattern ๐-mindexed-loadsโ enables the use of indexed loads ๐ This can be problematic though, because some optimizers then assume indexed stores exist, and that's not the case ๐ญ-mlra-priority-noneโ doesn't indicate any priority for target registers ๐ซ-mlra-priority-compactโ indicates target register priority forr0..r3/r12..r15๐-mlra-priority-noncompactโ reduces target register priority forr0..r3/r12..r15๐ธ-mmillicodeโ when you're optimizing for size with-Os, prologues and epilogues that have to save or restore a big pile of registers often get shortened by calling a special function in libgcc, which is called a millicode call ๐ง But these calls can cause performance issues, and/or linking issues when you link in a nonstandard way, so this option lets you turn millicode call generation on or off ๐-mcode-density-frameโ lets the compiler emit "enter" and "leave" instructions ๐ฆ These are only valid for CPUs with the code-density feature, so don't try it elsewhere ๐ โโ๏ธ-msize-level=levelโ fine-tunes size optimization with regards to instruction lengths and alignment ๐ The recognized values forlevelare:0โ no size optimization. This level is deprecated and treated like1๐ฌ1โ short instructions get used opportunistically ๐ท2โ on top of that, alignment of loops and of code after barriers gets dropped ๐3โ on top of that, optional data alignment gets dropped, and the optionOsis enabled ๐
This defaults to 3 when -Os is in effect. Otherwise, when this isn't set, the behavior is equivalent to level 1 ๐
-mtune=cpuโ sets instruction scheduling parameters forcpu, overriding anything implied by-mcpu=๐ฏ Supported values forcpuare:ARC600โ tunes for ARC600 CPU ๐งธARC601โ tunes for ARC601 CPU ๐งธARC700โ tunes for ARC700 CPU with standard multiplier block โจARC700-xmacโ tunes for ARC700 CPU with XMAC block ๐ฅARC725Dโ tunes for ARC725D CPU ๐ARC750Dโ tunes for ARC750D CPU ๐core3โ tunes for ARCv2 core3 type CPU. This option enables usage of the "dbnz" instruction ๐งrelease31aโ tunes for ARC4x release 3.10a ๐ฆ
-mmultcost=numโ sets the cost to assume for a multiply instruction, with4being equal to a normal instruction ๐
๐ฆ ARM Options ๐ฆ
These -m options are defined for the ARM port ๐ธ
-mabi=nameโ generates code for the specified ABI ๐ Permissible values are:apcs-gnu,atpcs,aapcsandaapcs-linuxโจ-mapcs-frameโ generates a stack frame that's compliant with the ARM Procedure Call Standard for all functions, even if it's not strictly necessary for the code to run correctly ๐งฑ If you specify-fomit-frame-pointerwith this option, stack frames don't get generated for leaf functions ๐ The default is-mno-apcs-frame. Heads up, this option is deprecated ๐ญ-mapcsโ a synonym for-mapcs-frame, and it's deprecated too ๐-mthumb-interworkโ generates code that supports calling between the ARM and Thumb instruction sets ๐ค Without this option, on pre-v5 architectures, the two instruction sets can't be reliably used inside one program ๐ The default is-mno-thumb-interwork, since slightly larger code gets generated when-mthumb-interworkis specified ๐ In AAPCS configurations this option is meaningless ๐ซ-msched-prolog,-mno-sched-prologโ allows or prevents reordering of instructions in the function prologue, or merging those instructions with the instructions in the function's body ๐ง With-mno-sched-prolog, all functions start with a recognizable set of instructions (or one of a choice from a small set of different function prologues), and that info can be used to locate the start of functions inside an executable piece of code ๐ The default is-msched-prolog๐-mfloat-abi=nameโ specifies which floating-point ABI to use ๐งฎ Permissible values are:soft,softfpandhard๐softmakes GCC generate output containing library calls for floating-point operations ๐softfpallows code generation using hardware floating-point instructions, but still uses the soft-float calling conventions ๐ ๏ธhardallows generation of floating-point instructions and uses FPU-specific calling conventions โก
The default depends on the specific target configuration ๐ฏ > Note that the hard-float and soft-float ABIs are not link-compatible. You have to compile your entire program with the same ABI, and link with a compatible set of libraries, or it's gonna be a whole disaster ๐
-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers ๐งบ This stops the compiler from using floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler ๐-mlittle-endianโ generates code for a processor running in little-endian mode ๐ This is the default for all standard configurations ๐ธ-mbig-endianโ generates code for a processor running in big-endian mode. The default is to compile code for a little-endian processor, so you have to ask for this one explicitly ๐-mbe8,-mbe32โ when linking a big-endian image, these let you select between BE8 and BE32 formats ๐งฉ The option has no effect for little-endian images and is ignored ๐ โโ๏ธ The default depends on the selected target architecture. For ARMv6 and later architectures the default is BE8, and for older architectures the default is BE32 ๐ฐ๏ธ Heads up, BE32 format has been deprecated by ARM ๐ญ-march=name[+extension...]โ specifies the name of the target ARM architecture ๐น GCC uses this name to figure out what kind of instructions it can emit when generating assembly code ๐งโ๐ป You can use this option together with-mcpu=, or instead of it ๐ซถ
Permissible names are: armv4t, armv5t, armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk, armv7, armv7-a, armv7ve, armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv8.6-a, armv9-a, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, armv8.1-m.main, iwmmxt and iwmmxt2 ๐งพ
Additionally, the following architectures, which lack support for the Thumb execution state, are recognized but support is deprecated: armv4 ๐ฅ
Lots of the architectures support extensions ๐งฉ You can add these by appending +extension to the architecture name. Extension options get processed in order, and capabilities accumulate. An extension will also enable any necessary base extensions it depends on. For example, the +crypto extension will always enable the +simd extension ๐ The exception to the additive construction is for extensions prefixed with +no...: these disable the specified option and any other extensions that may depend on the presence of that extension ๐ซ
For example, -march=armv7-a+simd+nofp+vfpv4 is equivalent to writing -march=armv7-a+vfpv4, since the +simd option is entirely disabled by the +nofp option that follows it ๐ซ โจ
Okay bestie, most of these extension names are super generic ๐ฅน but what they actually do depends on which architecture you put them on โจ Like, +simd works on both armv7-a and armv8-a, but on armv7-a it turns on the original ARMv7-A Advanced SIMD (Neon) extensions, and on armv8-a you get the ARMv8-A version ๐
Here's the tea ๐ซ The list below shows which extensions each architecture supports. If an architecture isn't mentioned, it straight up supports zero extensions ๐
armv5te,armv6,armv6j,armv6k,armv6kz,armv6t2,armv6z,armv6zk๐ง these all share the same two extensions:+fpโ The VFPv2 floating-point instructions.+vfpv2works as an alias for this one, so you can use either.+nofpโ Turns the floating-point instructions off.
armv7๐ the common subset of the ARMv7-A, ARMv7-R and ARMv7-M architectures.+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3-d16is an alias for this one. Heads up, bestie: the base ARMv7-M architecture doesn't support floating-point, but it's compatible with both ARMv7-A and ARMv7-R.+nofpโ Turns the floating-point instructions off.
armv7-a๐ the main character of the ARMv7 family, with the most extensions ๐ฅ+mpโ The multiprocessing extension.+secโ The security extension.+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3-d16is an alias for this one.+simdโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions.+neonand+neon-vfpv3can both be used as aliases for this one.+vfpv3โ The VFPv3 floating-point instructions, but with 32 double-precision registers.+vfpv3-d16-fp16โ The VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations.+vfpv3-fp16โ The VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations.+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers.+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, plus the half-precision floating-point conversion operations.+neon-vfpv4โ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions.+nosimdโ Disables the Advanced SIMD instructions. Floating-point stays on, though ๐+nofpโ Disables the floating-point and Advanced SIMD instructions.
armv7ve๐ฆ the extended version of ARMv7-A, with support for virtualization.+fpโ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4-d16is an alias for this one.+simdโ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions.+neon-vfpv4is an alias for this one.+vfpv3-d16โ The VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers.+vfpv3-d16-fp16โ The VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations.+vfpv3-fp16โ The VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations.+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers.+neonโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions.+neon-vfpv3is an alias for this one.+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, plus the half-precision floating-point conversion operations.+nosimdโ Disables the Advanced SIMD instructions. Floating-point stays on ๐ซถ+nofpโ Disables the floating-point and Advanced SIMD instructions.
armv8-a๐+crcโ The Cyclic Redundancy Check (CRC) instructions.+simdโ The ARMv8-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions.+nocryptoโ Disables the cryptographic instructions.+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions.+sbโ The Speculation Barrier Instruction.+predresโ The Execution and Data Prediction Restriction Instructions.
armv8.1-aโจ+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions. This also turns on the Advanced SIMD and floating-point instructions.+nocryptoโ Disables the cryptographic instructions.+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions.+sbโ The Speculation Barrier Instruction.+predresโ The Execution and Data Prediction Restriction Instructions.
armv8.2-a,armv8.3-a๐ these two share the same list:+fp16โ The half-precision floating-point data processing instructions. This also turns on the Advanced SIMD and floating-point instructions.+fp16fmlโ The half-precision floating-point fmla extension. This also turns on the half-precision floating-point extension, plus the Advanced SIMD and floating-point instructions.+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions. This also turns on the Advanced SIMD and floating-point instructions.+dotprodโ Enables the Dot Product extension. This also turns on the Advanced SIMD instructions.+nocryptoโ Disables the cryptographic extension.+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions.+sbโ The Speculation Barrier Instruction.+predresโ The Execution and Data Prediction Restriction Instructions.+i8mmโ The 8-bit Integer Matrix Multiply instructions. This also turns on the Advanced SIMD and floating-point instructions.+bf16โ The Brain half-precision floating-point instructions. This also turns on the Advanced SIMD and floating-point instructions.
armv8.4-a๐ฅ+fp16โ The half-precision floating-point data processing instructions. This also turns on the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-point fmla extension.+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension.+cryptoโ The cryptographic instructions. This also turns on the Advanced SIMD and floating-point instructions, plus the Dot Product extension.+nocryptoโ Disables the cryptographic extension.+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions.+sbโ The Speculation Barrier Instruction.+predresโ The Execution and Data Prediction Restriction Instructions.+i8mmโ The 8-bit Integer Matrix Multiply instructions. This also turns on the Advanced SIMD and floating-point instructions.+bf16โ The Brain half-precision floating-point instructions. This also turns on the Advanced SIMD and floating-point instructions.
armv8.5-a๐ธ+fp16โ The half-precision floating-point data processing instructions. This also turns on the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-point fmla extension.+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension.+cryptoโ The cryptographic instructions. This also turns on the Advanced SIMD and floating-point instructions, plus the Dot Product extension.+nocryptoโ Disables the cryptographic extension.+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions.+i8mmโ The 8-bit Integer Matrix Multiply instructions. This also turns on the Advanced SIMD and floating-point instructions.+bf16โ The Brain half-precision floating-point instructions. This also turns on the Advanced SIMD and floating-point instructions.
armv8.6-a๐ง+fp16โ The half-precision floating-point data processing instructions. This also turns on the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-point fmla extension.+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension.
+cryptoโ ๐ The cryptographic instructions, and this one also flips on the Advanced SIMD and floating-point instructions plus the Dot Product extension โจ+nocryptoโ ๐ Disable the cryptographic extension+nofpโ ๐ Disable the floating-point, Advanced SIMD and cryptographic instructions. Everything spicy, gone+i8mmโ ๐งฎ The 8-bit Integer Matrix Multiply instructions. This one also enables Advanced SIMD and floating-point instructions+bf16โ ๐ง The Brain half-precision floating-point instructions. This one also enables Advanced SIMD and floating-point instructions
๐ฆ armv7-r
+fp.spโ ๐ The single-precision VFPv3 floating-point instructions.+vfpv3xdworks as an alias for this extension too+fpโ ๐ The VFPv3 floating-point instructions with 16 double-precision registers.+vfpv3-d16can be used as an alias for this extension+vfpv3xd-d16-fp16โ ๐ The single-precision VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations+vfpv3-d16-fp16โ โจ The VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations+nofpโ ๐ Disable the floating-point extension+idivโ โ The ARM-state integer division instructions+noidivโ ๐ซ Disable the ARM-state integer division extension
๐ธ armv7e-m
+fpโ ๐ The single-precision VFPv4 floating-point instructions+fpv5โ ๐ท The single-precision FPv5 floating-point instructions+fp.dpโ ๐ The single- and double-precision FPv5 floating-point instructions+nofpโ ๐ Disable the floating-point extensions
๐ง armv8.1-m.main
+dspโ ๐ถ The DSP instructions+mveโ ๐ฆ The M-Profile Vector Extension (MVE) integer instructions+mve.fpโ ๐ฆ The M-Profile Vector Extension (MVE) integer and single precision floating-point instructions+fpโ โญ The single-precision floating-point instructions+fp.dpโ โญ The single- and double-precision floating-point instructions+nofpโ ๐ Disable the floating-point extension+cdecp0,+cdecp1, ... ,+cdecp7โ ๐ง Enable the Custom Datapath Extension (CDE) on selected coprocessors, according to the numbers given in the options in the range 0 to 7+pacbtiโ ๐ก๏ธ Enable the Pointer Authentication and Branch Target Identification Extension
๐ armv8-m.main
+dspโ ๐ถ The DSP instructions+nodspโ ๐ Disable the DSP extension+fpโ โญ The single-precision floating-point instructions+fp.dpโ โญ The single- and double-precision floating-point instructions+nofpโ ๐ Disable the floating-point extension+cdecp0,+cdecp1, ... ,+cdecp7โ ๐ง Enable the Custom Datapath Extension (CDE) on selected coprocessors, according to the numbers given in the options in the range 0 to 7
๐
armv8-r
+crcโ ๐งพ The Cyclic Redundancy Check (CRC) instructions+fp.spโ โญ The single-precision FPv5 floating-point instructions+simdโ ๐ฅ The ARMv8-A Advanced SIMD and floating-point instructions+cryptoโ ๐ The cryptographic instructions+nocryptoโ ๐ Disable the cryptographic instructions+nofpโ ๐ Disable the floating-point, Advanced SIMD and cryptographic instructions
-march=native causes the compiler to auto-detect the architecture of the build computer. โจ At present, this feature is only supported on GNU/Linux, and not all architectures are recognized. If the auto-detect is unsuccessful, the option has no effect ๐
-march=unset causes the compiler to ignore any -march=... options that appear earlier on the command line and behave as if the option was never passed. ๐งน This is useful to avoid warnings about conflicting CPU and architecture options when the two produce different architecture specifications.
๐ -mtune=name
This option specifies the name of the target ARM processor that GCC should tune the performance of the code for. ๐ฏ For some ARM implementations, you can get better performance by using this option. Permissible names are: arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi, arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, ares, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-r52plus, cortex-m0, cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m52, cortex-m55, cortex-m85, cortex-x1, cortex-x1c, cortex-m1.small-multiply, cortex-m0.small-multiply, cortex-m0plus.small-multiply, exynos-m1, marvell-pj4, neoverse-n1, neoverse-n2, neoverse-v1, xscale, iwmmxt, iwmmxt2, ep9312, fa526, fa626, fa606te, fa626te, fmp626, fa726te, star-mc1, xgene1.
Okay, and it gets even better ๐ญ This option can also tell GCC to tune the performance of the code for a big.LITTLE system. Permissible names are: cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a72.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55.
-mtune=generic-arch tells GCC to tune the performance for a blend of processors within architecture arch. ๐ The goal is code that runs well on the most popular processors right now, balancing optimizations that benefit some CPUs in the range while avoiding performance pitfalls of the other CPUs. The effects of this option may change in future GCC versions as CPU models come and go ๐ฐ๏ธ
-mtune permits the same extension options as -mcpu, but the extension options do not affect the tuning of the generated code ๐คท
-mtune=native causes the compiler to auto-detect the CPU of the build computer. โจ At present, this feature is only supported on GNU/Linux, and not all architectures are recognized. If the auto-detect is unsuccessful, the option has no effect ๐
๐ -mcpu=name[+extension...]
This specifies the name of the target ARM processor. ๐ GCC uses this name to work out the target ARM architecture (as if you'd specified -march) and the ARM processor type to tune for performance (as if you'd specified -mtune). If you use this option together with -march or -mtune, those options take precedence over the matching part of this option ๐
Lots of the supported CPUs have optional architectural extensions. ๐งฉ When that's the case, the extensions are normally enabled by default. If implementations that lack the extension exist, you can use the extension syntax to disable the ones that have been left out. For floating-point and Advanced SIMD (Neon) instructions, you also have to think about the settings of -mfloat-abi and -mfpu: floating-point and Advanced SIMD instructions will only be used if -mfloat-abi is not set to soft, and any setting of -mfpu other than auto will override the available floating-point and SIMD extension instructions. ๐ซถ
For example, cortex-a9 comes in three major configurations: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD. The default is to enable all the instructions, but the extensions +nosimd and +nofp can be used to disable just the SIMD or both the SIMD and floating-point instructions, respectively ๐ฆ
Permissible names for this option are the same as those for -mtune.
The following extension options are common to the listed CPUs ๐
+nodspโ ๐ Disable the DSP instructions oncortex-m33,cortex-m35p,cortex-m52,cortex-m55andcortex-m85. It also disables the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85+nopacbtiโ ๐ Disable the Pointer Authentication and Branch Target Identification Extension oncortex-m52andcortex-m85+nomveโ ๐ Disable the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85+nomve.fpโ ๐ Disable the M-Profile Vector Extension (MVE) single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85+cdecp0,+cdecp1, ... ,+cdecp7โ ๐ง Enable the Custom Datapath Extension (CDE) on selected coprocessors, according to the numbers given in the options in the range 0 to 7 oncortex-m52,cortex-m55andstar-mc1+nofpโ ๐ Disables the floating-point instructions onarm9e,arm946e-s,arm966e-s,arm968e-s,arm10e,arm1020e,arm1022e,arm926ej-s,arm1026ej-s,cortex-r5,cortex-r7,cortex-r8,cortex-m4,cortex-m7,cortex-m33,cortex-m35p,cortex-m52,cortex-m55andcortex-m85. It also disables the floating-point and SIMD instructions ongeneric-armv7-a,cortex-a5,cortex-a7,cortex-a8,cortex-a9,cortex-a12,cortex-a15,cortex-a17,cortex-a15.cortex-a7,cortex-a17.cortex-a7,cortex-a32,cortex-a35,cortex-a53andcortex-a55๐ญ+nofp.dpโ okay so this one switches OFF the double-precision bit of the floating-point instructions on cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-r52plus and cortex-m7 ๐+nosimdโ this one turns off the SIMD instructions (but keeps the floating-point ones) on generic-armv7-a, cortex-a5, cortex-a7 and cortex-a9 ๐ธ+cryptoโ bestie, this one ENABLES the cryptographic instructions on cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, exynos-m1, xgene1, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53 and cortex-a75.cortex-a55 ๐ฅ
Also, the generic-armv7-a pseudo target defaults to VFPv3 with 16 double-precision registers ๐ฆ. It supports these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16, neon-vfpv4. They mean the same thing as the extensions to -march=armv7-a โจ.
-mcpu=generic-arch is also allowed, and it's the same as -march=arch -mtune=generic-arch. Check out -mtune for more deets ๐ง.
-mcpu=native tells the compiler to auto-detect the CPU of the build computer ๐. Right now this only works on GNU/Linux, and not every architecture gets recognized. If the auto-detect doesn't work out, the option does nothing ๐.
-mcpu=unset makes the compiler ignore any -mcpu=... options that show up earlier on the command line, so it acts like that option was never passed at all ๐ซถ. This is super useful for avoiding warnings about conflicting CPU and architecture options when the two give different architecture specs ๐.
-mfpu=name ๐
This picks what floating-point hardware (or hardware emulation) is available on the target ๐. The permissible names are: auto, vfpv2, vfpv3, vfpv3-fp16, vfpv3-d16, vfpv3-d16-fp16, vfpv3xd, vfpv3xd-fp16, neon-vfpv3, neon-fp16, vfpv4, vfpv4-d16, fpv4-sp-d16, neon-vfpv4, fpv5-d16, fpv5-sp-d16, fp-armv8, neon-fp-armv8 and crypto-neon-fp-armv8. Also, neon is an alias for neon-vfpv3, and vfp is an alias for vfpv2 ๐.
The setting auto is the default and it's kind of special โจ. It makes the compiler pick the floating-point and Advanced SIMD instructions based on the settings of -mcpu and -march ๐
.
Heads up, bestie: if the selected floating-point hardware includes the NEON extension (e.g.-mfpu=neon), floating-point operations are NOT generated by GCC's auto-vectorization pass unless-funsafe-math-optimizationsis also specified ๐ญ. This is because NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic (in particular, denormal values are treated as zero), so using NEON instructions may lead to a loss of precision ๐.
You can also set the fpu name at function level by using the target("fpu=") function attributes or pragmas ๐.
-mfp16-format=name ๐ธ
This specifies the format of the "__fp16" half-precision floating-point type ๐ฆ. The permissible names are none, ieee, and alternative. The default is none, which means the "__fp16" type is not defined at all ๐.
-mstructure-size-boundary=n ๐ซถ
The sizes of all structures and unions get rounded up to a multiple of the number of bits set by this option โจ. The permissible values are 8, 32 and 64. The default value varies for different toolchains. For the COFF targeted toolchain, the default is 8. A value of 64 is only allowed if the underlying ABI supports it ๐.
Bigger numbers can produce faster, more efficient code, but they can also make your program bigger ๐ง. Different values are potentially incompatible ๐ . Code compiled with one value can't necessarily be expected to work with code or libraries compiled with another value, if they swap info using structures or unions ๐ญ.
This option is deprecated, so maybe don't build your life around it ๐.
-mabort-on-noreturn ๐
This generates a call to the function abort at the end of a noreturn function ๐ฅ. It runs if the function tries to return โญ.
-mlong-calls, -mno-long-calls ๐
These tell the compiler to make function calls by first loading the address of the function into a register, and then doing a subroutine call on that register ๐ฆ. You need this switch if the target function lives outside the 64-megabyte addressing range of the offset-based version of the subroutine call instruction ๐ธ.
Even with this switch on, not every function call gets turned into a long call ๐. The heuristic is that static functions, functions with the short_call attribute, functions inside the scope of a #pragma no_long_calls directive, and functions whose definitions have already been compiled within the current compilation unit are NOT turned into long calls ๐
. The exceptions are that weak function definitions, functions with the long_call attribute or the section attribute, and functions inside the scope of a #pragma long_calls directive are ALWAYS turned into long calls ๐ญ.
This feature is not enabled by default โจ. Specifying -mno-long-calls restores the default behavior, and so does putting the function calls inside the scope of a #pragma long_calls_off directive ๐ซถ. Heads up that these switches have no effect on how the compiler generates code for handling function calls via function pointers ๐.
-msingle-pic-base ๐ง
This treats the register used for PIC addressing as read-only, instead of loading it in the prologue for each function ๐. The runtime system is responsible for initializing this register with an appropriate value before execution begins ๐.
-mpic-register=reg ๐
This specifies the register to be used for PIC addressing ๐. For the standard PIC base case, the default is any suitable register the compiler picks. For the single PIC base case, the default is R9 if the target is EABI based or stack-checking is enabled, and otherwise the default is R10 ๐.
-mpic-data-is-text-relative โญ
This assumes the displacement between the text and data segments is fixed at static link time ๐ฅ. That lets you use PC-relative addressing operations to access data known to be in the data segment ๐ฆ. For non-VxWorks RTP targets, this option is enabled by default. When it's disabled on those targets, it enables -msingle-pic-base by default ๐.
-mpoke-function-name ๐ธ
This writes the name of each function into the text section, directly before the function prologue ๐. The generated code looks kinda like this:
t0
.ascii "arm_poke_function_name", 0
.align
t1
.word 0xff000000 + (t1 - t0)
arm_poke_function_name
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
When doing a stack backtrace, code can inspect the value of pc stored at fp + 0 ๐ซถ. If the trace function then looks at location pc - 12 and the top 8 bits are set, then we know there's a function name embedded right before this location, with length ((pc[-3]) & 0xff000000) ๐ฅ.
-mthumb, -marm ๐ฆ
These let you pick between generating code that runs in ARM state and code that runs in Thumb state ๐
. The default for most configurations is ARM state, but you can change that by configuring GCC with the --with-mode=state configure option ๐.
You can also override ARM and Thumb mode for each function by using the target("thumb") and target("arm") function attributes or pragmas โจ.
-mtpcs-frame ๐
This generates a stack frame that's compliant with the Thumb Procedure Call Standard for all non-leaf functions ๐. (A leaf function is one that doesn't call any other functions.) The default is -mno-tpcs-frame ๐.
-mtpcs-leaf-frame โญ
This generates a stack frame that's compliant with the Thumb Procedure Call Standard for all leaf functions ๐ง. (A leaf function is one that doesn't call any other functions.) The default is -mno-apcs-leaf-frame ๐.
-mcallee-super-interworking ๐
This gives all externally visible functions in the file being compiled an ARM instruction set header, which switches to Thumb mode before executing the rest of the function ๐ธ. That way these functions can be called from non-interworking code ๐ซถ. This option is not valid in AAPCS configurations, because interworking is already enabled by default ๐.
-mcaller-super-interworking ๐ฅ
This lets calls via function pointers (including virtual functions) execute correctly, whether or not the target code was compiled for interworking ๐ฆ. There's a small overhead in the cost of executing a function pointer when this option is enabled ๐ญ. This option is not valid in AAPCS configurations, because interworking is already enabled by default ๐.
-mtp=name ๐
This specifies the access model for the thread local storage pointer โจ. The model soft generates calls to __aeabi_read_tp. The other accepted models are tpidrurw, tpidruro and tpidrprw, which fetch the thread pointer directly from the corresponding system register (supported from the arm6k architecture and later) ๐
. These system registers are accessed through the CP15 co-processor interface, and the argument cp15 is also accepted as a convenience alias of tpidruro ๐.
softโ calls__aeabi_read_tptpidrurw,tpidruro,tpidrprwโ read the thread pointer straight from the system register (arm6k and later) ๐ฆcp15โ a convenience alias oftpidruro๐autoโ uses the best available method for the selected processor ๐ง
The default setting is auto ๐ซถ.
-mtls-dialect=dialect ๐
This specifies the dialect to use for accessing thread local storage ๐ธ. Two dialects are supported: gnu and gnu2 ๐. The gnu dialect selects the original GNU scheme for supporting local and global dynamic TLS models ๐
. The gnu2 dialect selects the GNU descriptor scheme, which gives better performance for shared libraries ๐. The GNU descriptor scheme is compatible with the original scheme, but it does require new assembler, linker and library support ๐ญ. Initial and local exec TLS models are unaffected by this option and always use the original scheme โจ.
-mword-relocations ๐ฅ
This only generates absolute relocations on word-sized values (i.e. R_ARM_ABS32) ๐ฆ. It's enabled by default on targets (uClinux, SymbianOS) where the runtime loader imposes this restriction, and when -fpic or -fPIC is specified ๐.
Watch out: this option conflicts with -mslow-flash-data ๐.
-mfix-cortex-m3-ldrd Some Cortex-M3 cores can corrupt data when ldrd instructions have overlapping destination and base registers. This option stops GCC from generating those instructions, and it's switched on by default when -mcpu=cortex-m3 is specified. ๐ก๏ธโจ
-mfix-cortex-a57-aes-1742098 -mno-fix-cortex-a57-aes-1742098 -mfix-cortex-a72-aes-1655431 -mno-fix-cortex-a72-aes-1655431 Turns the mitigation for an erratum on Cortex-A57 and Cortex-A72 that messes with the AES crypto instructions on or off. It's on by default when either -mcpu=cortex-a57 or -mcpu=cortex-a72 is specified. ๐๐
-munaligned-access -mno-unaligned-access Lets you turn reading and writing of 16- and 32-bit values from addresses that aren't 16- or 32-bit aligned on (or off). By default it's off for all pre-ARMv6, all ARMv6-M, and ARMv8-M Baseline architectures, and on for all other architectures. If unaligned access isn't enabled, words in packed data structures get accessed one byte at a time. ๐งฉ
The ARM attribute Tag_CPU_unaligned_access gets set in the generated object file to either true or false, depending on this option. If unaligned access is enabled, the preprocessor symbol __ARM_FEATURE_UNALIGNED is also defined. ๐ท๏ธ
-mslow-flash-data Assumes loading data from flash is slower than fetching instructions, so literal loads get minimized for better performance. This is only supported when compiling for ARMv7 M-profile, and it's off by default. It conflicts with -mword-relocations. ๐ขโก
-masm-syntax-unified Assumes inline assembler is using unified asm syntax. Right now it's off by default, which means divided syntax. This option has no impact on Thumb2, but that might change in future GCC releases. Divided syntax should be considered deprecated, so bye bye ๐๐
-mrestrict-it Restricts IT block generation so it follows the ARMv8-A rules. IT blocks can only contain a single 16-bit instruction from a select set of instructions. This is on by default for ARMv8-A Thumb mode. ๐
-mpure-code Stops constant data from being placed in code sections. Also, when compiling for ELF object format, it gives all text sections the ELF processor-specific section attribute SHF_ARM_PURECODE. This is only available when generating non-PIC code for M-profile targets. ๐ธ
-mcmse Generates secure code according to the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification", which you can find at <https://developer.arm.com/documentation/ecm0359818/latest/>. Very official, very important ๐๐
-mfix-cmse-cve-2021-35465 Mitigates a potential security issue with the VLLDM instruction on some M-profile devices when using CMSE (CVE-2021-365465). This is enabled by default when -mcpu= is used with cortex-m33, cortex-m35p, cortex-m52, cortex-m55, cortex-m85, or star-mc1. You can use -mno-fix-cmse-cve-2021-35465 to disable the mitigation. ๐ก๏ธ๐ซถ
-mstack-protector-guard=guard -mstack-protector-guard-offset=offset Generates stack protection code using a canary at guard. The supported locations are global for a global canary, or tls for a canary accessible through the TLS register. The option -mstack-protector-guard-offset= is for use with -fstack-protector-guard=tls, and it is not for use in user-land code. ๐ง
-mfdpic -mno-fdpic Selects the FDPIC ABI, which uses 64-bit function descriptors to represent pointers to functions. When the compiler is configured for arm-*-uclinuxfdpiceabi targets, this is on by default and implies -fPIE if none of the PIC/PIE-related options are provided. On other targets, it only enables the FDPIC-specific code generation features, so you'll need to explicitly provide the PIC/PIE-related options as needed. ๐ฆ
Static linking isn't supported, because it would still involve the dynamic linker when the program self-relocates. If that behavior is acceptable to you, use -static and -Wl,-dynamic-linker options. ๐
The opposite option, -mno-fdpic, is useful (and required) for building the Linux kernel with the same (arm-*-uclinuxfdpiceabi) toolchain you used to build userland programs. ๐ง
-mbranch-protection=features Enables branch protection features (armv8.1-m.main only). โจ
features can be one of the following forms:
none generates code without branch protection or return address signing. ๐ซ
standard generates code with all branch protection features enabled at their standard level. ๐ฏ
pac-ret generates code with return address signing set to its standard level, which means signing all functions that save the return address to memory. ๐
pac-ret+leaf extends pac-ret signing to include leaf functions, even if they don't write the return address to memory. ๐
bti adds landing-pad instructions at the permitted targets of indirect branch instructions. ๐ฌ
If support for the +pacbti architecture extension isn't enabled (for example, via -march=), then all branch protection and return address signing operations are constrained to use only the instructions defined in the architectural-NOP space. The generated code stays backwards-compatible with earlier versions of the architecture, but the extra security can be turned on at runtime on processors that support the PACBTI extension. ๐ง
Branch target enforcement using BTI can only be enabled at runtime if all code in the application has been compiled with at least -mbranch-protection=bti.
Any setting other than none is supported only on armv8-m.main or later. ๐
The default is to generate code without branch protection or return address signing. ๐
-mvectorize-with-neon-quad -mvectorize-with-neon-double Controls whether vectorization uses NEON quad-word or double-word registers. The default is -mvectorize-with-neon-quad. ๐
AVR Options
These options are defined for AVR implementations: ๐ฆ
-mmcu=mcu Specifies the AVR instruction set architecture (ISA) or device type. The default for this option is avr2. ๐ฏ
Here's the lineup of AVR devices and ISAs that are supported. Heads up, bestie: a complete device support setup needs startup code crtmcu.o, a device header avr/io*.h, a device library libmcu.a, and a device-specs file specs-mcu (see <https://gcc.gnu.org/wiki/avr-gcc#spec-files>). Only the specs file is provided by the compiler, according to the supported mcus below. The rest comes from AVR-LibC (<https://github.com/avrdudes/avr-libc/>), or from atpack files (<https://gcc.gnu.org/wiki/avr-gcc#atpack>) supplied by the hardware manufacturer. ๐ฆ๐
avr2 "Classic" devices with up to 8 KiB of program memory. mcu = attiny22, attiny26, at90s2313, at90s2323, at90s2333, at90s2343, at90s4414, at90s4433, at90s4434, at90c8534, at90s8515, at90s8535. ๐ท
avr25 "Classic" devices with up to 8 KiB of program memory and the MOVW instruction. mcu = attiny13, attiny13a, attiny24, attiny24a, attiny25, attiny261, attiny261a, attiny2313, attiny2313a, attiny43u, attiny44, attiny44a, attiny45, attiny48, attiny441, attiny461, attiny461a, attiny4313, attiny84, attiny84a, attiny85, attiny87, attiny88, attiny828, attiny841, attiny861, attiny861a, ata5272, ata6616c, at86rf401. ๐ซง
avr3 "Classic" devices with 16 KiB up to 64 KiB of program memory. mcu = at76c711, at43usb355. ๐บ
avr31 "Classic" devices with 128 KiB of program memory. mcu = atmega103, at43usb320. ๐ฐ
avr35 "Classic" devices with 16 KiB up to 64 KiB of program memory and the MOVW instruction. mcu = attiny167, attiny1634, atmega8u2, atmega16u2, atmega32u2, ata5505, ata6617c, ata664251, at90usb82, at90usb162. ๐
avr4 "Enhanced" devices with up to 8 KiB of program memory. mcu = atmega48, atmega48a, atmega48p, atmega48pa, atmega48pb, atmega8, atmega8a, atmega8hva, atmega88, atmega88a, atmega88p, atmega88pa, atmega88pb, atmega8515, atmega8535, ata5795, ata6285, ata6286, ata6289, ata6612c, at90pwm1, at90pwm2, at90pwm2b, at90pwm3, at90pwm3b, at90pwm81. ๐ฆ
avr5 "Enhanced" devices with 16 KiB up to 64 KiB of program memory. mcu = atmega16, atmega16a, atmega16hva, atmega16hva2, atmega16hvb, atmega16hvbrevb, atmega16m1, atmega16u4, atmega161, atmega162, atmega163, atmega164a, atmega164p, atmega164pa, atmega165, atmega165a, atmega165p, atmega165pa, atmega168, atmega168a, atmega168p, atmega168pa, atmega168pb, atmega169, atmega169a, atmega169p, atmega169pa, atmega32, atmega32a, atmega32c1, atmega32hvb, atmega32hvbrevb, atmega32m1, atmega32u4, atmega32u6, atmega323, atmega324a, atmega324p, atmega324pa, atmega324pb, atmega325, atmega325a, atmega325p, atmega325pa, atmega328, atmega328p, atmega328pb, atmega329, atmega329a, atmega329p, atmega329pa, atmega3250, atmega3250a, atmega3250p, atmega3250pa, atmega3290, atmega3290a, atmega3290p, atmega3290pa, atmega406, atmega64, atmega64a, atmega64c1, atmega64hve, atmega64hve2, atmega64m1, atmega64rfr2, atmega640, atmega644, atmega644a, atmega644p, atmega644pa, atmega644rfr2, atmega645, atmega645a, atmega645p, atmega649, atmega649a, atmega649p, atmega6450, atmega6450a, atmega6450p, atmega6490, atmega6490a, atmega6490p, ata5790, ata5790n, ata5791, ata6613c, ata6614q, ata5782, ata5831, ata8210, ata8510, ata5787, ata5835, ata5700m322, ata5702m322, at90pwm161, at90pwm216, at90pwm316, at90can32, at90can64, at90scr100, at90usb646, at90usb647, at94k, m3000. ๐
โจ
avr51โ ๐ "Enhanced" devices with 128 KiB of program memory, the glow-up crew โจ. mcu values:atmega128,atmega128a,atmega128rfa1,atmega128rfr2,atmega1280,atmega1281,atmega1284,atmega1284p,atmega1284rfr2,at90can128,at90usb1286,at90usb1287.avr6โ ๐ฆ "Enhanced" devices with a 3-byte PC, so anything with more than 128 KiB of program memory. mcu values:atmega256rfr2,atmega2560,atmega2561,atmega2564rfr2.avrxmega2โ ๐ธ "XMEGA" devices with more than 8 KiB and up to 64 KiB of program memory. mcu values:atxmega8e5,atxmega16a4,atxmega16a4u,atxmega16c4,atxmega16d4,atxmega16e5,atxmega32a4,atxmega32a4u,atxmega32c3,atxmega32c4,atxmega32d3,atxmega32d4,atxmega32e5,avr64da28,avr64da28s,avr64da32,avr64da32s,avr64da48,avr64da48s,avr64da64,avr64da64s,avr64db28,avr64db32,avr64db48,avr64db64,avr64dd14,avr64dd20,avr64dd28,avr64dd32,avr64du28,avr64du32,avr64ea28,avr64ea32,avr64ea48,avr64sd28,avr64sd32,avr64sd48.avrxmega3โ ๐ง "XMEGA" devices with up to 64 KiB of combined program memory and RAM, where the program memory is visible in the RAM address space. Major main-character energy ๐. mcu values:attiny202,attiny204,attiny212,attiny214,attiny402,attiny404,attiny406,attiny412,attiny414,attiny416,attiny416auto,attiny417,attiny424,attiny426,attiny427,attiny804,attiny806,attiny807,attiny814,attiny816,attiny817,attiny824,attiny826,attiny827,attiny1604,attiny1606,attiny1607,attiny1614,attiny1616,attiny1617,attiny1624,attiny1626,attiny1627,attiny3214,attiny3216,attiny3217,attiny3224,attiny3226,attiny3227,atmega808,atmega809,atmega1608,atmega1609,atmega3208,atmega3209,atmega4808,atmega4809,avr16dd14,avr16dd20,avr16dd28,avr16dd32,avr16du14,avr16du20,avr16du28,avr16du32,avr16ea28,avr16ea32,avr16ea48,avr16eb14,avr16eb20,avr16eb28,avr16eb32,avr16la14,avr16la20,avr16la28,avr16la32,avr32da28,avr32da28s,avr32da32,avr32da32s,avr32da48,avr32da48s,avr32db28,avr32db32,avr32db48,avr32dd14,avr32dd20,avr32dd28,avr32dd32,avr32du14,avr32du20,avr32du28,avr32du32,avr32ea28,avr32ea32,avr32ea48,avr32eb14,avr32eb20,avr32eb28,avr32eb32,avr32la14,avr32la20,avr32la28,avr32la32,avr32sd20,avr32sd28,avr32sd32.avrxmega4โ ๐ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory. mcu values:atxmega64a3,atxmega64a3u,atxmega64a4u,atxmega64b1,atxmega64b3,atxmega64c3,atxmega64d3,atxmega64d4,avr128da28,avr128da28s,avr128da32,avr128da32s,avr128da48,avr128da48s,avr128da64,avr128da64s,avr128db28,avr128db32,avr128db48,avr128db64.avrxmega5โ ๐ฅ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory, plus more than 64 KiB of RAM. mcu values:atxmega64a1,atxmega64a1u.avrxmega6โ ๐ "XMEGA" devices with more than 128 KiB of program memory. mcu values:atxmega128a3,atxmega128a3u,atxmega128b1,atxmega128b3,atxmega128c3,atxmega128d3,atxmega128d4,atxmega192a3,atxmega192a3u,atxmega192c3,atxmega192d3,atxmega256a3,atxmega256a3b,atxmega256a3bu,atxmega256a3u,atxmega256c3,atxmega256d3,atxmega384c3,atxmega384d3.avrxmega7โ ๐ "XMEGA" devices with more than 128 KiB of program memory and more than 64 KiB of RAM. mcu values:atxmega128a1,atxmega128a1u,atxmega128a4u.avrtinyโ ๐ "Reduced Tiny" Tiny core devices with only 16 general purpose registers and 512 B up to 4 KiB of program memory. mcu values:attiny4,attiny5,attiny9,attiny10,attiny102,attiny104,attiny20,attiny40.avr1โ ๐ This ISA is implemented by the minimal AVR core and is only supported for the assembler, so no compiling for it. mcu values:attiny11,attiny12,attiny15,attiny28,at90s1200.-mabsdataโ ๐ซถ Assume that all data in static storage can be reached with LDS / STS instructions. This only does anything on reduced Tiny devices like ATtiny40.- See also the "absdata" AVR Attributes,variable attribute.
-mcvtโ ๐ Use a compact vector table. Some devices support a CVT with only four entries:0=Reset,1=NMI,2=Prio1 IRQ,3=Prio0 IRQs. This option links the startup code fromcrtmcu-cvt.oinstead of the usualcrtmcu.o. Besides giving you the compact table, the startup code sets the bitCPUINT_CTRLA.CPUINT_CVT, which turns on the CVT on the device.- When you don't want the startup code to set
CPUINT_CTRLA.CPUINT_CVT, you can satisfy the symbol__init_cvtso that the code isn't pulled in fromlibmcu.aanymore. For example, you can link with-Wl,--defsym,__init_cvt=0. - The CVT startup code is available since AVR-LibC v2.3 (
https://github.com/avrdudes/avr-libc/issues/1010).
- When you don't want the startup code to set
-mdouble=bits,-mlong-double=bitsโ ๐ง Set the size (in bits) of thedoubleorlong doubletype, respectively. The only possible values for bits are 32 and 64. Whether a given value is allowed depends on the--with-double=and--with-long-double=configure options (https://gcc.gnu.org/install/configure.html#avr), and the same goes for the default values of the options.-mgas-isr-prologuesโ โญ Interrupt service routines (ISRs) may use the__gcc_isrpseudo instruction, which is supported by GNU Binutils. If this option is on, you can still turn the feature off for individual ISRs with the AVR Attributes,,"no_gccisr" function attribute. This feature is turned on by default if optimization is on (but not with-Og, @pxref{Optimize Options}), and if GNU Binutils supports PR21683 (https://sourceware.org/PR21683).-mint8โ ๐ญ Assumeintis an 8-bit integer. This changes the sizes of all the types: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes.
โ ๏ธ Heads up, bestie: this option does not conform to the C standards. It does give you smaller code size, though.
-mmain-is-OS_taskโ ๐ฆ Don't save registers inmain. The effect is the same as attaching the AVR Attributes,,"OS_task" attribute tomain. It's turned on by default if optimization is on.-mno-call-mainโ ๐ธ Don't runmainby means of:
XCALL main
XJMP exit
- Instead, put
mainin the section.init9(https://avrdudes.github.io/avr-libc/avr-libc-user-manual/mem_sections.html#sec_dot_init) so no call is needed. By setting this option, you're promising thatmainwill never return. - This option is for devices with very limited resources, where it saves a few bytes of code and stack space. It works as expected since AVR-LibC v2.3 (
https://github.com/avrdudes/avr-libc/issues/1012). With older versions, there's no performance gain.
-mno-interruptsโ ๐ซง The generated code is not compatible with hardware interrupts. The upside is that the code size is smaller.-mrelaxโ โจ Try to swap aCALLorJMPinstruction for the shorterRCALLorRJMPinstruction when that's possible. Setting-mrelaxjust adds the--mlink-relaxoption to the assembler's command line and the--relaxoption to the linker's command line.- Jump relaxing is done by the linker, because jump offsets aren't known until the code is located. So the assembler code the compiler generates stays the same, but the instructions in the executable may differ from the ones in the assembler code.
- Relaxing must be turned on if linker stubs are needed. See the section on "EIND" and linker stubs below.
-mpmem-wrap-aroundโ ๐ Enable program counter wrap-around in linker relaxation.-mrodata-in-ram,-mno-rodata-in-ramโ ๐ง Put the.rodatasections for read-only data in RAM or in program memory, respectively. For most devices there's no real choice, so this option acts more like an assertion.- Since v14, and for the AVR64* and AVR128* devices,
.rodatalives in flash memory by default, as long as the required GNU Binutils support (PR31124 (https://sourceware.org/PR31124)) is available. In that case,-mrodata-in-ramcan bring back the old layout with.rodatain RAM.
- Since v14, and for the AVR64* and AVR128* devices,
-mtiny-stackโ ๐ท Only change the lower 8 bits of the stack pointer.-mfract-convert-truncateโ ๐ Allow truncation instead of rounding towards zero for fractional fixed-point types.-nodevicelibโ ๐ โโ๏ธ Don't link against AVR-LibC's device specific librarylibmcu.a.- Heads up: since AVR-LibC v2.3, that library contains code that's essential for a program to work correctly. In particular, it has parts of the startup code, like
__init_sp(https://github.com/avrdudes/avr-libc/issues/1011) which sets the stack pointer to the symbol__stack,__init_cvt(https://github.com/avrdudes/avr-libc/issues/1010) which sets up the hardware for a compact vector table with-mcvt,__call_main(https://github.com/avrdudes/avr-libc/issues/1012) which callsmainandexit, and__do_flmap_init(https://github.com/avrdudes/avr-libc/issues/931) which sets up FLMAP according to the symbol__flmap.
- Heads up: since AVR-LibC v2.3, that library contains code that's essential for a program to work correctly. In particular, it has parts of the startup code, like
-nodevicespecsโ ๐ Don't add-specs=device-specs/specs-mcuto the compiler driver's command line. You're on the hook for giving the subprocesses (the compiler proper, the assembler, and the linker) the right command line options. That means you have to supply your own private device specs file with-specs=path-to-specs-file. There's no more need for the option-mmcu=mcu.- This option can also replace the older way of specifying custom device-specs files. That way needed
-B some-pathto point to a directory containing a folder named "device-specs", which in turn contained a specs file named "specs-mcu", where mcu was specified by-mmcu=mcu.
- This option can also replace the older way of specifying custom device-specs files. That way needed
-Waddr-space-convertโ Heads up, this one warns you whenever you convert between address spaces and the result doesn't fit inside the incoming address space. Those conversions can quietly go sideways ๐-Wmisspelled-isrโ Warns if your ISR name is misspelled, meaning it's missing the__vectorprefix. It's on by default, so you get this one for free ๐
๐ธ AVR Optimization Options ๐ธ
okay so these are the pure optimization options ๐ The ones from above, -mgas-isr-prologues, -mmain-is-OS_task, -mno-call-main, and -mrelax, are only almost optimization options. There are rare moments where their different code generation actually matters, so they're not 100% just speed boosts ๐ซถ
-maccumulate-argsโ Collects outgoing function arguments and grabs or releases the stack space for them once, in the function prologue and epilogue. Without this, outgoing arguments get pushed before each call and popped afterwards. Also check out-fdefer-popover in the Optimize Options section โจ
Popping arguments after a call can be expensive on AVR, so accumulating the stack space can actually give you smaller executables. Arguments don't need to be removed from the stack after every call anymore ๐ง
This one can shrink your code for functions that make several calls to functions that take their arguments on the stack, like printf-style functions ๐จ๏ธ
-mbranch-cost=costโ Sets the branch costs for conditional branch instructions tocost. Reasonable values are small, non-negative integers. The default branch cost is0๐-mcall-prologuesโ Function prologues and epilogues get expanded as calls to the right subroutines. The result is smaller code size ๐ฆ-mfuse-add,-mno-fuse-add,-mfuse-add=levelโ Optimizes indirect memory accesses on reduced Tiny devices. By default it useslevel=1for-Ogand-O1, andlevel=2for higher optimization levels. Valid values forlevelare0,1, and2๐-mfuse-move,-mno-fuse-move,-mfuse-move=levelโ Runs a post-reload optimization pass that tries to fuse move instructions and split multi-byte instructions into 8-bit operations. The default islevel=3for-O1, andlevel=23for higher optimizations. Valid values forlevelare in the range0 ... 23, which is a 3:2:2:2 mixed radix value. Each digit controls a different aspect of the optimization, so it's giving math nerd energy ๐ค๐-mfuse-move2โ Runs a post-combine optimization pass that tries to fuse move instructions ๐ฅ-mstrict-Xโ Uses the address registerXthe way the hardware intends. That meansXis only used in indirect, post-increment, or pre-decrement addressing ๐
Without this option, X can be used just like Y or Z, but that gets emulated with extra instructions. For example, loading a value with X+const addressing (where const is a small non-negative value, const < 64) into a register Rn is done like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-msplit-bit-shiftโ Splits multi-byte shifts with a constant offset into a byte-offset shift plus a residual shift with a non-byte offset. This is turned on by default for-O2and higher, including-Os, but not-Oz๐ Splitting shifts whose constant offset is a multiple of 8 is controlled by-mfuse-move.-msplit-ldstโ Splits multi-byte loads and stores into several byte loads and stores. Turned on by default for-O2and higher ๐ซง-muse-nonzero-bitsโ Enables optimizations that are only possible when some bits in a register are always zero. Turned on by default for-O2and higher ๐ง
๐ง "EIND" and Devices With More Than 128 Ki Bytes of Flash ๐ง
okay this section is a lot, but it's important bestie ๐ญ
Pointers in the implementation are 16 bits wide. The address of a function or label is stored as a word address, so indirect jumps and calls can target any code address in the range of 64 Ki words ๐
To make indirect jumps work on devices with more than 128 Ki bytes of program memory, there's a special function register called EIND. It serves as the most significant part of the target address when EICALL or EIJMP instructions are used โจ
Indirect jumps and calls on these devices are handled like this by the compiler, and they come with some limitations:
- The compiler never sets
EIND. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or might readEINDdirectly to emulate an indirect call/jump using aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved or restored in function or interrupt service routine prologues/epilogues. ๐ซ - For indirect calls to functions and computed gotos, the linker generates stubs. Stubs are jump pads, sometimes also called trampolines. So the indirect call or jump actually jumps to a stub, and the stub contains a direct jump to the desired address ๐ฆ
- Linker relaxation must be turned on so the linker generates the stubs correctly in all situations. See the compiler option
-mrelaxand the linker option--relax. There are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message ๐ - The default linker script is arranged for code with
EIND = 0. If your code is supposed to work withEIND != 0, you need a custom linker script to place the sections whose names start with.trampolinesinto the segment thatEINDpoints to ๐บ๏ธ - The startup code from libgcc never sets
EIND. Heads up that startup code is a blend of code from libgcc and AVR-LibC. For how AVR-LibC affectsEIND, check the AVR-LibC user manual athttps://avrdudes.github.io/avr-libc/avr-libc-user-manual/๐ - It's legit for user-specific startup code to set up
EINDearly, for example through initialization code placed in section.init3. That code runs before the general startup code that initializes RAM and calls constructors, but after the bit of AVR-LibC startup code that setsEINDto the segment where the vector table lives ๐ซถ
Here's an example:
#include <avr/io.h>
static void
__attribute__((section(".init3"),naked,used,no_instrument_function))
init3_set_eind (void)
{
__asm volatile ("ldi r24,pm_hh8(__trampolines_start)\n\t"
"out %i0,r24" :: "n" (&EIND) : "r24","memory");
}
The __trampolines_start symbol is defined in the linker script.
- Stubs get generated automatically by the linker when both of these conditions are met:
- The address of a label is taken by means of the
gsmodifier (short for generate stubs), like so:
- The address of a label is taken by means of the
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The final location of that label is in a code segment outside the segment where the stubs are located.
- The compiler emits
gsmodifiers for code labels in these situations:- Taking the address of a function or code label.
- Computed goto.
- If a prologue-save function is used. See the
-mcall-prologuescommand-line option. - Switch/case dispatch tables. If you don't want these dispatch tables, you can specify the
-fno-jump-tablescommand-line option. - C and C++ constructors/destructors called during startup/shutdown.
- If the tools hit a
gs()modifier explained above.
- Jumping to non-symbolic addresses like this is not supported ๐จ
int main (void)
{
/* Call function at word address 0x2 */
return ((int(*)(void)) 0x2)();
}
Instead, you need to set up a stub, meaning the function has to be called through a symbol (func_4 in the example):
int main (void)
{
extern int func_4 (void);
/* Call function at byte address 0x4 */
return func_4();
}
Then link the application with -Wl,--defsym,func_4=0x4. Alternatively, func_4 can be defined in the linker script โจ
๐ Handling of the "RAMPD", "RAMPX", "RAMPY" and "RAMPZ" Special Function Registers ๐
Some AVR devices support memories bigger than the 64 KiB range that 16-bit pointers can reach. To access memory locations outside that 64 KiB range, the content of a RAMP register gets used as the high part of the address. The X, Y, and Z address registers get concatenated with RAMPX, RAMPY, and RAMPZ special function registers, respectively, to form a wide address. Similarly, RAMPD is used together with direct addressing ๐
- The startup code initializes the
RAMPspecial function registers with zero. - If a named address space other than generic or
__flashis used (see AVR Named Address Spaces), thenRAMPZis set as needed before the operation. - If the device supports RAM larger than 64 KiB and the compiler needs to change
RAMPZto accomplish an operation,RAMPZis reset to zero after the operation. - If the device comes with a specific
RAMPregister, the ISR prologue/epilogue saves and restores that SFR, and initializes it with zero in case the ISR code might (implicitly) use it. - RAM larger than 64 KiB is not supported by GCC for AVR targets. If you use inline assembler to read from locations outside the 16-bit address range and change one of the
RAMPregisters, you must reset it to zero after the access โ ๏ธ
๐ AVR Built-in Macros ๐
GCC defines several built-in macros so user code can test for the presence or absence of features. Almost any of the following built-in macros are deduced from device capabilities and are therefore triggered by the -mmcu= command-line option ๐ง
For even more AVR-specific built-in macros, see AVR Named Address Spaces and AVR Built-in Functions ๐
__AVR_ARCH__โ A built-in macro that resolves to a decimal number identifying the architecture. It depends on the-mmcu=mcuoption. Possible values are:
2, 25, 3, 31, 35, 4, 5, 51, 6
for mcu="avr2", "avr25", "avr3", "avr31", "avr35", "avr4", "avr5", "avr51", "avr6", respectively, and:
100, 102, 103, 104, 105, 106, 107
Those mcu values each get their own number, respectively ๐
: "avrtiny", "avrxmega2", "avrxmega3", "avrxmega4", "avrxmega5", "avrxmega6", and "avrxmega7" ๐ธ. If mcu names an actual device, this built-in macro gets set to match. For example, with -mmcu=atmega8 the macro is defined to 4 โจ.
"__AVR_Device__"๐ Setting-mmcu=devicedefines this macro, and it reflects the device's name. So-mmcu=atmega8defines"__AVR_ATmega8__",-mmcu=attiny261adefines"__AVR_ATtiny261A__", and so on ๐ฆ.- The names follow the scheme
"__AVR_Device__", where Device is the device name as it's written in the AVR user manual. The difference between Device in the macro and device in-mmcu=deviceis that the latter is always lowercase ๐. - If device is only a core architecture like
avr51and not a real device, this macro isn't defined ๐.
- The names follow the scheme
"__AVR_DEVICE_NAME__"๐ Setting-mmcu=devicemakes this one hold the device's name. With-mmcu=atmega8it's defined to"atmega8".- Same deal here: if device is just a core architecture like
avr51, this macro isn't defined.
- Same deal here: if device is just a core architecture like
"__AVR_CVT__"๐ You're compiling with-mcvtto use a compact vector table."__AVR_XMEGA__"๐ The device or architecture belongs to the XMEGA family."__AVR_HAVE_ADIW__"โจ The device has theADIWandSBIWinstructions."__AVR_HAVE_ELPM__"๐ง The device has theELPMinstruction."__AVR_HAVE_ELPMX__"๐ฆ The device has theELPM Rn,ZandELPM Rn,Z+instructions."__AVR_HAVE_LPMX__"๐ The device has theLPM Rn,ZandLPM Rn,Z+instructions."__AVR_HAVE_MOVW__"๐ The device has theMOVWinstruction for 16-bit register-to-register moves."__AVR_HAVE_MUL__"๐ฅ The device has a hardware multiplier."__AVR_HAVE_JMP_CALL__"๐ธ The device has theJMPandCALLinstructions. This is the case for devices with more than 8 KiB of program memory."__AVR_HAVE_EIJMP_EICALL__"and"__AVR_3_BYTE_PC__"โญ The device has theEIJMPandEICALLinstructions. This is the case for devices with more than 128 KiB of program memory. It also means the program counter (PC) is 3 bytes wide."__AVR_2_BYTE_PC__"๐ The program counter (PC) is 2 bytes wide. This is the case for devices with up to 128 KiB of program memory."__AVR_HAVE_8BIT_SP__"and"__AVR_HAVE_16BIT_SP__"๐ The compiler treats the stack pointer (SP) register as an 8-bit or 16-bit register, respectively. The definition of these macros is affected by-mtiny-stack."__AVR_HAVE_SPH__"and"__AVR_SP8__"๐ซถ The device has the SPH (high part of stack pointer) special function register, or has an 8-bit stack pointer, respectively. The definition of these macros is affected by-mmcu=, and for-mmcu=avr2and-mmcu=avr25also by-msp8."__AVR_HAVE_RAMPD__","__AVR_HAVE_RAMPX__","__AVR_HAVE_RAMPY__", and"__AVR_HAVE_RAMPZ__"๐ The device has theRAMPD,RAMPX,RAMPY, andRAMPZspecial function registers, respectively."__NO_INTERRUPTS__"๐ This macro reflects the-mno-interruptscommand-line option."__AVR_ERRATA_SKIP__"and"__AVR_ERRATA_SKIP_JMP_CALL__"๐ญ Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum. The skip instructions areSBRS,SBRC,SBIS,SBIC, andCPSE. The second macro is only defined if"__AVR_HAVE_JMP_CALL__"is also set."__AVR_ISA_RMW__"๐ฅ The device has Read-Modify-Write instructions (XCH,LAC,LAS, andLAT)."__AVR_SFR_OFFSET__=offset"๐ง Instructions that can address I/O special function registers directly, likeIN,OUT,SBI, etc., may use a different address than an instruction accessing RAM, likeLDorSTS. This offset depends on the device architecture and has to be subtracted from the RAM address to get the respective I/O address."__AVR_SHORT_CALLS__"๐ The-mshort-callscommand-line option is set."__AVR_PM_BASE_ADDRESS__=addr"๐ Some devices support reading from flash memory usingLD*instructions. The flash memory shows up in the data address space at an offset of"__AVR_PM_BASE_ADDRESS__". If this macro isn't defined, the feature isn't available. If it is defined, the address space is linear and there's no need to put.rodatainto RAM. This is handled by the default linker description file, and it's currently available foravrtinyandavrxmega3. Even more convenient, there's no need for address spaces like__flashor features like theprogmemattribute andpgm_read_*."__AVR_HAVE_FLMAP__"๐ This macro is defined when the following conditions are met:- The device has the
NVMCTRL_CTRLB.FLMAPbitfield. This applies to theAVR64*andAVR128*devices. - It's not known at assembler-time which emulation will be used.
- The device has the
This implies the compiler was configured with GNU Binutils that implement PR31124 (https://sourceware.org/PR31124).
"__AVR_RODATA_IN_RAM__"๐ธ This macro is undefined when the code is compiled for a core architecture. When the code is compiled for a device, the macro is defined to1when the.rodatasections for read-only data are located in RAM, and defined to0otherwise."__WITH_AVRLIBC__"๐ฆ The compiler is configured to be used together with AVR-LibC. See the--with-avrlibcconfigure option."__HAVE_SIGNAL_N__"โญ The compiler supports thesignal(num)andinterrupt(num)AVR Attributes,,function attributes, with an argumentnumthat specifies the number of the interrupt service routine."__HAVE_DOUBLE_MULTILIB__"๐ Defined if-mdouble=acts as a multilib option."__HAVE_DOUBLE32__"and"__HAVE_DOUBLE64__"โจ Defined if the compiler supports 32-bit double or 64-bit double, respectively. The actual layout is specified by-mdouble=."__DEFAULT_DOUBLE__"๐ง The size in bits ofdoubleif-mdouble=is not set. To test the layout ofdoublein a program, use the built-in macro"__SIZEOF_DOUBLE__"."__HAVE_LONG_DOUBLE32__","__HAVE_LONG_DOUBLE64__","__HAVE_LONG_DOUBLE_MULTILIB__", and"__DEFAULT_LONG_DOUBLE__"๐ Same as above, but forlong doubleinstead ofdouble."__WITH_DOUBLE_COMPARISON__"๐ซถ Reflects the--with-double-comparison={tristate|bool|libf7}configure option (https://gcc.gnu.org/install/configure.html#avr) and is defined to2or3."__WITH_LIBF7_LIBGCC__","__WITH_LIBF7_MATH__", and"__WITH_LIBF7_MATH_SYMBOLS__"๐ Reflect the--with-libf7={libgcc|math|math-symbols}configure option (https://gcc.gnu.org/install/configure.html#avr).
โจ AVR Internal Options โจ
Okay bestie, these ones are used internally by the compiler, and they're how device specs files talk to the compiler proper ๐ง. You don't need to set them by hand, and they are not optimization options ๐
. They're documented for completeness, and so you can get a better understanding of device specs (https://gcc.gnu.org/wiki/avr-gcc#spec-files) files.
Using these the wrong way may lead to sub-optimal or wrong code. Don't freestyle these ๐ญ.
-mn-flash=num๐ Assume the flash memory has a size ofnumtimes 64 KiB. This determines which"__flashN"address spaces are available.-mflmap๐ The device has theFLMAPbit field, located in the special function registerNVMCTRL_CTRLB.-mrmw๐ฅ Assume the device supports the Read-Modify-Write instructionsXCH,LAC,LAS, andLAT.-mshort-calls๐ธ AssumeRJMPandRCALLcan target the whole program memory. This option is used for multilib generation and selection for the devices from architectureavrxmega3.-mskip-bug๐ Generate code without skips (CPSE,SBRS,SBRC,SBIS,SBIC) over 32-bit instructions.-msp8๐ซถ Treat the stack pointer register as an 8-bit register, i.e. assume the high byte of the stack pointer is zero. The compiler uses this option to select and build multilibs for architecturesavr2andavr25. These architectures mix devices with and withoutSPH.
โจ Blackfin Options โจ
-mcpu=cpu[-sirevision]๐ฆ Specifies the name of the target Blackfin processor. Currently, cpu can be one of these:bf512,bf514,bf516,bf518,bf522,bf523,bf524,bf525,bf526,bf527,bf531,bf532,bf533,bf534,bf536,bf537,bf538,bf539,bf542,bf544,bf547,bf548,bf549,bf542m,bf544m,bf547m,bf548m,bf549m,bf561,bf592
The optional sirevision specifies the silicon revision of the target Blackfin processor. Any workarounds available for the targeted silicon revision are enabled. If sirevision is none, no workarounds are enabled. If sirevision is any, all workarounds for the targeted processor are enabled. The "__SILICON_REVISION__" macro is defined to two hexadecimal digits representing the major and minor numbers in the silicon revision. If sirevision is none, "__SILICON_REVISION__" is not defined. If sirevision is any, "__SILICON_REVISION__" is defined to be 0xffff. If this optional sirevision isn't used, GCC assumes the latest known silicon revision of the targeted Blackfin processor.
GCC defines a preprocessor macro for the specified cpu. For the bfin-elf toolchain, this option causes the hardware BSP provided by libgloss to be linked in if -msim is not given.
Without this option, bf532 is used as the processor by default.
Heads up: support forbf561is incomplete. Forbf561, only the preprocessor macro is defined.
-msim๐ Specifies that the program will be run on the simulator. This causes the simulator BSP provided by libgloss to be linked in. This option has effect only for thebfin-elftoolchain. Certain other options, such as-mid-shared-libraryand-mfdpic, imply-msim.-momit-leaf-frame-pointerโจ Don't keep the frame pointer in a register for leaf functions. This avoids the instructions to save, set up, and restore frame pointers, and makes an extra register available in leaf functions.-mspecld-anomalyand-mno-specld-anomaly๐ When enabled, the compiler ensures the generated code does not contain speculative loads after jump instructions. If this option is used,"__WORKAROUND_SPECULATIVE_LOADS"is defined.-mcsync-anomaly,-mno-csync-anomalyโ okay so when this is on, the compiler makes sure it never slipsCSYNCorSSYNCinstructions in too soon after conditional branches ๐ซถ Using it also defines__WORKAROUND_SPECULATIVE_SYNCSโจ-mlow64k,-mno-low64kโ when enabled, the compiler gets to assume your whole program fits in the low 64k of memory, so it can take shortcuts ๐ธ The default is-mno-low64k, which treats the program as arbitrarily large, so no shortcuts for you, bestie ๐-mstack-check-l1โ does stack checking using info the uClinux kernel stashes in L1 scratchpad memory ๐ง-mid-shared-library,-mno-id-shared-libraryโ generates code that supports shared libraries through the library ID method. This is the vibe for execute in place and shared libraries in an environment with no virtual memory management ๐ฆ It implies-fPIC, and on abfin-elftarget it also implies-msim. The default is-mno-id-shared-library, which doesn't assume ID-based shared libraries are in use.-mleaf-id-shared-library,-mno-leaf-id-shared-libraryโ same ID-based shared library energy, but this one assumes your library or executable won't link against any other ID shared libraries ๐ That lets the compiler use faster code for jumps and calls. The default is-mno-leaf-id-shared-library, where nobody makes that assumption, so the jump and call instructions come out slower ๐ข-mshared-library-id=nโ sets the identification number of the ID-based shared library you're compiling ๐ A value of0gives you more compact code. Other values force that number onto the current library, but they're no more space- or time-efficient than just leaving the option out.-msep-data,-mno-sep-dataโ lets the data segment live in a different area of memory from the text segment ๐ This helps with execute in place when there's no virtual memory management, since it gets rid of relocations against the text section. The default is-mno-sep-data, which assumes the data segment follows the text segment.-mlong-calls,-mno-long-callsโ tells the compiler to do function calls the long way: load the function's address into a register first, then make a subroutine call on that register ๐ You need this if the target function lives outside the 24-bit addressing range of the offset-based subroutine call instruction. It's not on by default, and-mno-long-callsputs you back to the default. Heads up, these switches don't change how calls through function pointers get generated ๐-mfast-fpโ links with the fast floating-point library โก It relaxes some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN), all in the name of performance.-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally ๐ It does nothing unless you also use-mfdpic.-mmulticoreโ builds a standalone application for multicore Blackfin processors ๐ It makes sure the right start files and link scripts for multicore get used, and defines the macro__BFIN_MULTICORE. This one only works with-mcpu=bf561[-sirevision]. You can pair it with-mcoreaor-mcorebfor the one-application-per-core setup. Without either of those, you get the single-application, dual-core model, where the main function of Core B has to be namedcoreb_main. If you skip this option entirely, you get the single-core application model.-mcoreaโ builds a standalone application for Core A of BF561 in the one-application-per-core setup ๐ซถ The proper start files and link scripts for Core A get used, and the macro__BFIN_COREAis defined. This only works together with-mmulticore.-mcorebโ builds a standalone application for Core B of BF561 in the one-application-per-core setup ๐ The right start files and link scripts for Core B get used, and__BFIN_COREBis defined. When you use this one,coreb_mainreplacesmain. It also only works together with-mmulticore.-msdramโ builds a standalone application for SDRAM ๐ง Start files and link scripts get used to put your app into SDRAM, and the macro__BFIN_SDRAMis defined. Your loader has to initialize SDRAM before it loads the application.-micplbโ assumes ICPLBs are enabled at run time ๐ฅ This changes how certain anomaly workarounds behave. For Linux targets, the default is to assume ICPLBs are enabled. For standalone applications, the default is off.
๐ฆ C6X Options ๐ฆ
-march=nameโ sets the name of the target architecture ๐ GCC uses this to figure out which kinds of instructions it's allowed to emit when generating assembly code. The valid names arec62x,c64x,c64x+,c67x,c67x+, andc674x.-mbig-endianโ generates code for a big-endian target ๐ธ-mlittle-endianโ generates code for a little-endian target. This is the default โจ-msimโ picks startup files and a linker script that work with the simulator ๐ง-msdata=defaultโ puts small global and static data into the.neardatasection, which gets pointed to by registerB14๐ Small uninitialized global and static data goes into.bss, which sits right next to.neardata. Small read-only data goes into.rodata. The sections for the big pieces of data are.fardata,.far, and.const.-msdata=allโ puts all data into the small-data sections, not just the small stuff, and uses addressing relative to theB14register to get at it ๐-msdata=noneโ no small-data sections at all. Everything gets accessed with absolute addresses ๐ All initialized global and static data goes into.fardata, all uninitialized data goes into.far, and all constant data goes into.const.-mdsbtโ compiles for the DSBT shared library ABI ๐ฆ You need this to compile with-fpicor-fPIC, and it implies-fpic.-mlong-callsโ avoids PC-relative calls and uses indirection instead ๐
๐ CRIS Options ๐
These options are defined specifically for the CRIS ports ๐
-march=architecture-type,-mcpu=architecture-typeโ generates code for the architecture you pick โญ The choices arev3,v8, andv10, which line up with ETRAX 4, ETRAX 100, and ETRAX 100 LX. The default isv0.-mtune=architecture-typeโ tunes everything that applies to the generated code for the architecture you name, except the ABI and the set of available instructions ๐ซถ The choices are the same as for-march=architecture-type.-mmax-stackframe=nโ warns when a function's stack frame goes overnbytes โ ๏ธ-metrax4,-metrax100โ these are just synonyms for-march=v3and-march=v8, respectively ๐ง-mmul-bug-workaround,-mno-mul-bug-workaroundโ works around a bug in themulsandmuluinstructions, on the CPU models where that bug shows up ๐ฅ It's disabled by default.-mpdebugโ turns on CRIS-specific verbose debug info in the assembly code ๐ This also turns off the#NO_APPformatted-code indicator that gets sent to the assembler at the top of the assembly file.-mcc-initโ don't reuse condition-code results from the previous instruction ๐ โโ๏ธ Instead, always emit compare and test instructions before any condition codes get used.-mno-side-effectsโ doesn't emit instructions with side effects in addressing modes, except for post-increment ๐ธ-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ these decide whether the stack frame, individual data, and constants get aligned to the biggest single data access size for your chosen CPU model ๐ The no- versions turn that alignment off. The default is 32-bit alignment. ABI details like structure layout stay the same no matter what you pick here.-m32-bit,-m16-bit,-m8-bitโ kind of like the stack, data, and const alignment options above, but these make the stack frame, writable data, and constants 32-bit, 16-bit, or 8-bit aligned ๐ The default is 32-bit alignment.-mno-prologue-epilogue,-mprologue-epilogueโ with-mno-prologue-epilogue, the normal function prologue and epilogue that set up the stack frame get skipped, and no return instructions or return sequences get generated ๐
Use -mno-prologue-epilogue only alongside careful visual inspection of the compiled code, bestie. No warnings or errors show up when call-saved registers need to be saved, or when storage for local variables needs to be allocated. You're on your own for that one ๐ญ
-mbest-lib-options,-moverride-best-lib-optionsโ-mbest-lib-optionspicks the most feature-enabling options that the other options allow ๐ It has no no- form, but-moverride-best-lib-optionsturns it off no matter where the two options sit on the command line.-mtrap-using-break8โ emits traps asbreak 8๐ฆ This is the default for CRIS v3 and up. If you disable it, calls toabortget used instead.-mtrap-unaligned-atomicโ emits checks that makebreak 8instructions run when atomic builtins get applied to misaligned memory ๐-munaligned-atomic-may-use-libraryโ handles atomic builtins that might get applied to unaligned data by calling library functions instead ๐ This one overrides-mtrap-unaligned-atomic.-simโ links with the input-output functions from a simulator library ๐งช Code, initialized data, and zero-initialized data all get allocated one after another.-sim2โ works like-sim, but the linker options place initialized data at0x40000000and zero-initialized data at0x80000000๐ซ
๐ C-SKY Options ๐
GCC has a whole set of options just for C-SKY V2 chips ๐ง Let's go through them ๐
-march=archโ pick the C-SKY target architecture ๐ Valid values for arch areck801,ck802,ck803,ck807, andck810. The default isck810.-mcpu=cpuโ pick the exact C-SKY target processor ๐ Valid values for cpu are the whole squad:
ck801, ck801t, ck802, ck802t, ck802j, ck803, ck803h, ck803t,
ck803ht, ck803f, ck803fh, ck803e, ck803eh, ck803et, ck803eht,
ck803ef, ck803efh, ck803ft, ck803eft, ck803efht, ck803r1, ck803hr1,
ck803tr1, ck803htr1, ck803fr1, ck803fhr1, ck803er1, ck803ehr1,
ck803etr1, ck803ehtr1, ck803efr1, ck803efhr1, ck803ftr1, ck803eftr1,
ck803efhtr1, ck803s, ck803st, ck803se, ck803sf, ck803sef, ck803seft,
ck807e, ck807ef, ck807, ck807f, ck810e, ck810et, ck810ef, ck810eft,
ck810, ck810v, ck810f, ck810t, ck810fv, ck810tv, ck810ft, and
ck810ftv.
-mbig-endian,-mlittle-endianโ choose big-endian or little-endian code ๐ธ The default is little-endian.-mfloat-abi=nameโ choose which floating-point ABI to use ๐ฅ Permissible values aresoft,softfp, andhard.soft: GCC generates output with library calls for floating-point operations.softfp: you get hardware floating-point instructions, but it still uses the soft-float calling conventions.hard: you get floating-point instructions and FPU-specific calling conventions.
The default depends on the specific target configuration.
โ ๏ธ The hard-float and soft-float ABIs are NOT link-compatible. Compile your entire program with the same ABI and link with a compatible set of libraries, or it's giving chaos ๐
-mdouble-float,-mno-double-floatโ when-mhard-floatis in effect, turn on generation of double-precision float instructions ๐ฆ This is the default except when compiling forCK803.-mfdivdu,-mno-fdivduโ when-mhard-floatis in effect, turn on generation of"frecipd","fsqrtd", and"fdivd"instructions โจ This is the default except when compiling forCK803.-mfpu=fpuโ select the floating-point processor ๐ This option can only be used with-mhard-float. Values for fpu arefpv2_sf(equivalent to-mno-double-float -mno-fdivdu),fpv2(-mdouble-float -mno-divdu), andfpv2_divd(-mdouble-float -mdivdu).-melrw,-mno-elrwโ enable the extended"lrw"instruction ๐ง This option defaults to on forCK801and off otherwise.-mistack,-mno-istackโ enable interrupt stack instructions. The default is off. ๐ The-mistackoption is required to handle the"interrupt"and"isr"function attributes.-mmp,-mno-mpโ enable multiprocessor instructions. The default is off ๐-mcp,-mno-cpโ enable coprocessor instructions. The default is off ๐ซถ-mcache,-mno-cacheโ enable coprocessor instructions. The default is off ๐ธ-msecurity,-mno-securityโ enable C-SKY security instructions. The default is off ๐-mtrust,-mno-trustโ enable C-SKY trust instructions. The default is off ๐ฆ-mdsp,-mno-dsp,-medsp,-mno-edsp,-mvdsp,-mno-vdspโ enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively ๐ All of these options default to off.-mdiv,-mno-divโ generate divide instructions. Default is off โจ-msmart,-mno-smartโ generate code for Smart Mode, using only registers numbered0-7so you can use 16-bit instructions ๐ This option is ignored forCK801, where this is already the required behavior, and it defaults to on forCK802. For other targets, the default is off.-mhigh-registers,-mno-high-registersโ generate code using the high registers numbered16-31๐ This option is not supported onCK801,CK802, orCK803, and it's enabled by default for other processors.-manchor,-mno-anchorโ generate code using global anchor symbol addresses ๐-mpushpop,-mno-pushpopโ generate code using"push"and"pop"instructions ๐ This option defaults to on.-mmultiple-stld,-mno-multiple-stldโ generate code using"stm"and"ldm"instructions ๐ง This option isn't supported onCK801, but it's enabled by default on other processors.-mconstpool,-mno-constpoolโ create constant pools in the compiler, instead of handing that job off to the assembler ๐ซถ This option is the default and is required for correct code generation onCK801andCK802. On other processors it's optional.-mstack-size,-mno-stack-sizeโ emit".stack_size"directives for each function in the assembly output ๐ฆ This option defaults to off.-mccrt,-mno-ccrtโ generate code for the C-SKY compiler runtime instead oflibgcc๐ This option defaults to off.-mbranch-cost=nโ set the branch costs to roughly"n"instructions ๐ The default is1.-msched-prolog,-mno-sched-prologโ permit scheduling of function prologue and epilogue sequences ๐ Using this option can result in code that is not compliant with the C-SKY V2 ABI prologue requirements, and that cannot be debugged or backtraced. It is disabled by default.
๐จ Heads up, bestie: -msched-prolog can make code that isn't compliant with the C-SKY V2 ABI prologue requirements. That code also can't be debugged or backtraced. It's disabled by default for a reason.
-msim,-mno-simโ links the librarylibsemi.a, which is compatible with the simulator ๐ฅ๏ธ Applicable to ELF compiler only.
โจ Cygwin and MinGW Options โจ
These additional options are available for Microsoft Windows targets ๐ธ
-mconsoleโ generate a console application by telling the linker to set the PE header subsystem type needed for console apps ๐ This option is available for Cygwin and MinGW targets and is enabled by default on those targets.-mcrtdll=libraryโ preprocess, compile, or link with the specified C RunTime DLL library ๐ง This option adjusts the predefined macros"__CRTDLL__","__MSVCRT__","_UCRT", and"__MSVCRT_VERSION__"for the specified CRT library. It also picks the start file for the CRT library and links with the CRT library. Recognized CRT library names for the preprocessor are"crtdll*","msvcrt10*","msvcrt20*","msvcrt40*","msvcr40*","msvcrtd*","msvcrt-os*","msvcr70*","msvcr71*","msvcr80*","msvcr90*","msvcr100*","msvcr110*","msvcr120*"and"ucrt*". If this option isn't specified, the default MinGW import library"msvcrt"is used for linking, and no other preprocessor adjustment is done. The MinGW import library"msvcrt"is just a symlink to (or a copy of) another MinGW CRT import library, chosen during MinGW compilation. The MinGW import library"msvcrt-os"is for the Windows system CRT DLL"msvcrt.dll", and in most cases it's the default MinGW import library. Generally speaking, changing the CRT DLL requires recompiling the entire MinGW CRT. This option is for experimental and testing purposes only ๐งช It's available for MinGW targets.-mdllโ available for Cygwin and MinGW targets ๐ It generates a DLL (a dynamic link library), letting you select the required runtime startup object and entry point.-mnop-fun-dllimportโ available for Cygwin and MinGW targets ๐ It makes GCC ignore the"dllimport"attribute.-mthreadsโ supports thread-safe exception handling on MinGW ๐ฅ Programs that rely on thread-safe exception handling must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT. When linking, it links in a special thread helper library,-lmingwthrd, which cleans up per-thread exception-handling data.-municodeโ available for MinGW-w64 targets ๐ธ It predefines the"UNICODE"preprocessor macro and chooses Unicode-capable runtime startup code.-mwin32โ available for Cygwin and MinGW targets ๐ฆ It sets the typical Microsoft Windows predefined macros in the preprocessor, but it doesn't influence the choice of runtime library or startup code.-mwindowsโ available for Cygwin and MinGW targets ๐ It generates a GUI application by telling the linker to set the PE header subsystem type appropriately.-fno-set-stack-executableโ available for MinGW targets ๐ซถ It means the executable flag for the stack used by nested functions isn't set. This is necessary for binaries running in kernel mode of Microsoft Windows, since the User32 API (the one used to set executable privileges) isn't available there.-fwritable-relocated-rdataโ available for MinGW and Cygwin targets ๐ง It puts relocated data in a read-only section into the".data"section. This is necessary for older runtimes that don't support modifying".rdata"sections for pseudo-relocation.-mpe-aligned-commonsโ available for Cygwin and MinGW targets ๐ It means the GNU extension to the PE file format, which permits correct alignment of COMMON variables, should be used when generating code. It's enabled by default if GCC detects that the target assembler found during configuration supports the feature.-muse-libstdc-wrappersโ uses Cygwin DLL wrappers to support the C++ operators"new"and"delete"๐
See also under x86 Options for standard options.
๐ Darwin Options ๐
These options are defined for all architectures running the Darwin operating system ๐
FSF GCC on Darwin does not create "fat" object files. It creates an object file for the single architecture that GCC was built to target. Apple's GCC on Darwin does create "fat" files if multiple -arch options are used. It does this by running the compiler or linker multiple times and joining the results together with lipo ๐
The subtype of the file created (like ppc7400 or ppc970 or i686) is determined by the flags that specify the ISA that GCC is targeting, like -mcpu or -march. You can use -force_cpusubtype_ALL to override this โจ
okay so the Darwin tools are not chill about ISA mismatches ๐ the assembler, as, only lets you use instructions that are valid for the subtype of the file it's generating, so you literally cannot put 64-bit instructions in a ppc750 object file ๐
โโ๏ธ the shared library linker, /usr/bin/libtool, will fail and print an error if you ask it to make a shared library with a less restrictive subtype than its input files (like shoving a ppc970 object file into a ppc7400 library, no thank you ๐ญ). the executable linker, ld, is the chill one ๐ซถ it quietly gives the executable the most restrictive subtype of any of its inputs.
โจ OPTIONS โจ
-Fdirโ okay this one's a whole vibe ๐ธ it adds the framework directorydirto the front of the list of places searched for header files. these directories get mixed in with the ones from-Ioptions and they're scanned left-to-right, in order ๐ง
A framework directory is just a folder full of frameworks ๐ and a framework is a directory that ends in .framework and has a Headers and/or PrivateHeaders directory sitting right inside it. the framework's name is the folder name without the .framework part. its headers live in one of those two folders, and Headers gets searched first ๐
A subframework is a framework directory that lives inside a framework's Frameworks directory ๐ฆ you can only #include subframework headers from inside a header of the framework that contains it, or from a sibling subframework header. two subframeworks are siblings if they're in the same framework. a subframework should not share a name with a framework, and if it does, GCC will warn you ๐จ right now a subframework can't have subframeworks of its own, but that might get added later ๐
the standard frameworks live in /System/Library/Frameworks and /Library/Frameworks. an example include looks like #include <Framework/header.h>, where Framework is the framework's name and header.h is found in its PrivateHeaders or Headers directory ๐
-iframeworkdirโ like-F, except the directory gets treated as a system directory ๐ซง the big difference is that with-iframework, the compiler won't warn you about stuff inside header files it finds throughdir. this option only works for the C family of languages ๐-arch nameโ generates output for architecturename๐ as we talked about earlier, GCC makes output for the architecture it was configured for, and you use its usual options to pick subarchitecture variants.-archis only here for compatibility, but ifnamedoesn't match GCC's own idea of the target architecture, you'll get an error ๐ โโ๏ธ-dependency-file filenameโ this is just an alias for the preprocessor option-MF filename๐ง-fapple-kextโ generates code for Darwin loadable kernel extensions ๐ฅ-gusedโ emits debugging info for symbols that are used โจ for the stabs debugging format, this also turns on-feliminate-unused-debug-symbols. it's ON by default, so you're already getting it ๐-gfullโ emits debugging info for all symbols and types ๐ the whole buffet ๐ฝ๏ธ-matt-stubs,-mno-att-stubsโ turns on (or off) AT&T-style PIC stubs ๐ฆ this is the default when the target architecture supports it, which right now means x86 only ๐-mconstant-cfstrings,-fconstant-cfstringsโ when the NeXT runtime is in use (which is the default on these systems), this overrides any-fconstant-string-classsetting and makes@"..."literals get laid out as constant CoreFoundation strings ๐ธ-fconstant-cfstringsis just an alias for-mconstant-cfstrings, so they're twins ๐ฏโโ๏ธ-mdynamic-no-picโ generates code for executables, not shared libraries ๐ heads up, this one is incompatible with-fpic,-fPIC,-fpie, and-fPIE, so don't mix them ๐ โโ๏ธ-mfix-and-continue,-ffix-and-continue,-findirect-dataโ generates code built for fast turnaround development โก the example given is letting GDB dynamically load.ofiles into programs that are already running, which is giving main character debugging energy ๐ญ-findirect-dataand-ffix-and-continueare only around for backwards compatibility ๐ซถ-mkernelโ turns on kernel development mode ๐ง this one sets-static,-fno-common,-fno-use-cxa-atexit,-fno-exceptions,-fno-non-call-exceptions,-fapple-kext,-fno-weak, and-fno-rtti, where applicable ๐ for PowerPC targets it also sets-mno-altivec,-msoft-float,-fno-builtin, and-mlong-branch๐-mmacosx-version-min=version,-asm_macosx_version_min=versionโ-mmacosx-version-minsets the earliest MacOS X version this executable will run on, which isversionโจ typical values include12,10.12, and10.5.8๐
If the compiler was built to use the system's headers by default, then the default for this option is the system version the compiler is running on. otherwise, the default is to make choices that work with as many systems and codebases as possible ๐ซง
-asm_macosx_version_min=version is similar, but the GCC driver only passes its version info to the assembler ๐ง
-mone-byte-boolโ overrides the defaults forboolso thatsizeof(bool)==1๐ by default,sizeof(bool)is 4 on Darwin/PowerPC and 1 on Darwin/x86, so this option does nothing on x86 ๐
Warning: -mone-byte-bool makes GCC generate code that is NOT binary compatible with code made without that switch ๐ญ using it might mean recompiling every other module in your program, including system libraries. only use it to conform to a non-default data model.
-msymbol-stubs,-mno-symbol-stubsโ forces generation of external symbol indirection stubs for PIC references ๐ฆ by default this gets turned on automatically if the target linker version (-mtarget-linker) is old enough to need them ๐-mtarget-linker=version,-mtarget-linker versionโ specifies the target ld64 version and overrides whatever version is in the GCC configuration ๐ฅ newer linker versions support improved code generation in some cases, like for PIC code ๐-ObjCโ equivalent to-x objective-c, which says the input is Objective-C source code ๐-ObjC++โ equivalent to-x objective-c++, which says the input is Objective-C++ source code ๐-Wnonportable-cfstrings,-Wno-nonportable-cfstringsโ warns if constant CoreFoundation string objects contain non-portable characters โ ๏ธ this warning is enabled by default ๐ซถ-all_loadโ loads all members of static archive libraries ๐ฆ seeman ld(1)for more ๐ง-arch_errors_fatalโ makes errors about files with the wrong architecture fatal ๐-bind_at_loadโ marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched ๐ธ-bundleโ produces a Mach-o bundle format file ๐ซง seeman ld(1)for more information ๐-bundle_loader executableโ specifies the executable that will load the build output file being linked ๐ seeman ld(1)for more information ๐-dynamiclibโ when you pass this, GCC produces a dynamic library instead of an executable when linking, using the Darwinlibtoolcommand ๐ฆ-force_cpusubtype_ALLโ makes GCC's output file have theALLsubtype, instead of one controlled by the-mcpuor-marchoption ๐-nodefaultrpathsโ doesn't add default run paths for the compiler library directories to executables, modules, or dynamic libraries ๐ง on macOS 10.5 and later, the embedded runpath gets added by default unless you put-nodefaultrpathson the link line. run paths are needed (and therefore enforced) to build on macOS 10.11 or later ๐-nodefaultexportโ doesn't add default symbol exports to modules or dynamic libraries ๐
These next ones are the linker options that get passed straight through to the Darwin linker, which explains them in full in its own man page ๐ no cap, it's a lot to cover here ๐ญ
-allowable_client client_nameโ passed to the Darwin linker ๐ง-client_nameโ passed to the Darwin linker ๐ง-compatibility_versionโ passed to the Darwin linker ๐ง-current_versionโ passed to the Darwin linker ๐ง-dead_stripโ passed to the Darwin linker ๐ง-dylib_fileโ passed to the Darwin linker ๐ง-dylinkerโ passed to the Darwin linker ๐ง-dylinker_install_nameโ passed to the Darwin linker ๐ง-dynamicโ passed to the Darwin linker ๐ง-exported_symbols_listโ passed to the Darwin linker ๐ง-filelistโ passed to the Darwin linker ๐ง-flat_namespaceโ passed to the Darwin linker ๐ง-force_flat_namespaceโ passed to the Darwin linker ๐ง-frameworkโ passed to the Darwin linker ๐ง-headerpad_max_install_namesโ passed to the Darwin linker ๐ง-image_baseโ passed to the Darwin linker ๐ง-init symbol-nameโ passed to the Darwin linker ๐ง-install_nameโ passed to the Darwin linker ๐ง-keep_private_externsโ passed to the Darwin linker ๐ง-pagezero_sizeโ passed to the Darwin linker ๐ง-preloadโ passed to the Darwin linker ๐ง-read_only_relocsโ passed to the Darwin linker ๐ง-sectalignโ passed to the Darwin linker ๐ง-sectcreateโ passed to the Darwin linker ๐ง-seg_addr_tableโ passed to the Darwin linker ๐ง-seg1addrโ passed to the Darwin linker ๐ง-segaddrโ passed to the Darwin linker ๐ง-segprotโ passed to the Darwin linker ๐ง-segs_read_only_addrโ passed to the Darwin linker ๐ง-segs_read_write_addrโ passed to the Darwin linker ๐ง-sub_libraryโ passed to the Darwin linker ๐ง-sub_umbrellaโ passed to the Darwin linker ๐ง-twolevel_namespaceโ passed to the Darwin linker ๐ง-twolevel_namespace_hintsโ passed to the Darwin linker ๐ง-umbrellaโ passed to the Darwin linker ๐ง-undefinedโ passed to the Darwin linker ๐ง-unexported_symbols_listโ passed to the Darwin linker ๐ง-weak_frameworkโ passed to the Darwin linker ๐ง-weak_reference_mismatchesโ passed to the Darwin linker ๐ง-whatsloadedโ passed to the Darwin linker ๐ง-whyloadโ passed to the Darwin linker ๐ง
๐ฆ DEC Alpha Options ๐ฆ
okay these are the -m options defined for the DEC Alpha implementations ๐
-mno-soft-float,-msoft-floatโ tells GCC to use (or not use) the hardware floating-point instructions for floating-point operations ๐ฅ with-msoft-float, functions inlibgcc.aget used to do the floating-point ops instead. unless those get replaced by routines that emulate the FP operations, or get compiled to call such emulation routines, those routines will issue floating-point operations ๐ญ if you're compiling for an Alpha without floating-point operations, you have to make sure the library is built so it doesn't call them ๐ โโ๏ธ
Note that Alpha implementations without floating-point operations are required to have floating-point registers ๐ง
-mfp-regs,-mno-fp-regsโ generates code that uses (or does not use) the floating-point register set ๐-mno-fp-regsimplies-msoft-float๐ซถ if the FP register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results get passed in$0instead of$f0๐ธ this is a non-standard calling sequence, so any function with a floating-point argument or return value that gets called by code compiled with-mno-fp-regsmust also be compiled with that option ๐
A typical use of this option is building a kernel that doesn't use, and so doesn't need to save and restore, any floating-point registers ๐
Okay bestie, the Alpha chip's floating-point hardware is built for maximum speed ๐๏ธ๐จ It's mostly IEEE compliant, but full compliance needs a little software help ๐ซถ
-mieeeโ This is the fully IEEE-compliant mode, except the inexact-flag isn't kept track of (more on that below) ๐ When it's on, the macro_IEEE_FPgets defined during compilation โจ The code runs slower, but it can handle denormalized numbers and the special IEEE values like not-a-number and plus/minus infinity ๐ฆ Other Alpha compilers call this-ieee_with_no_inexact๐
DEBIAN SPECIFIC: this one is on by default for alpha-linux-gnu, unless -ffinite-math-only (which is part of the -ffast-math set) is specified ๐ The reason is that the software functions in the GNU libc math libraries can produce denormalized numbers, NaNs, and infs, and without -mieee those will make a program SIGFPE the second it tries to use the results ๐
-mieee-with-inexactโ This is like-mieee, but the generated code also keeps the IEEE inexact-flag ๐ซง Turn it on and you get fully-compliant IEEE math. Along with_IEEE_FP, the macro_IEEE_FP_EXACTgets defined too โจ On some Alpha chips the code can run significantly slower than the default, and since hardly any code depends on the inexact-flag, you should normally skip this one ๐ โโ๏ธ Other Alpha compilers call it-ieee_with_inexact๐-mfp-trap-mode=trap-modeโ This controls which floating-point-related traps are enabled ๐ชค Other Alpha compilers call it-fptm trap-mode๐ The trap mode can be one of four values:nโ The default (normal) setting. The only traps enabled are the ones that can't be turned off in software, like the division by zero trap ๐uโ Everythingngives you, plus underflow traps ๐ธsuโ Likeu, but the instructions are marked as safe for software completion (check the Alpha architecture manual for the deets) ๐งsuiโ Likesu, plus inexact traps ๐
-mfp-rounding-mode=rounding-modeโ Picks the IEEE rounding mode ๐ Other Alpha compilers call it-fprm rounding-mode๐ The rounding-mode can be one of these:nโ Normal IEEE rounding. Numbers get rounded towards the nearest machine number, or towards the even machine number if it's a tie โ๏ธmโ Round towards minus infinity โฌ๏ธcโ Chopped rounding. Numbers get rounded towards zero ๐ซงdโ Dynamic rounding. A field in the floating-point control register (fpcr, see the Alpha architecture reference manual) decides which rounding mode is in effect ๐๏ธ The C library sets this register to round towards plus infinity, so unless your program changes the fpcr,dmeans round towards plus infinity โจ
-mtrap-precision=trap-precisionโ Okay so, Alpha floating-point traps are imprecise ๐ญ Without software help you can't recover from a floating trap, and the program usually has to be terminated. GCC can generate code that helps OS trap handlers figure out the exact spot that caused a floating-point trap ๐ You can pick how precise you want it:pโ Program precision. This is the default, and it means a trap handler can only tell which program caused a floating-point exception ๐ฆfโ Function precision. The trap handler can find the function that caused the exception ๐งฉiโ Instruction precision. The trap handler can find the exact instruction that caused the exception ๐ฏ
Other Alpha compilers have equivalent options called -scope_safe and -resumption_safe ๐
-mieee-conformantโ Marks the generated code as IEEE conformant ๐ > Don't use this unless you also specify-mtrap-precision=iand either-mfp-trap-mode=suor-mfp-trap-mode=sui, or it's not gonna be it ๐ โโ๏ธ Its only effect is to emit the line.eflag 48in the function prologue of the generated assembly file ๐งพ-mbuild-constantsโ Normally, GCC looks at a 32- or 64-bit integer constant to see if it can put it together from smaller constants in two or three instructions ๐งฉ If it can't, it outputs the constant as a literal and generates code to load it from the data segment at run time. Use this option to make GCC build all integer constants with code, even if that takes more instructions (the max is six) ๐จ You typically use this when building a shared library dynamic loader ๐ช Since it's itself a shared library, it has to relocate itself in memory before it can find the variables and constants in its own data segment ๐-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ These decide whether GCC should generate code that uses the optional BWX, CIX, FIX and MAX instruction sets ๐๏ธ By default it uses whichever instruction sets the CPU type from-mcpu=supports, or the ones supported by the CPU GCC was built on if you didn't specify one ๐ซถ-msafe-bwa,-mno-safe-bwaโ These decide whether, without the optional BWX instruction set, GCC should generate multi-thread and async-signal safe code for byte and aligned word memory accesses ๐งต-msafe-partial,-mno-safe-partialโ These decide whether GCC should generate multi-thread and async-signal safe code for partial memory accesses ๐งฉ That includes piecemeal accesses to unaligned data, plus block accesses to the leading and trailing parts of aggregate types or other objects in memory that don't start and end on an aligned 64-bit data boundary ๐-mfloat-vax,-mfloat-ieeeโ-mfloat-vaxgenerates code that uses VAX F and G floating-point arithmetic, and-mfloat-ieeegenerates code that does not use it, so you get IEEE single and double precision instead ๐ฆ-mexplicit-relocs,-mno-explicit-relocsโ Older Alpha assemblers had no way to generate symbol relocations except through assembler macros, and those macros don't allow optimal instruction scheduling ๐ฉ GNU Binutils as of version 2.12 supports a new syntax that lets the compiler explicitly mark which relocations apply to which instructions ๐ This option is mostly useful for debugging, since GCC detects the assembler's capabilities when it's built and sets the default accordingly ๐ง-msmall-data,-mlarge-dataโ When-mexplicit-relocsis in effect, static data is accessed through gp-relative relocations ๐๏ธ With-msmall-data, objects 8 bytes long or smaller get placed in a small data area (the.sdataand.sbsssections) and get accessed through 16-bit relocations off of the$gpregister โจ This caps the small data area at 64KB, but the variables can be accessed with a single instruction, which is iconic ๐
The default is -mlarge-data. With this option, the data area is limited to just below 2GB ๐ Programs that need more than 2GB of data must use malloc or mmap to allocate the data in the heap instead of in the program's data segment ๐ง
When generating code for shared libraries, -fpic implies -msmall-data, and -fPIC implies -mlarge-data ๐ซง
-msmall-text,-mlarge-textโ With-msmall-text, the compiler assumes the code of the entire program (or shared library) fits in 4MB, so it's reachable with a branch instruction ๐ฆ When-msmall-datais also used, the compiler can assume all local symbols share the same$gpvalue, which cuts the instructions for a function call from 4 down to 1 ๐โโ๏ธ The default is-mlarge-text๐ธ-mcpu=cpu_typeโ Sets the instruction set and instruction scheduling parameters for the machine type cpu_type ๐ป You can use either the EV style name or the matching chip number. GCC supports scheduling parameters for the EV4, EV5 and EV6 families, and it picks the default instruction set values from the processor you specify ๐ฏ If you don't specify a processor type, GCC defaults to the processor the compiler was built on ๐๏ธ
Supported values for cpu_type are:
ev4,ev45,21064โ Schedules as an EV4 and has no instruction set extensions ๐ฑev5,21164โ Schedules as an EV5 and has no instruction set extensions ๐ฟev56,21164aโ Schedules as an EV5 and supports the BWX extension ๐pca56,21164pc,21164PCโ Schedules as an EV5 and supports the BWX and MAX extensions ๐ทev6,21264โ Schedules as an EV6 and supports the BWX, FIX, and MAX extensions ๐บev67,21264aโ Schedules as an EV6 and supports the BWX, CIX, FIX, and MAX extensions ๐
Native toolchains also support the value native, which picks the best architecture option for the host processor ๐ฅ๏ธ -mcpu=native has no effect if GCC doesn't recognize the processor ๐คทโโ๏ธ
-mtune=cpu_typeโ Sets only the instruction scheduling parameters for the machine type cpu_type ๐ถ The instruction set stays the same. Native toolchains also supportnative, which picks the best architecture option for the host processor ๐ฅ๏ธ-mtune=nativehas no effect if GCC doesn't recognize the processor ๐ซ-mmemory-latency=timeโ Sets the latency the scheduler should assume for typical memory references as the application sees them โฑ๏ธ This number depends a lot on the application's memory access patterns and the size of the external cache on the machine ๐ง Valid options for time are:numberโ A decimal number representing clock cycles ๐ขL1,L2,L3,mainโ GCC has estimates of clock cycles for "typical" EV4 & EV5 hardware at the Level 1, 2 & 3 caches (also called Dcache, Scache, and Bcache), as well as main memory ๐ง Heads up,L3is only valid for EV5 โ ๏ธ
-mtls-kernelโ Emitsrdvalinstead ofrduniqfor the thread pointer ๐งตโจ
๐ฆ eBPF Options ๐ฆ
-mtls-size=bitsizeโ okay so this one sets the bit size of immediate TLS offsets ๐ The valid values are16,32, and64, and it defaults to32โจ-mlong-double-128,-mlong-double-64โ these decide how big the "long double" type is ๐ ngl-mlong-double-128is incompatible with VAX floating point, so don't mix them ๐
๐ง eBPF Options ๐ง
-mframe-limit=bytesโ this is the hard limit for frame sizes, in bytes ๐ฆ The value has to be less than or equal to32767. If you don't pick one, it defaults to whatever limit the version of the Linux kernel you're targeting imposes ๐ธ-mbig-endianโ generates code for a big-endian target ๐-mlittle-endianโ generates code for a little-endian target. This is the default, so you're already slaying ๐-mjmpext,-mno-jmpextโ turn the extra conditional-branch instructions on or off ๐ฆ They're enabled for CPU v2 and above.-mjmp32,-mno-jmp32โ turn 32-bit jump instructions on or off ๐ Enabled for CPU v3 and above.-malu32,-mno-alu32โ turn 32-bit ALU instructions on or off โจ Enabled for CPU v3 and above.-mv3-atomics,-mno-v3-atomicsโ turn on or off the instructions for general atomic operations that came in with CPU v3 โก Enabled for CPU v3 and above.-mbswap,-mno-bswapโ turn byte swap instructions on or off ๐ Enabled for CPU v4 and above.-msdiv,-mno-sdivโ turn signed division and modulus instructions on or off โ Enabled for CPU v4 and above.-msmov,-mno-smovโ turn sign-extending move and memory load instructions on or off ๐ Enabled for CPU v4 and above.-mcpu=versionโ picks which version of the eBPF ISA you're targeting ๐ Newer versions might not be supported by every kernel, so check first ๐ The default isv4.
Here are the supported values for version:
v1โ the first stable eBPF ISA, with no special features or extensions ๐ผv2โ supports the jump extensions, as in-mjmpext๐ฆv3โ all the v2 features, plus:- 32-bit jump operations, as in
-mjmp32 - 32-bit ALU operations, as in
-malu32 - general atomic operations, as in
-mv3-atomics
- 32-bit jump operations, as in
v4โ all the v3 features, plus:- byte swap instructions, as in
-mbswap - signed division and modulus instructions, as in
-msdiv - sign-extending move and memory load instructions, as in
-msmov
- byte swap instructions, as in
-mco-re,-mno-co-reโ enable or disable BPF Compile Once - Run Everywhere (CO-RE) support ๐ CO-RE support is enabled by default when you generate BTF debug information for the BPF target (-gbtf).-mxbpfโ generates code for an expanded version of BPF that relaxes some of the usual BPF restrictions ๐ One of the things it does is save and restore callee-saved registers at function entry and exit, respectively.-masm=dialectโ outputs assembly using the eBPF dialect you pick ๐ The default ispseudoc.
Here are the supported values for dialect:
normalโ outputs the normal assembly dialectpseudocโ outputs the pseudo-C assembly dialect
-minline-memops-threshold=bytesโ sets a size threshold in bytes. At or below it,memmove,memcpy, andmemsetare always expanded inline ๐ง Anything bigger would need a library call instead, but BPF doesn't allow libcalls, so going over the threshold is a compile-time error ๐ The default is1024bytes.-Wco-reโ turns on warnings for situations where-mco-reis enabled but it might not be possible to generate CO-RE compatible code ๐
๐ธ FR30 Options ๐ธ
These options are defined specifically for the FR30 port ๐
-msmall-modelโ uses the small address space model ๐ฃ This can make smaller code, but it assumes that all symbolic values and addresses fit into a 20-bit range.-mno-lsimโ assumes runtime support has already been provided, so there's no need to include the simulator library (libsim.a) on the linker command line ๐ง
๐ FRV Options ๐
-mgpr-32โ only uses the first 32 general-purpose registers ๐ข-mgpr-64โ uses all 64 general-purpose registers ๐-mfpr-32โ uses only the first 32 floating-point registers ๐ข-mfpr-64โ uses all 64 floating-point registers ๐ช-mhard-floatโ uses hardware instructions for floating-point operations โก-msoft-floatโ uses library routines for floating-point operations instead ๐-malloc-ccโ dynamically allocates condition code registers ๐ช-mfixed-ccโ doesn't try to dynamically allocate condition code registers, and only usesicc0andfcc0๐-mdword,-mno-dwordโ control whether the ABI uses double-word instructions ๐-mdouble,-mno-doubleโ enable or disable use of floating-point double instructions ๐ฆ-mmedia,-mno-mediaโ enable or disable use of media instructions ๐ถ-mmuladd,-mno-muladdโ enable or disable use of multiply and add/subtract instructions โ๏ธ-mfdpicโ selects the FDPIC ABI, which uses function descriptors to represent pointers to functions ๐งญ Without any PIC/PIE-related options, it implies-fPIE. With-fpicor-fpie, it assumes GOT entries and small data are within a 12-bit range from the GOT base address. With-fPICor-fPIE, GOT offsets are computed with 32 bits ๐ข With abfin-elftarget, this option implies-msim.-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally ๐งฉ It has no effect without-mfdpic. It's enabled by default if you're optimizing for speed and compiling for shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is in the command line โก-mTLSโ assumes a large TLS segment when generating thread-local code ๐งต-mtlsโ does not assume a large TLS segment when generating thread-local code ๐งถ-mgprel-roโ enables the use of"GPREL"relocations in the FDPIC ABI for data that's known to be in read-only sections ๐ It's enabled by default, except for-fpicor-fpie. Even though it may help make the global offset table smaller, it trades 1 instruction for 4 there ๐ค With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols, and it avoids the need for a GOT entry for the referenced symbol, so it's more likely to be a win โจ If it isn't, you can use-mno-gprel-roto disable it.-multilib-library-picโ links with the (library, not FD) pic libraries ๐ฆ It's implied by-mlibrary-pic, as well as by-fPICand-fpicwithout-mfdpic. You should never have to use it explicitly ๐ โโ๏ธ-mlinked-fpโ follows the EABI requirement of always creating a frame pointer whenever a stack frame is allocated ๐ผ๏ธ This option is enabled by default and can be disabled with-mno-linked-fp.-mlong-callsโ uses indirect addressing to call functions outside the current compilation unit ๐ This lets the functions be placed anywhere within the 32-bit address space ๐-malign-labelsโ tries to align labels to an 8-byte boundary by inserting NOPs into the previous packet ๐งฑ This only does anything when VLIW packing is enabled. It doesn't create new packets; it just adds NOPs to existing ones ๐ซถ-mlibrary-picโ generates position-independent EABI code ๐งญ-macc-4โ uses only the first four media accumulator registers 4๏ธโฃ-macc-8โ uses all eight media accumulator registers 8๏ธโฃ-mpack,-mno-packโ enable or disable packing VLIW instructions ๐ฆ-mno-eflagsโ does not mark ABI switches ine_flags๐ซ-mcond-move,-mno-cond-moveโ enable or disable the use of conditional-move instructions. It's enabled by default โช๏ธ
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mscc,-mno-sccโ enable or disable the use of conditional set instructions. It's enabled by default ๐ฏ
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mcond-exec,-mno-cond-execโ enable or disable the use of conditional execution. It's enabled by default ๐โโ๏ธ
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mvliw-branch,-mno-vliw-branchโ enable or disable an optimization pass that packs branches into VLIW instructions. It's enabled by default ๐ฆ
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mmulti-cond-exec,-mno-multi-cond-execโ enable or disable optimization of"&&"and"||"in conditional execution. It's enabled by default ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mnested-cond-exec,-mno-nested-cond-execโ enable or disable nested conditional execution optimizations. It's enabled by default ๐ช
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-moptimize-membar,-mno-optimize-membarโ this switch removes redundantmembarinstructions from the compiler-generated code ๐งน It's enabled by default.-mtomcat-statsโ makes gas print out tomcat statistics ๐-mcpu=cpuโ selects the processor type to generate code for ๐ฅ๏ธ The possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300, andsimpleโจ
๐ FT32 Options ๐
These options are defined specifically for the FT32 port ๐
-msimโ specifies that the program will run on the simulator ๐ฅ๏ธ This causes an alternate runtime startup and library to be linked.
You must not use this option when generating programs that will run on real hardware ๐จ You must provide your own runtime library for whatever I/O functions are needed.
-mnodivโ does not usedivandmodinstructions โ-mft32bโ enables use of the extended instructions of the FT32B processor ๐-mcompressโ compresses all code using the FT32B code compression scheme ๐๏ธ-mnopmโ does not generate code that reads program memory ๐ต
๐ง GNU/Linux Options ๐ง
These -m options are defined for GNU/Linux targets ๐ง
-mglibcโ uses the GNU C library ๐ This is the default, except on*-*-linux-*uclibc*,*-*-linux-*musl*, and*-*-linux-*android*targets ๐-muclibc๐ Okay bestie, this one switches GCC over to the uClibc C library. It's the default on*-*-linux-*uclibc*targets.-mmusl๐ธ This one uses the musl C library instead. It's the default on*-*-linux-*musl*targets.-mbionic๐ค This one uses the Bionic C library. It's the default on*-*-linux-*android*targets.-mandroid,-mno-android๐ฑ This makes your code Android-compatible ๐ It's the default on*-*-linux-*android*targets.- When compiling, it turns on
-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default. When linking, it makes the GCC driver pass Android-specific options to the linker. It also defines the preprocessor macro"__ANDROID__". - You can turn all of this off with
-mno-android.
- When compiling, it turns on
-tno-android-cc๐ โโ๏ธ This turns off the compilation side of-mandroid. So-mbionic,-fPIC,-fno-exceptionsand-fno-rttiwon't get turned on by default.-tno-android-ld๐ง This turns off the linking side of-mandroid. The linker gets the standard Linux linking options instead.
โจ H8/300 Options โจ
Okay so these -m options are only for the H8/300 implementations ๐ง
-mrelax๐ฆ Shortens some address references at link time, whenever that's possible. It does this by using the linker option-relax.-mh๐ Generates code for the H8/300H.-msโจ Generates code for the H8S.-mn๐ Generates code for the H8S and H8/300H in the normal mode. You have to use this with either-mhor-ms.-msx๐ฅ Generates H8SX code.-ms2600๐ Generates code for the H8S/2600. You must use this with-ms.-mquickcall๐ซถ Uses registers for passing arguments.-mslowbyte๐ข Treats access to byte-sized memory as slow.-mexr,-mno-exr๐ Stores extended registers on the stack before running functions with the"monitor"attribute. The default is-mexr. This one is only valid for H8S targets.-mint32๐ Makes"int"data 32 bits by default.-malign-300๐ On the H8/300H and H8S, this uses the same alignment rules as the H8/300. By default those chips align longs and floats on 4-byte boundaries.-malign-300moves them to 2-byte boundaries instead. It has no effect on the H8/300.
โจ HPPA Options โจ
These -m options are defined for the HPPA family of computers ๐ฅ๏ธ
-march=architecture-type๐๏ธ Generates code for the architecture you specify. The choices are1.0for PA 1.0,1.1for PA 1.1 and2.0for PA 2.0 processors. To find the right architecture option for your machine, check/usr/lib/sched.modelson an HP-UX system. Code compiled for lower-numbered architectures runs on higher-numbered ones, but not the other way around.-mpa-risc-1-0,-mpa-risc-1-1,-mpa-risc-2-0๐ฏ These are synonyms for-march=1.0,-march=1.1and-march=2.0, respectively.-matomic-libcalls,-mno-atomic-libcallsโ๏ธ Generates libcalls for atomic loads and stores when sync libcalls are disabled. This one is enabled by default. It only affects how the HPPA backend generates atomic libcalls.- Both the sync and libatomic libcall implementations use locking ๐ So processor stores aren't atomic with respect to other atomic operations. Processor loads up to
DImodeare atomic with respect to other atomic operations, as long as they're implemented as a single access. - The PA-RISC architecture doesn't support any atomic operations in hardware except the
"ldcw"instruction. So all atomic support is implemented using sync and atomic libcalls. Sync libcall support lives inlibgcc.a, and atomic libcall support lives inlibatomic. - This option generates
"__atomic_exchange"calls for atomic stores. It also gives special handling to atomicDImodeaccesses on 32-bit targets.
- Both the sync and libatomic libcall implementations use locking ๐ So processor stores aren't atomic with respect to other atomic operations. Processor loads up to
-mcaller-copies๐ฆ The caller copies function arguments that get passed by hidden reference. Use this one with care, because it isn't compatible with the default 32-bit runtime. Only aggregates larger than eight bytes are passed by hidden reference, though, and this option gives better compatibility with OpenMP ๐-mcoherent-ldcw๐ง Uses theldcw/ldcdcoherent cache-control hint.-mdisable-fpregs๐ซ Disables floating-point registers. It's equivalent to-msoft-float.-mdisable-indexing๐ Stops the compiler from using indexing address modes. This avoids some pretty obscure problems when compiling MIG generated code under MACH.-mfast-indirect-calls๐๏ธ Generates code that assumes calls never cross space boundaries. This lets GCC emit faster indirect calls.- Heads up: this doesn't work in the presence of shared libraries or nested functions โ ๏ธ
-mfixed-range=register-range๐ Generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use, which is handy when compiling kernel code. Write a register range as two registers separated by a dash. You can list multiple ranges separated by a comma.-mgas๐งต Enables assembler directives that only GAS understands.-mgnu-ld๐ Uses options specific to GNU ld. This passes-sharedto ld when building a shared library. It's the default when GCC is configured, explicitly or implicitly, with the GNU linker.- This option doesn't change which ld gets called. It only changes the parameters passed to that ld. The ld that's called is decided by the
--with-ldconfigure option, then GCC's program search path, and finally the user'sPATH. - You can print the linker GCC uses with
which `gcc -print-prog-name=ld`. - This option is only available on the 64-bit HP-UX GCC, i.e. configured with
hppa*64*-*-hpux*.
- This option doesn't change which ld gets called. It only changes the parameters passed to that ld. The ld that's called is decided by the
-mhp-ld๐ข Uses options specific to HP ld. This passes-bto ld when building a shared library, and passes+Accept TypeMismatchto ld on all links. It's the default when GCC is configured, explicitly or implicitly, with the HP linker.- Like
-mgnu-ld, this doesn't change which ld gets called. It only changes the parameters passed to it. The ld that's called is decided by the--with-ldconfigure option, GCC's program search path, and finally the user'sPATH. - You can print the linker GCC uses with
which `gcc -print-prog-name=ld`. - This option is only available on the 64-bit HP-UX GCC, i.e. configured with
hppa*64*-*-hpux*.
- Like
-mlinker-opt๐ง Enables the optimization pass in the HP-UX linker.- Heads up: this makes symbolic debugging impossible ๐
-mlong-calls๐ Generates code that uses long call sequences. This makes sure a call can always reach linker generated stubs.- By default, long calls are only generated when the distance from the call site to the beginning of the function or translation unit (depending on the case) goes past a predefined limit. That limit is set by the branch type being used. The limits for normal calls are 7,600,000 and 240,000 bytes, for PA 2.0 and PA 1.X architectures respectively. Sibling calls are always limited to 240,000 bytes.
- Distances are measured from the beginning of functions when using the
-ffunction-sectionsoption. They're also measured that way when using the-mgasand-mno-portable-runtimeoptions together under HP-UX with the SOM linker. - It's usually not something you want, since it degrades performance ๐ฌ But it may be useful in large applications, especially when partial linking is used to build the application.
- The types of long calls used depend on the capabilities of the assembler and linker, and on the type of code being generated. Systems that support long absolute calls, and long PIC symbol-difference or PC-relative calls, should see a relatively small impact. An indirect call is used on 32-bit ELF systems in PIC code, though, and it's quite long ๐ซ
-mlong-load-store๐ฆ Generates 3-instruction load and store sequences, which the HP-UX 10 linker sometimes requires. This is equivalent to the+koption to the HP compilers.-mno-space-regs๐ Generates code that assumes the target has no space registers. This allows GCC to generate faster indirect calls and use unscaled index address modes. Such code is suitable for level 0 PA systems and kernels.-mordered๐งฑ Assumes memory references are ordered, so barriers aren't needed.-mportable-runtime๐งณ Uses the portable calling conventions HP proposed for ELF systems.-mschedule=cpu-type๐๏ธ Schedules code according to the constraints for the machine typecpu-type. The choices are700 7100,7100LC,7200,7300and8000. To find the right scheduling option for your machine, check/usr/lib/sched.modelson an HP-UX system. The default scheduling is8000.-msio,-mwsio๐จ๏ธ-msiogenerates the predefine"_SIO"for server IO. The default is-mwsio, which generates the predefines"__hp9000s700","__hp9000s700__"and"_WSIO"for workstation IO. These options are available under HP-UX and HI-UX.-msoft-float๐งฎ Generates output containing library calls for floating point.
Warning: the requisite libraries aren't available for all HPPA targets. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation. You must make your own arrangements to provide suitable library functions for cross-compilation.
-msoft-float changes the calling convention in the output file, so it's only useful if you compile all of a program with this option. In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work.
-msoft-mult๐ Uses software integer multiplication. This disables the use of the"xmpyu"instruction.-munix=unix-stdโฐ Generates compiler predefines and selects a startfile for the specified UNIX standard. The choices are93,95and98.93is supported on all HP-UX versions.95is available on HP-UX 10.10 and later.98is available on HP-UX 11.11 and later. The defaults are93for HP-UX 10.00,95for HP-UX 10.10 through 11.00, and98for HP-UX 11.11 and later.
okay so -munix=93 gives you the exact same predefines as GCC 3.3 and 3.4 ๐ธ and then it's giving upgrades. -munix=95 adds extra predefines for XOPEN_UNIX and _XOPEN_SOURCE_EXTENDED, plus the startfile unix95.o โจ. -munix=98 goes even harder ๐ฅ with extra predefines for _XOPEN_UNIX, _XOPEN_SOURCE_EXTENDED, _INCLUDE__STDC_A1_SOURCE and _INCLUDE_XOPEN_SOURCE_500, plus the startfile unix98.o ๐ฆ.
๐ญ bestie, listen: this option changes the interfaces for various library routines, and it also messes with the operational behavior of the C library. So extreme care is needed when you use it ๐
If you're writing library code that has to work with more than one UNIX standard, you need to test, set and restore the variable __xpg4_extended_mask as appropriate ๐ง. Most GNU software doesn't provide this capability, so don't be surprised if it's missing ๐
โจ OPTIONS โจ
-nolibdldโ no link options to search libdld.sl get generated when-staticis used on HP-UX 10 and later ๐ซถ-staticโ okay, this one's a whole saga ๐ญ. The HP-UX C library version ofsetlocaledepends on libdld.sl, and there's no archive version of it. So when you pass-static, you need special link options to sort that dependency out ๐ . On HP-UX 10 and later, the GCC driver adds the necessary options to link with libdld.sl for you, which means the resulting binary ends up dynamic ๐ฆ. On the 64-bit port, the linkers already make dynamic binaries by default anyway. If you don't want the driver adding those link options, use-nolibdld๐-threadsโ adds multithreading support with the dce thread library under HP-UX ๐งต and sets flags for both the preprocessor and the linker โจ
๐ธ IA-64 Options ๐ธ
These are the -m options defined for the Intel IA-64 architecture ๐
-mbig-endianโ generates code for a big-endian target. This is the default for HP-UX ๐-mlittle-endianโ generates code for a little-endian target. This is the default for AIX5 and GNU/Linux ๐-mgnu-as,-mno-gnu-asโ generates (or doesn't) code for the GNU assembler. The-mgnu-asone is the default ๐ง-mgnu-ld,-mno-gnu-ldโ generates (or doesn't) code for the GNU linker. This is the default too ๐-mno-picโ generates code that doesn't use a global pointer register. heads up: the result is not position independent code, and it violates the IA-64 ABI ๐-mvolatile-asm-stop,-mno-volatile-asm-stopโ generates (or doesn't) a stop bit right before and right after volatile asm statements ๐-mregister-names,-mno-register-namesโ generates (or doesn't)in,loc, andoutregister names for the stacked registers. This may make assembler output more readable ๐-mno-sdata,-msdataโ disables (or enables) optimizations that use the small data section. This may be useful for working around optimizer bugs ๐-mconstant-gpโ generates code that uses a single constant global pointer value. This is useful when compiling kernel code ๐ง-mauto-picโ generates code that is self-relocatable. This implies-mconstant-gp. It's useful when compiling firmware code ๐ฅ-minline-float-divide-min-latencyโ generates code for inline divides of floating-point values using the minimum latency algorithm โก-minline-float-divide-max-throughputโ generates code for inline divides of floating-point values using the maximum throughput algorithm ๐-mno-inline-float-divideโ doesn't generate inline code for divides of floating-point values ๐-minline-int-divide-min-latencyโ generates code for inline divides of integer values using the minimum latency algorithm โก-minline-int-divide-max-throughputโ generates code for inline divides of integer values using the maximum throughput algorithm ๐-mno-inline-int-divideโ doesn't generate inline code for divides of integer values ๐-minline-sqrt-min-latencyโ generates code for inline square roots using the minimum latency algorithm โก-minline-sqrt-max-throughputโ generates code for inline square roots using the maximum throughput algorithm ๐-mno-inline-sqrtโ doesn't generate inline code forsqrt๐-mno-dwarf2-asm,-mdwarf2-asmโ doesn't (or does) generate assembler code for the DWARF line number debugging info. This may be useful when you're not using the GNU assembler ๐ฃ-mearly-stop-bits,-mno-early-stop-bitsโ allows stop bits to be placed earlier than immediately before the instruction that triggered the stop bit. This can improve instruction scheduling, but it doesn't always ๐คทโโ๏ธ-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use. This is useful when compiling kernel code ๐ซง. A register range is two registers separated by a dash, and you can list multiple ranges separated by a comma ๐-mtls-size=tls-sizeโ specifies the bit size of immediate TLS offsets. Valid values are14,22, and64๐-mtune=cpu-typeโ tunes the instruction scheduling for a particular CPU. Valid values areitanium,itanium1,merced,itanium2, andmckinley๐ฏ-milp32,-mlp64โ generates code for a 32-bit or 64-bit environment. The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits. These are HP-UX specific flags ๐ฐ-mno-sched-br-data-spec,-msched-br-data-specโ (dis/en)ables data speculative scheduling before reload. This results in generation ofld.ainstructions and the corresponding check instructions (ld.c/chk.a). The default setting is disabled ๐-msched-ar-data-spec,-mno-sched-ar-data-specโ (en/dis)ables data speculative scheduling after reload. This results in generation ofld.ainstructions and the corresponding check instructions (ld.c/chk.a). The default setting is enabled โ-mno-sched-control-spec,-msched-control-specโ (dis/en)ables control speculative scheduling. This feature is only available during region scheduling (that is, before reload). It results in generation of theld.sinstructions and the corresponding check instructionschk.s. The default setting is disabled ๐-msched-br-in-data-spec,-mno-sched-br-in-data-specโ (en/dis)ables speculative scheduling of the instructions that depend on the data speculative loads before reload. This is only effective with-msched-br-data-specenabled. The default setting is enabled โ-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ (en/dis)ables speculative scheduling of the instructions that depend on the data speculative loads after reload. This is only effective with-msched-ar-data-specenabled. The default setting is enabled โ-msched-in-control-spec,-mno-sched-in-control-specโ (en/dis)ables speculative scheduling of the instructions that depend on the control speculative loads. This is only effective with-msched-control-specenabled. The default setting is enabled โ-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ if enabled, speculative dependencies are considered when computing the instruction priorities. This makes the use of speculation a bit more conservative. The default setting is disabled ๐-msched-spec-ldc,-mno-sched-spec-ldcโ uses a simple data speculation check. This option is on by default ๐ข-msched-control-spec-ldc,-mno-sched-control-spec-ldcโ uses a simple check for control speculation. This option is on by default ๐ข-msched-stop-bits-after-every-cycle,-mno-sched-stop-bits-after-every-cycleโ places a stop bit after every cycle when scheduling. This option is on by default ๐ข-msched-fp-mem-deps-zero-cost,-mno-sched-fp-mem-deps-zero-costโ assumes that floating-point stores and loads are not likely to cause a conflict when placed into the same instruction group. This option is disabled by default ๐-msel-sched-dont-check-control-spec,-mno-sel-sched-dont-check-control-specโ generates checks for control speculation in selective scheduling. This flag is disabled by default ๐-msched-max-memory-insns=max-insnsโ sets a limit on the number of memory insns per instruction group, giving lower priority to subsequent memory insns that try to schedule in the same instruction group. This is frequently useful for preventing cache bank conflicts. The default value is1๐งฑ-msched-max-memory-insns-hard-limit,-mno-sched-max-memory-insns-hard-limitโ makes the limit set by-msched-max-memory-insnsa hard limit, disallowing more than that number in an instruction group. Otherwise the limit is "soft," meaning non-memory operations are preferred when the limit is reached, but memory operations may still be scheduled ๐ซ
๐ฆ LM32 Options ๐ฆ
These -m options are defined for the LatticeMico32 architecture ๐ท
-mbarrel-shift-enabledโ enables barrel-shift instructions ๐-mdivide-enabledโ enables divide and modulus instructions โ-mmultiply-enabledโ enables multiply instructions โ๏ธ-msign-extend-enabledโ enables sign extend instructions ๐งฒ-muser-enabledโ enables user-defined instructions ๐งโ๐ป
๐ LoongArch Options ๐
These command-line options are defined for LoongArch targets ๐
-march=arch-typeโ generates instructions for the machine type arch-type.-march=arch-typelets GCC generate code that may not run at all on processors other than the one you indicated ๐ฌ. The choices for arch-type are:nativeโ the local processor type detected by the native compiler ๐loongarch64โ the generic LoongArch 64-bit processor ๐la464โ a LoongArch LA464-based processor with LSX and LASX ๐ธla664โ a LoongArch LA664-based processor with LSX, LASX and all LoongArch v1.1 instructions ๐la64v1.0โ LoongArch64 ISA version 1.0 ๐งฉla64v1.1โ LoongArch64 ISA version 1.1 ๐งฉla32v1.0โ LoongArch32 ISA version 1.0 ๐งฉla32rv1.0โ LoongArch32 Reduced ISA version 1.0 ๐งฉ
More info about the LoongArch ISA versions can be found at <https://github.com/loongson/la-toolchain-conventions> ๐
-mtune=tune-typeโ optimizes the generated code for the given processor target ๐ฏ
The choices for tune-type are:
nativeโ the local processor type, sniffed out by the native compiler ๐genericโ a generic LoongArch processor ๐ธloongarch64โ a generic LoongArch 64-bit processor ๐la464โ the LoongArch LA464 core โจla664โ the LoongArch LA664 core ๐ฆloongarch32โ a generic LoongArch 32-bit processor ๐ง
-mabi=base-abi-typeโ okay so this one picks the calling convention you want the code generated for ๐base-abi-typecan be one of:lp64dโ uses 64-bit general purpose registers and 32/64-bit floating-point registers for passing parameters ๐ The data model is LP64, sointis 32 bits whilelong intand pointers are 64 bits.lp64fโ uses 64-bit general purpose registers and 32-bit floating-point registers for passing parameters ๐ Same LP64 data model:intis 32 bits,long intand pointers are 64 bits.lp64sโ uses 64-bit general purpose registers and no floating-point registers for passing parameters ๐ซถ Same LP64 data model:intis 32 bits,long intand pointers are 64 bits.
-mfpu=fpu-typeโ generates code for the FPU type you pick, which can be one of:64โ lets hardware floating-point instructions be used for both 32-bit and 64-bit operations ๐ฅ32โ lets hardware floating-point instructions be used for 32-bit operations only ๐noneor0โ stops hardware floating-point instructions from being used at all ๐
-msimd=simd-typeโ turns on LoongArch SIMD instructions for vectorization and builtin functions โญ The value can be one of:lasxโ enables instructions from the 256-bit LoongArch Advanced SIMD Extension (LASX) and the 128-bit LoongArch SIMD Extension (LSX) ๐lsxโ enables instructions from the 128-bit LoongArch SIMD Extension (LSX) only ๐noneโ no LoongArch SIMD instruction is allowed to be generated ๐
-msoft-floatโ forces-mfpu=noneand stops floating-point registers from being used for passing parameters ๐งธ Heads up: this one may change the target ABI ๐จ-msingle-floatโ forces-mfpu=32and lets 32-bit floating-point registers be used for passing parameters ๐ฆ Also may change the target ABI โ ๏ธ-mdouble-floatโ forces-mfpu=64and lets 32/64-bit floating-point registers be used for passing parameters ๐ Yep, this one may change the target ABI too ๐-mlasx,-mno-lasx,-mlsx,-mno-lsxโ these incrementally adjust how much of the SIMD stuff (none / LSX / LASX) the compiler is allowed to use for code generation ๐ Turning on LASX with-mlasxautomatically turns on LSX too, and turning off LSX with-mno-lsxautomatically turns off LASX. These are driver-only options: they act on the final-msimdconfiguration and make changes in the order they show up on the GCC driver's command line ๐ That gives the final, canonicalized-msimdoption that gets passed to the compiler proper ๐ง-mbranch-cost=nโ sets the cost of branches to roughlyninstructions ๐ธ-maddr-reg-reg-cost=nโ sets the cost ofADDRESS_REG_REGto the value calculated byn๐-mcheck-zero-division,-mno-check-zero-divisonโ this pair decides whether integer division by zero traps (or doesn't) ๐ Fun fact: the page really does spell the second one-mno-check-zero-divisonwith that typo, so copy it exactly ๐ The default is-mcheck-zero-divisionfor-O0or-Og, and-mno-check-zero-divisionfor other optimization levels โจ-mbreak-code=codeโ tells GCC to emit a"break"code instruction for irrecoverable traps, the kind coming from"__builtin_trap"or inserted by the compiler (like an erroneous path isolated with-fisolate-erroneous-paths-dereference) ๐ฅ The other option is an"amswap.w $r0, $r1, $r0"instruction, which makes the hardware trigger an Instruction Not-defined Exception ifcodeis negative or greater than32767๐ฅ The default is-1, which means use the"amswap.w"instruction ๐-mcond-move-int,-mno-cond-move-intโ conditional moves for integral data in general-purpose registers are enabled (or disabled) ๐ง The default is-mcond-move-int๐-mcond-move-float,-mno-cond-move-floatโ conditional moves for floating-point registers are enabled (or disabled) ๐ฆ The default is-mcond-move-floatโจ-mmemcpy,-mno-memcpyโ forces (or doesn't force) the use of"memcpy"for non-trivial block moves ๐ซถ The default is-mno-memcpy, which lets GCC inline most constant-sized copies ๐ Setting the optimization level to-Osalso forces"memcpy", but-mno-memcpycan override that if you set it explicitly, no matter what order the options show up in on the command line ๐-mstrict-align,-mno-strict-alignโ avoids (or allows) generating memory accesses that may not be aligned on a natural object boundary, as described in the architecture specification ๐ The default is-mno-strict-align๐-G numโ puts global and static data smaller thannumbytes into a small data section ๐งธ The default value is0๐ธ-mmax-inline-memcpy-size=nโ inlines all block moves (like calls to"memcpy"or structure copies) less than or equal tonbytes ๐ The default value ofnis1024โญ-mcmodel=code-modelโ sets the code model to one of the following ๐tiny-static(Not implemented yet) ๐tiny(Not implemented yet) ๐normalโ the text segment must be within 128MB of addressing space, and the data segment must be within 2GB of addressing space ๐mediumโ the text segment and data segment must both be within 2GB of addressing space ๐ฆ This is the default code model, unless GCC was configured with--with-cmodel=specifying a different default code model ๐large(Not implemented yet) ๐extremeโ this mode doesn't limit the size of the code segment or the data segment ๐ฅ Heads up:-mcmodel=extremeis incompatible with-fpltand/or-mexplicit-relocs=none๐จ
-mexplicit-relocs=style,-mexplicit-relocs,-mno-explicit-relocsโ this decides when to use assembler relocation operators for symbolic addresses ๐ง The alternative is assembler macros, which may limit instruction scheduling but allow linker relaxation ๐ซถ With-mexplicit-relocs=none, the assembler macros are always used. With-mexplicit-relocs=always, the assembler relocation operators are always used. With-mexplicit-relocs=auto, the compiler uses the relocation operators where linker relaxation is impossible (to improve code quality) and macros everywhere else โจ
The default is figured out from the assembler capability detected when GCC was built, plus the setting of -mrelax. It's -mexplicit-relocs=none if the assembler doesn't support relocation operators at all, -mexplicit-relocs=always if the assembler supports them but -mrelax isn't enabled, and -mexplicit-relocs=auto if the assembler supports them and -mrelax is enabled ๐
For backward compatibility, -mexplicit-relocs is equivalent to -mexplicit-relocs=always, and -mno-explicit-relocs is equivalent to -mexplicit-relocs=none ๐ฆ
-mdirect-extern-access,-mno-direct-extern-accessโ controls use of the GOT to access external symbols ๐ The default is-mno-direct-extern-access: the GOT is used for external symbols with default visibility, but not for other external symbols ๐ซถ
With -mdirect-extern-access, the GOT isn't used and all external symbols are PC-relatively addressed ๐ง This is only suitable for environments where no dynamic link is performed, like firmwares, OS kernels, and executables linked with -static or -static-pie ๐ -mdirect-extern-access is not compatible with -fPIC or -fpic ๐จ
-mrelax,-mno-relaxโ takes (or doesn't take) advantage of linker relaxations ๐ธ If-mpass-mrelax-to-asis enabled, this option is also passed to the assembler ๐ The default is figured out at GCC build time by detecting assembler support:-mrelaxif the assembler supports both the-mrelaxoption and conditional branch relaxation,-mno-relaxotherwise ๐ The conditional branch relaxation part is required, because the".align"directives and conditional branch instructions in the assembly code GCC outputs may be rejected by the assembler due to a relocation overflow ๐ญ-mpass-mrelax-to-as,-mno-pass-mrelax-to-asโ passes (or doesn't pass) the-mrelaxor-mno-relaxoption to the assembler ๐งธ The default is figured out at GCC build time by detecting assembler support:-mpass-mrelax-to-asif the assembler supports the-mrelaxoption,-mno-pass-mrelax-to-asotherwise ๐ฆ This option is mostly useful for debugging, or for interoperating with assemblers that are different from the one used at build time ๐ง-mrecipโ enables use of the reciprocal estimate and reciprocal square root estimate instructions, with extra Newton-Raphson steps to boost precision, instead of doing a divide (or a square root and then a divide) for floating-point arguments ๐งฎ These instructions only get generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math๐ซถ This option is off by default โ Before you use it, you must make sure the target CPU supports the"frecipe"and"frsqrte"instructions ๐ Note that while the throughput of the sequence is higher than the throughput of the non-reciprocal instruction, the precision of the sequence can be decreased by up to 2 ulp (i.e. the inverse of 1.0 equals0.99999994) ๐ฌ-mrecip=optโ controls which reciprocal estimate instructions may be used ๐ฏoptis a comma-separated list of options, and each one may be preceded by a!to invert it ๐allโ enables all estimate instructions ๐defaultโ enables the default instructions, equivalent to-mrecip๐noneโ disables all estimate instructions, equivalent to-mno-recip๐ซdivโ enables the approximation for scalar division โvec-divโ enables the approximation for vectorized division ๐งฎsqrtโ enables the approximation for scalar square root ๐ฑvec-sqrtโ enables the approximation for vectorized square root ๐ฟrsqrtโ enables the approximation for scalar reciprocal square root ๐ฆvec-rsqrtโ enables the approximation for vectorized reciprocal square root ๐
So, for example, -mrecip=all,!sqrt enables all of the reciprocal approximations except for scalar square root ๐
โจ
-mfrecipe,-mno-frecipeโ okay so these let you turn the"frecipe.{s/d}"and"frsqrte.{s/d}"instructions on or off ๐ . When you compile with-march=la664it's on by default, and otherwise the default is-mno-frecipe๐ธ-mdiv32,-mno-div32โ this one lets you use (or skip) thediv.w[u]andmod.w[u]instructions when the input is not sign-extended โจ. With-march=la664it's enabled by default. Everywhere else it defaults to-mno-div32๐ง-mlam-bh,-mno-lam-bhโ toggles theam{swap/add}[_db].{b/h}instructions ๐ฅ. Same deal: on with-march=la664, and-mno-lam-bhotherwise ๐-mlamcas,-mno-lamcasโ toggles theamcas[_db].{b/h/w/d}instructions ๐ฆ. It's enabled by default with-march=la664, and the default is-mno-lamcasotherwise ๐-mld-seq-sa,-mno-ld-seq-saโ this is about whether a same-address load-load barrier (dbar 0x700) is needed at all ๐. With-march=la664it's enabled by default. Otherwise the default is-mno-ld-seq-sa, which means the load-load barrier is needed ๐ญ-mscq,-mno-scqโ lets you use (or not use) the 16-byte conditional store instructionsc.q๐. The default is-mscqif the machine type you pick with-march=supports this instruction, and-mno-scqif it doesn't ๐-mtls-dialect=optโ this controls which TLS dialect can be used for general dynamic and local dynamic TLS models ๐. Theoptargument can be one of these:tradโ traditional TLS, and this is the default ๐descโ uses TLS descriptors โจ
-mannotate-tablejump,-mno-annotate-tablejumpโ when a jump table gets used to optimize aswitchstatement, this makes a.discard.tablejump_annotateannotation section ๐ง. It ties thejirlinstruction to the jump table, which is super handy because some external tools, like objtool from the Linux kernel building system, need that annotation to analyze control flow ๐ซถ. The default is-mno-annotate-tablejump๐
๐ฆ LynxOS Options ๐ฆ
These options are for LynxOS targets, so if that's your world, this part's for you ๐ธ
-msharedโ uses shared libraries ๐. The default is linking with static libraries instead ๐ง-mthreadsโ adds multi-threading support ๐งต-mlegacy-threadsโ adds legacy multi-threading support ๐ฐ๏ธ. Heads up, this one is incompatible with-mthreads, so you can't have both ๐
๐ M32C Options ๐
-mcpu=nameโ picks the CPU your code gets generated for โจ.namecan ber8cfor the R8C/Tiny series,m16cfor the M16C (up to /60) series,m32cmfor the M16C/80 series, orm32cfor the M32C/80 series ๐ฅ-msimโ tells GCC your program will run on the simulator ๐งช. This links in an alternate runtime library that supports stuff like file I/O ๐
โ ๏ธ Do not use this option for programs that will run on real hardware! You have to supply your own runtime library for whatever I/O functions you need, no shortcuts bestie ๐ญ
-memregs=numberโ sets how many memory-based pseudo-registers GCC uses during code generation ๐ง . These get used like real registers, so it's a tradeoff between fitting your code into the available registers and the performance hit from using memory instead ๐ฆ. Every module in a program has to be compiled with the same value for this option ๐. Because of that, you must not use this option with GCC's default runtime libraries ๐
๐ M32R/D Options ๐
These -m options are defined for Renesas M32R/D architectures ๐ธ.
-m32r2โ generates code for the M32R/2 ๐-m32rxโ generates code for the M32R/X โจ-m32rโ generates code for the M32R ๐. This is the default ๐-mmodel=smallโ assumes all objects live in the lower 16MB of memory, so their addresses can be loaded with theld24instruction ๐ง. It also assumes all subroutines are reachable with theblinstruction ๐ฆ. This is the default ๐
The addressability of a particular object can be set with the "model" attribute ๐.
-mmodel=mediumโ assumes objects may be anywhere in the 32-bit address space, so the compiler generatesseth/add3instructions to load their addresses ๐. It also assumes all subroutines are reachable with theblinstruction ๐ฅ-mmodel=largeโ assumes objects may be anywhere in the 32-bit address space, with the compiler generatingseth/add3instructions to load their addresses ๐. This time it assumes subroutines may not be reachable with theblinstruction, so the compiler generates the much slowerseth/add3/jlinstruction sequence ๐ข-msdata=noneโ disables use of the small data area ๐ซ. Variables get put into.data,.bss, or.rodata, unless the"section"attribute has been specified ๐. This is the default ๐
The small data area is made up of the .sdata and .sbss sections ๐งธ. You can explicitly put objects into the small data area with the "section" attribute using one of these sections ๐ซถ
-msdata=sdataโ puts small global and static data in the small data area, but doesn't generate any special code to reference it ๐ท-msdata=useโ puts small global and static data in the small data area and generates special instructions to reference it โญ-G numโ puts global and static objects that are less than or equal tonumbytes into the small data or BSS sections, instead of the normal data or BSS sections ๐ง. The default value ofnumis8๐ข. The-msdataoption has to be set to eithersdataorusefor this to do anything ๐
All modules should be compiled with the same -G num value ๐ซ. Compiling with different values of num may or may not work ๐คทโโ๏ธ. If it doesn't work, the linker gives you an error message, so incorrect code is never generated ๐ก๏ธ
-mdebugโ makes the M32R-specific code in the compiler display some statistics that might help you debug your programs ๐-malign-loops,-mno-align-loopsโ aligns all loops to a 32-byte boundary ๐. This option is disabled by default ๐ค-missue-rate=numberโ issuesnumberinstructions per cycle ๐โโ๏ธ.numbercan only be1or2โก-mbranch-cost=numberโnumbercan only be1or2๐ธ. If it's1, branches are preferred over conditional code. If it's2, the opposite applies ๐-mflush-trap=numberโ specifies the trap number used to flush the cache ๐งน. The default is12, and valid numbers are between0and15inclusive ๐ฏ-mno-flush-trapโ specifies that the cache cannot be flushed by using a trap ๐ซ๐ชค-mflush-func=nameโ specifies the name of the operating system function to call to flush the cache ๐ ๏ธ. The default is_flush_cache, but a function call is only used if a trap isn't available ๐-mno-flush-funcโ indicates that there's no OS function for flushing the cache ๐ โโ๏ธ
๐ท M680x0 Options ๐ท
These are the -m options defined for M680x0 and ColdFire processors ๐ธ. The default settings depend on which architecture was selected when the compiler was configured, so the defaults for the most common choices are listed below ๐.
-march=archโ generates code for a specific M680x0 or ColdFire instruction set architecture ๐๏ธ. For M680x0 architectures,archcan be68000,68010,68020,68030,68040,68060, orcpu32๐ . ColdFire architectures are picked based on Freescale's ISA classification, and the valid values areisaa,isaaplus,isab, andisac๐ฆ
GCC defines the macro "__mcfarch__" whenever it's generating code for a ColdFire target ๐. The arch in that macro is one of the -march arguments listed above ๐งฉ
When you use -march and -mtune together, they select code that runs on a family of similar processors, but that's optimized for one particular microarchitecture ๐
-mcpu=cpuโ generates code for a specific M680x0 or ColdFire processor ๐ฅ๏ธ. The M680x0 cpus are68000,68010,68020,68030,68040,68060,68302,68332, andcpu32โจ. The ColdFire cpus are in the table below, which also sorts the CPUs into families ๐:
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
๐ โโ๏ธ-mcpu=cpuoverrides-march=archifarchis compatible withcpu. Other combinations of-mcpuand-marchget rejected, so be careful, bestie ๐
GCC defines the macro "__mcf_cpu_cpu" when a ColdFire target cpu is selected ๐งฌ. It also defines "__mcf_family_family", where the value of family comes from the table above ๐
-mtune=tuneโ tunes the code for a particular microarchitecture, but still within the constraints set by-marchand-mcpu๐๏ธ. The M680x0 microarchitectures are68000,68010,68020,68030,68040,68060, andcpu32๐ง . The ColdFire microarchitectures arecfv1,cfv2,cfv3,cfv4, andcfv4e๐
You can also use -mtune=68020-40 for code that needs to run pretty well on 68020, 68030, and 68040 targets ๐ซถ. -mtune=68020-60 is similar, but it includes 68060 targets too ๐. These two options select the same tuning decisions as -m68020-40 and -m68020-60 respectively ๐
GCC defines the macros "__mcarch" and "__mcarch__" when tuning for 680x0 architecture arch ๐ท๏ธ. It also defines "mcarch" unless either -ansi or a non-GNU -std option is used ๐. If GCC is tuning for a range of architectures, as selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in that range ๐
GCC also defines the macro "__muarch__" when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments listed above ๐ฆ
-m68000,-mc68000โ generates output for a 68000 ๐ฃ. This is the default when the compiler is configured for 68000-based systems ๐ฒ๏ธ, and it's equivalent to-march=68000โจ
Use this option for microcontrollers with a 68000 or EC000 core, including the 68008, 68302, 68306, 68307, 68322, 68328, and 68356 ๐ง๐
-m68010โ okay bestie, this one generates output for a 68010 ๐ง It's the default when the compiler is set up for 68010 systems, and it's the same as-march=68010โจ-m68020,-mc68020โ a 68020 glow-up ๐ Default for 68020 systems, and equivalent to-march=68020๐ธ-m68030โ targets the 68030 ๐ฆ Default for 68030 systems, same as-march=68030-m68040โ targets the 68040 ๐ฅ Default for 68040 systems, and equivalent to-march=68040. This one also turns off the 68881/68882 instructions that a 68040 would have to fake in software. Use it if your 68040 doesn't have the code to emulate them ๐-m68060โ targets the 68060 ๐ Default for 68060 systems, equivalent to-march=68060. It also blocks the 68020 and 68881/68882 instructions that the 68060 would otherwise have to emulate in software. Use it if your 68060 is missing that emulation code ๐ซถ-m68302โ generates code for a 68302 ๐-m68332โ generates code for a 68332 ๐-m68851โ the 68851 was an external MMU for the 68020 ๐ GCC accepts this option, but it doesn't actually use it, so it's basically a nice gesture ๐-mcpu32โ generates output for a CPU32 ๐ Default for CPU32 systems, equivalent to-march=cpu32. Use it for microcontrollers with a CPU32 or CPU32+ core, like the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360 โจ-mfidoaโ generates code for a Fido A ๐ง-m5200โ generates output for a 520X ColdFire CPU ๐ธ Default for 520X systems. It's equivalent to-mcpu=5206, but it's deprecated now, so switch to that option instead ๐ฅ Use it for microcontrollers with a 5200 core, like the MCF5202, MCF5203, MCF5204 and MCF5206 ๐ฆ-m5206eโ generates output for a 5206e ColdFire CPU ๐ It's deprecated in favor of the equivalent-mcpu=5206e-m528xโ generates output for a member of the ColdFire 528X family ๐ฅ Deprecated in favor of the equivalent-mcpu=528x-m5307โ generates output for a ColdFire 5307 CPU โญ Deprecated in favor of the equivalent-mcpu=5307-m5407โ generates output for a ColdFire 5407 CPU ๐ Deprecated in favor of the equivalent-mcpu=5407-mcfv4eโ generates output for a ColdFire V4e family CPU, like the 547x/548x ๐ This one includes hardware floating-point instructions. It's equivalent to-mcpu=547x, and it's deprecated in favor of that option ๐ซถ-m68020-40โ generates output for a 68040 without using any of the new instructions ๐ The result runs pretty efficiently on a 68020/68881, a 68030 or a 68040. The generated code does use the 68881 instructions that get emulated on the 68040 โจ It's equivalent to-march=68020 -mtune=68020-40.-m68020-60โ generates output for a 68060 without using any of the new instructions ๐ฆ Same deal: it runs pretty efficiently on a 68020/68881, a 68030 or a 68040. The generated code does use the 68881 instructions that get emulated on the 68060 ๐ It's equivalent to-march=68020 -mtune=68020-60.-mhard-float,-m68881โ generates floating-point instructions ๐ฅ This is the default for 68020 and up, and for ColdFire devices with an FPU. It defines the macro"__HAVE_68881__"on M680x0 targets and"__mcffpu__"on ColdFire targets ๐-msoft-floatโ doesn't generate floating-point instructions, and uses library calls instead ๐ฅบ This is the default for 68000, 68010, and 68832 targets. It's also the default for ColdFire devices that don't have an FPU ๐-mdiv,-mno-divโ generates (or doesn't generate) ColdFire hardware divide and remainder instructions ๐ธ If-marchis used without-mcpu, the default is"on"for ColdFire architectures and"off"for M680x0 architectures. Otherwise, the default comes from the target CPU (either the default CPU, or the one set with-mcpu). For example, the default is"off"for-mcpu=5206and"on"for-mcpu=5206e๐ง
GCC defines the macro "__mcfhwdiv__" when this option is enabled โจ
-mshort,-mno-short,-mnoshortโ treats type"int"as 16 bits wide, just like"short int"๐ Parameters passed on the stack also get aligned to a 16-bit boundary, even on targets whose API says they should be promoted to 32-bit ๐ This option is disabled by default.-mbitfield,-mno-bitfield,-mnobitfieldโ controls use of the bit-field instructions ๐-m68000,-mcpu32and-m5200imply-mnobitfield, and-m68020implies-mbitfield๐ซถ-mrtd,-mno-rtd,-mnortdโ controls use of a different function-calling convention, and this one is kinda spicy ๐ถ๏ธ Functions that take a fixed number of arguments return with the"rtd"instruction, which pops their arguments while returning. That saves one instruction in the caller, since the caller doesn't need to pop the arguments anymore โจ
Heads up, bestie: this calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler ๐
Also: you must provide function prototypes for all functions that take variable numbers of arguments (including "printf"). Otherwise, incorrect code gets generated for calls to those functions ๐ญ
Seriously: incorrect code results if you call a function with too many arguments. Normally, extra arguments are harmlessly ignored, but not here ๐
The "rtd" instruction is supported by the 68010, 68020, 68030, 68040, 68060 and CPU32 processors, but not by the 68000 or 5200 ๐
The default is -mno-rtd ๐
-malign-int,-mno-align-intโ controls whether GCC aligns"int","long","long long","float","double", and"long double"variables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐ฆ Aligning on 32-bit boundaries gives code that runs somewhat faster on processors with 32-bit busses, but it costs more memory ๐
Warning: if you use the -malign-int switch, GCC aligns structures containing the above types differently than most published application binary interface specifications for the m68k ๐จ
Use the pc-relative addressing mode of the 68000 directly, instead of using a global offset table ๐ง At present, this option implies -fpic, allowing at most a 16-bit offset for pc-relative addressing. -fPIC is not presently supported with -mpcrel, though this could be supported for 68020 and higher processors ๐ฅน
-mno-strict-align,-mstrict-alignโ doesn't (or does) assume that unaligned memory references are handled by the system ๐ธ-msep-data,-mno-sep-dataโ with-msep-data, GCC generates code that lets the data segment live in a different area of memory from the text segment ๐ This allows execute-in-place in an environment without virtual memory management. This option implies-fPICโจ
This option is disabled by default. GCC generates code that assumes the data segment follows the text segment ๐
-mid-shared-library,-mno-id-shared-libraryโ if enabled, GCC generates code that supports shared libraries via the library ID method ๐ This allows execute-in-place and shared libraries in an environment without virtual memory management. This option implies-fPIC๐ซถ
This option is disabled by default โจ
-mshared-library-id=nโ specifies the identification number of the ID-based shared library being compiled ๐ Specifying0generates more compact code. Specifying other values forces the allocation of that number to the current library, but that's no more space- or time-efficient than leaving this option out ๐ฆ-mxgot,-mno-xgotโ when generating position-independent code for ColdFire, this generates code that works if the GOT has more than 8192 entries ๐ฅ This code is larger and slower than code generated without this option. On M680x0 processors, this option isn't needed, since-fPICis enough ๐
GCC normally uses a single instruction to load values from the GOT. It's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker report an error like this:
relocation truncated to fit: R_68K_GOT16O foobar
If that happens, recompile your code with -mxgot, and it should work with very large GOTs ๐ฅบ Just know that code generated with -mxgot is less efficient, since it takes 4 instructions to fetch the value of a global symbol ๐ญ
Some linkers, including newer versions of the GNU linker, can create multiple GOTs and sort GOT entries. If you have one of those linkers, you should only need -mxgot when compiling a single object file that accesses more than 8192 GOT entries. Very few do ๐
These options have no effect unless GCC is generating position-independent code ๐ธ
-mxtlsโ supports a TLS segment larger than 64K โจ The considerations are similar to the ones for-mxgotabove. The default 16-bit offset addressing for TLS is more efficient, but it may be inadequate for some programs ๐ง-mlong-jump-table-offsetsโ uses 32-bit offsets in"switch"tables ๐ The default is 16-bit offsets ๐
MCore Options ๐
These are the -m options defined for the Motorola M*Core processors ๐ฆ
-mhardlit,-mno-hardlitโ inlines constants into the code stream if it can be done in two instructions or less ๐ฅ-mdiv,-mno-divโ uses the divide instruction ๐ (Enabled by default).-mrelax-immediates,-mno-relax-immediatesโ allows arbitrary-sized immediates in bit operations ๐-mwide-bitfields,-mno-wide-bitfieldsโ always treats bit-fields as"int"-sized ๐-m4byte-functions,-mno-4byte-functionsโ forces all functions to be aligned to a 4-byte boundary ๐ซถ-mcallgraph-data,-mno-callgraph-dataโ emits callgraph information โญ-mslow-bytes,-mno-slow-bytesโ okay so these two decide how byte-sized reads happen ๐-mslow-bytestells GCC to prefer word access when reading byte quantities โจ-mlittle-endian,-mbig-endianโ pick your endian vibe ๐ these make code for a little-endian or big-endian target, in that order. Big-endian is the default, and little-endian only works with-m340๐ธ-m210โ generates code for the 210 processor ๐-m340โ generates code for the 340 processor ๐-mno-lsimโ the bestie move if your runtime support is already handled ๐ซถ it tells GCC to skip the simulator library (libsim.a) on the linker command line-mstack-increment=sizeโ sets the biggest amount a single stack increment can be ๐ big numbers can speed things up for programs that need lots of stack space, but they can also trigger a segmentation fault if the stack gets extended too much ๐ญ the default is0x1000๐ง
๐ฆ MicroBlaze Options ๐ฆ
-msoft-floatโ software emulation for floating point, and this is the default ๐-mhard-floatโ uses hardware floating-point instructions ๐ฅ-mmemcpyโ don't optimize block moves, just usememcpy๐-mcpu=cpu-typeโ uses the features of, and schedules code for, the CPU you name ๐ values look likevX.YY.Z, whereXis the major version,YYis the minor version, andZis the compatibility code ๐ฆ example values arev3.00.a,v4.00.b,v5.00.a,v5.00.b, andv6.00.aโจ-mxl-soft-mul,-mno-xl-soft-mulโ software multiply emulation, enabled by default ๐-mxl-soft-div,-mno-xl-soft-divโ software emulation for divides, also enabled by default ๐ธ-mxl-barrel-shiftโ uses the hardware barrel shifter ๐-mxl-pattern-compareโ uses pattern compare instructions ๐-msmall-dividesโ table lookup optimization for small signed integer divisions ๐ง-mxl-gp-optโ uses GP-relative".sdata"/".sbss"sections ๐-mxl-multiply-highโ uses multiply high instructions for the high part of a 32x32 multiply โญ-mxl-float-convertโ uses hardware floating-point conversion instructions ๐ฅ-mxl-float-sqrtโ uses the hardware floating-point square root instruction ๐-mbig-endianโ generates code for a big-endian target ๐-mlittle-endianโ generates code for a little-endian target ๐ธ-mxl-reorderโ uses reorder instructions (swap and byte reversed load/store) ๐ฆ-mxl-mode-app-modelโ picks the application modelapp-model. Here are your valid models ๐executableโ the normal executable, and the default ๐ซถ it uses the startup codecrt0.oxmdstubโ made for the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent calledxmdstub๐ it uses the startup filecrt1.oand sets the start address of the program to0x800bootstrapโ for applications loaded by a bootloader ๐ฅพ this model uses the startup filecrt2.o, which doesn't have a processor reset vector handler. It's perfect for handing control back to the bootloader on a processor reset instead of the application ๐novectorsโ for applications that don't need any of the MicroBlaze vectors ๐ this can be handy inside a monitoring application. This model usescrt3.oas its startup file ๐ง
-mxl-prefetchโ turns on insertion of prefetch (wic) instructions at call sites ๐-mpic-data-is-text-relativeโ assumes the displacement between the text and data segments is fixed at static link time ๐ฆ this lets data get referenced by offset from the start of the text address instead of the GOT, since PC-relative addressing isn't supported ๐
๐ MIPS Options ๐
-EB,-mebโ generates big-endian code ๐-EL,-melโ generates little-endian code ๐ this is the default formips*el-*-*configurations โจ-march=archโ generates code that runs onarch, which can be the name of a generic MIPS ISA or the name of a particular processor ๐ the ISA names are:mips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5, andmips64r6๐ the processor names are:4kc,4km,4kp,4ksc,4kec,4kem,4kep,4ksd,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,24kec,24kef2_1,24kef1_1,34kc,34kf2_1,34kf1_1,34kn,74kc,74kf2_1,74kf1_1,74kf3_2,1004kc,1004kf2_1,1004kf1_1,i6400,i6500,interaptiv,loongson2e,loongson2f,loongson3a,gs464,gs464e,gs264e,m4k,m14k,m14kc,m14ke,m14kec,m5100,m5101,octeon,octeon+,octeon2,octeon3,orion,p5600,p6600,r2000,r3000,r3900,r4000,r4400,r4600,r4650,r4700,r5900,r6000,r8000,rm7000,rm9000,r10000,r12000,r14000,r16000,sb1,sr71000,vr4100,vr4111,vr4120,vr4130,vr4300,vr5000,vr5400,vr5500,xlrandxlp.allegrex, The special valuefrom-abiselects the most compatible architecture for the selected ABI ๐ง that meansmips1for 32-bit ABIs andmips3for 64-bit ABIs ๐
The native Linux/GNU toolchain also supports the value native, which picks the best architecture option for the host processor ๐ป -march=native has no effect if GCC doesn't recognize the processor ๐
In processor names, a final 000 can be abbreviated as k (for example, -march=r2k) โจ prefixes are optional, and vr may be written r ๐
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core ๐ names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core ๐ธ and names of the form nf3_2 refer to processors with FPUs clocked at a 3:2 ratio with respect to the core ๐ฆ for compatibility reasons, nf is accepted as a synonym for nf2_1, while nx and bfx are accepted as synonyms for nf1_1 ๐ซถ
GCC defines two macros based on the value of this option ๐ the first is "_MIPS_ARCH", which gives the name of the target architecture as a string ๐ the second has the form "_MIPS_ARCH_foo", where foo is the capitalized value of "_MIPS_ARCH" ๐ for example, -march=r2000 sets "_MIPS_ARCH" to "r2000" and defines the macro "_MIPS_ARCH_R2000" ๐
Heads up bestie: the"_MIPS_ARCH"macro uses the processor names given above. In other words, it has the full prefix and doesn't abbreviate000ask๐ withfrom-abi, the macro names the resolved architecture (either"mips1"or"mips3"). It names the default architecture when no-marchoption is given ๐
-mtune=archโ optimizes forarch๐ฏ among other things, this option controls how instructions get scheduled and the perceived cost of arithmetic operations ๐ง the list ofarchvalues is the same as for-march๐
When this option isn't used, GCC optimizes for the processor specified by -march ๐ by using -march and -mtune together, you can generate code that runs on a whole family of processors, but optimize it for one particular member of that family ๐ฆ
-mtune defines the macros "_MIPS_TUNE" and "_MIPS_TUNE_foo", which work the same way as the -march ones described above โจ
-mips1โ equivalent to-march=mips1๐ธ-mips2โ equivalent to-march=mips2๐ธ-mips3โ equivalent to-march=mips3๐ธ-mips4โ equivalent to-march=mips4๐ธ-mips32โ equivalent to-march=mips32๐ธ-mips32r3โ equivalent to-march=mips32r3๐ธ-mips32r5โ equivalent to-march=mips32r5๐ธ-mips32r6โ equivalent to-march=mips32r6๐ธ-mips64โ equivalent to-march=mips64๐ธ-mips64r2โ equivalent to-march=mips64r2๐ธ-mips64r3โ equivalent to-march=mips64r3๐ธ-mips64r5โ equivalent to-march=mips64r5๐ธ-mips64r6โ equivalent to-march=mips64r6๐ธ-mips16,-mno-mips16โ generates (or doesn't generate) MIPS16 code ๐งฉ if GCC is targeting a MIPS32 or MIPS64 architecture, it uses the MIPS16e ASE ๐
MIPS16 code generation can also be controlled on a per-function basis with the "mips16" and "nomips16" attributes ๐ฆ
-mmips16e2,-mno-mips16e2โ uses (or doesn't use) the MIPS16e2 ASE ๐ง this option changes how-mips16behaves, so it targets the MIPS16e2 ASE instead โจ-mflip-mips16,-mflip-mips16โ generates MIPS16 code on alternating functions ๐ this one is only there for regression testing of mixed MIPS16/non-MIPS16 code generation, so it's not meant for everyday compiling of user code ๐ซ-minterlink-compressed,-mno-interlink-compressedโ requires (or doesn't require) that code using the standard (uncompressed) MIPS ISA be link-compatible with MIPS16 and microMIPS code, and vice versa ๐
For example, code using the standard ISA encoding can't jump directly to MIPS16 or microMIPS code. It has to use a call or an indirect jump instead ๐ซ so -minterlink-compressed disables direct jumps unless GCC knows the jump's target isn't compressed ๐
-minterlink-mips16,-mno-interlink-mips16โ aliases of-minterlink-compressedand-mno-interlink-compressed๐ฐ๏ธ these predate the microMIPS ASE and are kept around for backwards compatibility ๐ซถ-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generates code for the given ABI ๐ฆ
The EABI comes in a 32-bit and a 64-bit variant โจ GCC normally generates 64-bit code when you pick a 64-bit architecture, but you can use -mgp32 to get 32-bit code instead ๐
For info about the O64 ABI, check out https://gcc.gnu.org/projects/mipso64-abi.html ๐
GCC supports a variant of the o32 ABI where the floating-point registers are 64 bits wide instead of 32 ๐ you can select this combo with -mabi=32 -mfp64 ๐ this ABI relies on the mthc1 and mfhc1 instructions, so it's only supported for MIPS32R2, MIPS32R3, and MIPS32R5 processors ๐ฅ
The register assignments for arguments and return values stay the same, but each scalar value is passed in a single 64-bit register instead of a pair of 32-bit registers ๐ง for example, scalar floating-point values are returned in $f0 only, not a $f0/$f1 pair ๐ the set of call-saved registers also stays the same, in that the even-numbered double-precision registers are saved ๐ซถ
So okay, there are two extra flavours of the o32 ABI that help you hop from 32-bit to 64-bit registers without losing your mind ๐ฆ. The first is FPXX (-mfpxx), and it's giving full flexibility: all code has to run correctly with either 32-bit or 64-bit registers ๐
. FPXX code can be linked with FP32 or FP64, but never both at once ๐ซถ. The second is FP64A (-mfp64 -mno-odd-spreg). It's basically FP64 but it refuses to touch odd-numbered single-precision registers ๐ธ. Pair it with the "FRE" mode on MIPS32R5 FPUs and FP32 and FP64A code can link together and run in the same process without switching FPU modes โจ. Iconic, honestly.
-mabicalls,-mno-abicallsโ Okay, so these tell GCC to generate (or not generate) code that works with SVR4-style dynamic objects ๐.-mabicallsis the default on SVR4-based systems ๐.-mshared,-mno-sharedโ This one decides whether your code is fully position-independent, which means it can get linked into shared libraries ๐. It only matters when you're using-mabicalls๐.
All -mabicalls code has traditionally been position-independent, even if you use stuff like -fPIC and -fpic ๐ง. BUT, and this is the tea โ, the GNU toolchain lets executables use absolute accesses for locally-binding symbols as an extension ๐. It can also use shorter GP initialization sequences and make direct calls to locally-defined functions ๐ฅ. That's the mode -mno-shared turns on โญ.
-mno-shared needs binutils 2.16 or higher, and the objects it makes can only be linked by the GNU linker ๐
. The ABI of the final executable doesn't change, only the ABI of relocatable objects does ๐ฆ. Using -mno-shared usually leaves executables both smaller and quicker, which is so slay ๐โโ๏ธโจ. -mshared is the default ๐.
-mplt,-mno-pltโ This asks GCC to assume (or not assume) that the static and dynamic linkers support PLTs and copy relocations ๐ธ. It only affects-mno-shared -mabicalls๐ซถ. For the n64 ABI, it does absolutely nothing unless you also use-msym32๐.
You can make -mplt the default by configuring GCC with --with-mips-plt ๐. Otherwise the default is -mno-plt ๐.
-mxgot,-mno-xgotโ These lift (or don't lift) the usual limits on how big the global offset table can be ๐.
GCC normally loads GOT values with a single instruction, which is efficient, but only if the GOT is smaller than about 64k ๐ญ. Anything bigger and the linker gets mad and reports something like this:
relocation truncated to fit: R_MIPS_GOT16 foobar
If you see that, recompile with -mxgot ๐. It works with really huge GOTs, but the code is a bit less efficient, because it takes three instructions to fetch the value of a global symbol ๐. Some linkers can make multiple GOTs, and if yours is one of them, you should only need -mxgot when one object file touches more than 64k's worth of GOT entries ๐ง. Very few linkers do that, lowkey ๐ซ .
These options do nothing unless GCC is generating position-independent code ๐.
-mgp32โ Assume that general-purpose registers are 32 bits wide ๐ธ.-mgp64โ Assume that general-purpose registers are 64 bits wide ๐.-mfp32โ Assume that floating-point registers are 32 bits wide ๐ฆ.-mfp64โ Assume that floating-point registers are 64 bits wide โจ.-mfpxxโ Don't assume any particular width for floating-point registers at all ๐ง.-mhard-floatโ Use the floating-point coprocessor instructions ๐ฅ.-msoft-floatโ Don't use the floating-point coprocessor instructions. Instead, floating-point math gets done with library calls ๐ .-mno-floatโ This is basically-msoft-float, but it also swears that the program you're compiling does zero floating-point operations ๐. Right now it's only supported by some bare-metal MIPS configurations, where it might pick a special set of libraries with no floating-point support at all (that includes stuff like the floating-pointprintfformats) ๐. If code compiled with-mno-floataccidentally has floating-point operations in it, it's very likely to fail at link time or run time ๐ญ.-msingle-floatโ Assume the floating-point coprocessor only does single-precision operations ๐.-mdouble-floatโ Assume the floating-point coprocessor supports double-precision operations. This is the default, obvi ๐.-modd-spreg,-mno-odd-spregโ These enable (or disable) the use of odd-numbered single-precision floating-point registers for the o32 ABI ๐ฆ. Enabling them is the default for processors that are known to support those registers โจ. When you're using the o32 FPXX ABI,-mno-odd-spregis set by default ๐ซถ.-mabs=2008,-mabs=legacyโ These control how the special not-a-number (NaN) IEEE 754 floating-point data gets handled by theabs.fmtandneg.fmtmachine instructions ๐.
By default, or when you use -mabs=legacy, you get the legacy treatment ๐. In this case, those instructions are treated as arithmetic, so they get avoided wherever correct operation is needed and the input might be a NaN ๐ญ. Instead, GCC uses a longer sequence of instructions that manipulates the sign bit of the floating-point datum by hand, unless -ffinite-math-only is also specified ๐ง.
-mabs=2008 picks the IEEE 754-2008 treatment ๐. Here, those instructions count as non-arithmetic, so they work correctly in every case, including when the input operand is a NaN ๐ธ. That's why they're always used for the respective operations ๐.
-mnan=2008,-mnan=legacyโ These control how the special not-a-number (NaN) IEEE 754 floating-point data gets encoded ๐ .
-mnan=legacy selects the legacy encoding ๐ฆ. In this one, quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, while signaling NaNs (sNaNs) are marked by that first bit being 1 ๐.
-mnan=2008 selects the IEEE 754-2008 encoding โจ. Here, qNaNs have that first bit set to 1, and sNaNs have it set to 0 ๐.
The default is -mnan=legacy, unless GCC was configured with --with-nan=2008 ๐.
-mllsc,-mno-llscโ These decide whether to use (or not use) thell,sc, andsyncinstructions to implement the atomic memory built-in functions ๐ฅ. If you specify neither, GCC uses those instructions as long as the target architecture supports them ๐ซถ.
-mllsc is handy if the runtime environment can emulate the instructions ๐ง. -mno-llsc can be useful when you're compiling for nonstandard ISAs ๐. You can make either one the default by configuring GCC with --with-llsc and --without-llsc respectively ๐. --with-llsc is the default for some configurations, so check the installation documentation for details ๐.
-mdsp,-mno-dspโ These use (or don't use) revision 1 of the MIPS DSP ASE ๐ธ. This option defines the preprocessor macro"__mips_dsp", and it also defines"__mips_dsp_rev"to 1 โจ.-mdspr2,-mno-dspr2โ These use (or don't use) revision 2 of the MIPS DSP ASE ๐ฆ. This option defines the preprocessor macros"__mips_dsp"and"__mips_dspr2", and it also defines"__mips_dsp_rev"to 2 ๐.-msmartmips,-mno-smartmipsโ These use (or don't use) the MIPS SmartMIPS ASE ๐ .-mpaired-single,-mno-paired-singleโ These use (or don't use) paired-single floating-point instructions ๐. This option needs hardware floating-point support to be enabled first ๐ซถ.-mdmx,-mno-mdmxโ These use (or don't use) MIPS Digital Media Extension instructions ๐ฅ. This only works when you're generating 64-bit code, and it also needs hardware floating-point support to be enabled ๐ญ.-mips3d,-mno-mips3dโ These use (or don't use) the MIPS-3D ASE ๐. The option-mips3dimplies-mpaired-single, so they come as a package deal ๐ง.-mmicromips,-mno-micromipsโ These generate (or don't generate) microMIPS code ๐. You can also control microMIPS code generation on a per-function basis with themicromipsandnomicromipsattributes ๐.-mmt,-mno-mtโ These use (or don't use) MT Multithreading instructions ๐ธ.-mmcu,-mno-mcuโ These use (or don't use) the MIPS MCU ASE instructions ๐ฆ.-meva,-mno-evaโ These use (or don't use) the MIPS Enhanced Virtual Addressing instructions โจ.-mvirt,-mno-virtโ These use (or don't use) the MIPS Virtualization (VZ) instructions ๐.-mxpa,-mno-xpaโ These use (or don't use) the MIPS eXtended Physical Address (XPA) instructions ๐.-mcrc,-mno-crcโ These use (or don't use) the MIPS Cyclic Redundancy Check (CRC) instructions ๐ซถ.-mginv,-mno-ginvโ These use (or don't use) the MIPS Global INValidate (GINV) instructions ๐.-mmsa,-mno-msaโ These use (or don't use) the MIPS MSA extension instructions ๐ฅ.-mloongson-mmi,-mno-loongson-mmiโ These use (or don't use) the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐ .-mloongson-ext,-mno-loongson-extโ These use (or don't use) the MIPS Loongson EXTensions (EXT) instructions ๐ง.-mloongson-ext2,-mno-loongson-ext2โ These use (or don't use) the MIPS Loongson EXTensions r2 (EXT2) instructions ๐.-mlong64โ Forcelongtypes to be 64 bits wide ๐ธ. Check out-mlong32for an explanation of the default and how the pointer size is determined ๐.-mlong32โ Forcelong,int, and pointer types to be 32 bits wide ๐ฆ.
The default sizes of int, long, and pointers depend on the ABI ๐ซถ. All the supported ABIs use 32-bit ints ๐. The n64 ABI uses 64-bit longs, and so does the 64-bit EABI, but the others use 32-bit longs ๐. Pointers are the same size as longs, or the same size as integer registers, whichever is smaller โจ.
-msym32,-mno-sym32โ These assume (or don't assume) that all symbols have 32-bit values, no matter which ABI you picked ๐. This is super useful together with-mabi=64and-mno-abicalls, because it lets GCC generate shorter and faster references to symbolic addresses ๐ฅ.-G numโ Put definitions of externally-visible data in a small data section if that data is no bigger than num bytes ๐. This lets GCC generate more efficient accesses to the data, so check out-mgpoptfor the details ๐ง. The default-Gvalue depends on the configuration ๐ .-mlocal-sdata,-mno-local-sdataโ okay so these two either extend ๐ or don't extend the-Gbehavior to local data too, like static variables in C ๐ .-mlocal-sdatais the default for every configuration ๐.
If the linker starts yelling that an application is hogging too much small data ๐ญ, try rebuilding the less performance-critical bits with -mno-local-sdata. You can also build big libraries with -mno-local-sdata so they leave more room for the main program ๐ซถ.
-mextern-sdata,-mno-extern-sdataโ this one decides whether GCC assumes (or doesn't assume ๐ โโ๏ธ) that externally-defined data lives in a small data section, as long as its size fits within the-Glimit โจ.-mextern-sdatais the default for all configurations ๐ธ.
Be careful here, bestie ๐. If you compile a module Mod with -mextern-sdata -G num -mgpopt, and Mod references a variable Var that's no bigger than num bytes, you must make sure Var is placed in a small data section. If another module defines Var, you either compile that module with a high-enough -G setting or attach a "section" attribute to Var's definition. If Var is common, you have to link the application with a high-enough -G setting ๐ฅ.
The easiest way to avoid stress is to compile and link every module with the same -G option ๐ง. But if you're building a library that supports several different small data limits, you can compile it with the highest supported -G setting and also use -mno-extern-sdata, so the library stops making assumptions about externally-defined data ๐ฆ.
-mgpopt,-mno-gpoptโ uses (or doesn't use) GP-relative accesses for symbols that are known to live in a small data section ๐ง . See-G,-mlocal-sdataand-mextern-sdatafor the full picture ๐.-mgpoptis the default for all configurations ๐.
-mno-gpopt is useful when the $gp register might not hold the value of "_gp" ๐. For example, if the code is part of a library that might be used in a boot monitor, programs that call boot monitor routines pass an unknown value in $gp. (In those situations, the boot monitor itself is usually compiled with -G0 ๐ซ .)
-mno-gpopt implies -mno-local-sdata and -mno-extern-sdata โจ.
-membedded-data,-mno-embedded-dataโ allocates variables to the read-only data section first if possible, then to the small data section if possible, and otherwise to data ๐ฆ. It gives slightly slower code than the default ๐ข, but it reduces the amount of RAM needed while executing, so it might be your fave for some embedded systems ๐.-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ puts uninitialized"const"variables in the read-only data section ๐. This option only means something when paired with-membedded-data๐ซถ.-mcode-readable=settingโ specifies whether GCC is allowed to generate code that reads from executable sections ๐. There are three possible settings, babe:-mcode-readable=yesโ instructions can freely access executable sections. This is the default setting ๐.-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must NOT ๐ . This is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set ๐. It's also useful on processors that can be configured to have a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM ๐ง.-mcode-readable=noโ instructions must not access executable sections ๐ซ. This can be useful on targets configured to have a dual instruction/data SRAM interface that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM ๐.
On SDE targets, -mcode-data-in-code is available as a traditional alias for -mcode-readable=no, and -mcode-xonly is the traditional alias for -mcode-readable=pcrel ๐
.
-msplit-addresses,-mno-split-addressesโ enables (or disables) use of the%hi()and%lo()assembler relocation operators ๐งฉ. This option has been superseded by-mexplicit-relocs๐ค, but it's kept around for backwards compatibility ๐.-mexplicit-relocs=none,-mexplicit-relocs=base,-mexplicit-relocs=pcrel,-mexplicit-relocs,-mno-explicit-relocsโ these control whether explicit relocs (such as%gp_rel) get used ๐ง. The default depends on the version of GAS that was around when GCC itself was built ๐ฐ๏ธ.
The "base" explicit-relocs support was introduced into GAS in 2001 ๐
. The "pcrel" explicit-relocs support was introduced into GAS in 2014, and it supports %pcrel_hi and %pcrel_lo ๐ฆ.
-mcheck-zero-division,-mno-check-zero-divisionโ traps (or doesn't trap) on integer division by zero ๐. The default is-mcheck-zero-divisionโ .-mdivide-traps,-mdivide-breaksโ MIPS systems check for division by zero by generating either a conditional trap or abreakinstruction ๐. Using traps gives smaller code, but it's only supported on MIPS II and later ๐. Also, some versions of the Linux kernel have a bug that stopstrapfrom generating the proper signal ("SIGFPE") ๐ญ. Use-mdivide-trapsto allow conditional traps on architectures that support them, and-mdivide-breaksto force the use of breaks ๐ซถ.
The default is usually -mdivide-traps, but you can override it at configure time using --with-divide=breaks ๐ ๏ธ. Divide-by-zero checks can be completely disabled using -mno-check-zero-division ๐.
-mload-store-pairs,-mno-load-store-pairsโ enables (or disables) an optimization that pairs consecutive load or store instructions to enable load/store bonding ๐. It's on by default, but it only takes effect when the selected architecture is known to support bonding ๐.-mstrict-align,-mno-strict-align,-munaligned-access,-mno-unaligned-accessโ disables (or enables) direct unaligned access for MIPS Release 6 ๐ . MIPSr6 requires load/store unaligned-access support, either by hardware or by trapping and emulation ๐ง . In the latter case,-mstrict-alignmay be needed by the operating system kernel ๐ฅ๏ธ. The options-munaligned-accessand-mno-unaligned-accessare obsolete and only provided for backward compatibility ๐ฐ๏ธ.-mmemcpy,-mno-memcpyโ forces (or doesn't force) the use of"memcpy"for non-trivial block moves ๐. The default is-mno-memcpy, which lets GCC inline most constant-sized copies โก.-mlong-calls,-mno-long-callsโ disables (or doesn't disable) use of the"jal"instruction ๐. Calling functions using"jal"is more efficient, but it requires the caller and callee to be in the same 256 megabyte segment ๐บ๏ธ.
This option has no effect on abicalls code ๐
. The default is -mno-long-calls โ
.
-mmad,-mno-madโ enables (or disables) use of the"mad","madu"and"mul"instructions, as provided by the R4650 ISA ๐งฎ.-mimadd,-mno-imaddโ enables (or disables) use of the"madd"and"msub"integer instructions ๐ข. The default is-mimaddon architectures that support"madd"and"msub", except for the 74k architecture, where it was found to generate slower code ๐.-mfused-madd,-mno-fused-maddโ enables (or disables) use of the floating-point multiply-accumulate instructions when they're available ๐งฎ. The default is-mfused-maddโจ.
On the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product is calculated to infinite precision and is not subject to the FCSR Flush to Zero bit ๐. This may be undesirable in some circumstances ๐ค. On other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions ๐ฏ.
-nocppโ tells the MIPS assembler to not run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐ โโ๏ธ.-mfix-24k,-mno-fix-24kโ works around the 24K E48 (lost data on stores during refill) errata ๐ฉน. The workarounds are implemented by the assembler rather than by GCC ๐งฉ.-mfix-r4000,-mno-fix-r4000โ works around certain R4000 CPU errata ๐ ๏ธ. There are three of them, so buckle up:- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
- A double-word or a variable shift may give an incorrect result if executed while an integer multiplication is in progress.
- An integer division may give an incorrect result if started in a delay slot of a taken branch or a jump.
-mfix-r4400,-mno-fix-r4400โ works around certain R4400 CPU errata ๐ฉน:- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
-mfix-r10000,-mno-fix-r10000โ works around certain R10000 errata ๐ ๏ธ:"ll"/"sc"sequences may not behave atomically on revisions prior to 3.0. They may deadlock on revisions 2.6 and earlier.
This option can only be used if the target architecture supports branch-likely instructions ๐จ. -mfix-r10000 is the default when -march=r10000 is used; -mno-fix-r10000 is the default otherwise ๐ฏ.
-mfix-r5900,-mno-fix-r5900โ do not attempt to schedule the preceding instruction into the delay slot of a branch instruction placed at the end of a short loop of six instructions or fewer. Instead, always schedule a"nop"instruction there ๐ง. The short loop bug under certain conditions causes loops to execute only once or twice, due to a hardware bug in the R5900 chip ๐ต. The workaround is implemented by the assembler rather than by GCC ๐งฉ.-mfix-rm7000,-mno-fix-rm7000โ works around the RM7000"dmult"/"dmultu"errata ๐ง. The workarounds are implemented by the assembler rather than by GCC ๐งฉ.-mfix-vr4120,-mno-fix-vr4120โ works around certain VR4120 errata ๐ ๏ธ:"dmultu"does not always produce the correct result."div"and"ddiv"do not always produce the correct result if one of the operands is negative.
The workarounds for the division errata rely on special functions in libgcc.a ๐. At present, these functions are only provided by the "mips64vr*-elf" configurations ๐ฏ.
Other VR4120 errata require a NOP to be inserted between certain pairs of instructions ๐ซ . These errata are handled by the assembler, not by GCC itself ๐งฉ.
Okay so the VR4130 has this sneaky mflo/mfhi errata ๐
-mfix-vr4130,-mno-fix-vr4130โ these work around the VR4130 "mflo"/"mfhi" errata ๐ฉน. The fix is handled by the assembler, not GCC, but GCC steers clear ofmfloandmfhiwhen the VR4130macc,macchi,dmaccanddmacchiinstructions are available instead โจ.-mfix-sb1,-mno-fix-sb1โ bestie, this one patches certain SB-1 CPU core errata ๐ . Right now it only handles the SB-1 revision 2 "F1" and "F2" floating-point errata ๐ฅ.-mfix4300,-mno-fix4300โ this works around a bug in early VR4300 silicon ๐. Multiplies with certain operands can corrupt the multiply that comes right after them ๐.
๐ฆ -mr10k-cache-barrier=setting ๐ฆ
This one controls whether GCC inserts cache barriers to dodge the side effects of speculation on R10K processors ๐.
Okay, the vibe: lots of processors guess which way a conditional branch will go and speculatively run instructions from the "taken" branch ๐ฎ. If the guess was wrong, they abort those instructions later. The R10K is extra though, because even aborted instructions can leave side effects behind ๐ญ.
This only really messes with kernel stores and, depending on the system, kernel loads ๐. For example, a speculatively-executed store might pull the target memory into cache and mark the line as dirty, even if the store gets aborted later. If a DMA operation writes to that same memory before the "dirty" line is flushed, the cached data overwrites the DMA-ed data ๐. The R10K processor manual has the full scoop, including other potential problems ๐.
One workaround is to insert cache barrier instructions before every memory access that might be speculatively executed and that might have side effects even if aborted ๐ง. -mr10k-cache-barrier=setting controls how GCC does this. It assumes that aborted accesses to any byte in the following regions have no side effects:
- the memory occupied by the current function's stack frame;
- the memory occupied by an incoming stack argument;
- the memory occupied by an object with a link-time-constant address.
It's the kernel's job to make sure speculative accesses to these regions are actually safe ๐ซถ.
If your input program has a function declaration like this:
void foo (void);
then the implementation of foo must allow j foo and jal foo to run speculatively ๐ง. GCC honors this for functions it compiles itself. It expects non-GCC functions (like hand-written assembly) to do the same ๐.
The option comes in three forms:
-mr10k-cache-barrier=load-storeโ inserts a cache barrier before a load or store that might be speculatively executed and that might have side effects even if aborted ๐ธ.-mr10k-cache-barrier=storeโ inserts a cache barrier before a store that might be speculatively executed and that might have side effects even if aborted ๐.-mr10k-cache-barrier=noneโ disables the insertion of cache barriers. This is the default setting ๐.-mflush-func=func,-mno-flush-funcโ picks the function GCC calls to flush the I and D caches, or tells it to skip calling any such function ๐. If you do call one, it has to take the same arguments as the common_flush_func: the address of the memory range being flushed, the size of that range, and the number3(to flush both caches) โจ. The default depends on the target GCC was configured for, but it's commonly either_flush_funcor__cpu_flush๐.-mbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions ๐งฎ. Heads up, this is only a heuristic, so it isn't guaranteed to give consistent results across releases ๐. A zero cost redundantly selects the default, which is based on the-mtunesetting ๐.-mbranch-likely,-mno-branch-likelyโ enables or disables Branch Likely instructions, no matter what the selected architecture defaults to ๐ฆ. By default they may be generated if the selected architecture supports them. The exception is the MIPS32 and MIPS64 architectures, plus processors that implement those. For those, Branch Likely instructions aren't generated by default, because MIPS32 and MIPS64 specifically deprecate their use ๐ โโ๏ธ.-mcompact-branches=never,-mcompact-branches=optimal,-mcompact-branches=alwaysโ these control which form of branches gets generated ๐ฏ. The default is-mcompact-branches=optimal.-mcompact-branches=neverโ makes sure compact branch instructions are never generated ๐ซ.-mcompact-branches=alwaysโ makes sure a compact branch instruction is generated if one is available, for MIPS Release 6 onwards ๐โโ๏ธ. If a compact branch instruction isn't available (or it's pre-R6), a delay slot form of the branch is used instead ๐ข. If it's used for MIPS16/microMIPS targets, it's just ignored right now. The MIPS16/microMIPS behavior may change in the future, since those do have some compact branch instructions ๐.-mcompact-branches=optimalโ uses a delay slot branch if one is available in the current ISA and the delay slot is successfully filled ๐ง . If the delay slot isn't filled, a compact branch is chosen when one is available โจ.
-mfp-exceptions,-mno-fp-exceptionsโ specifies whether FP exceptions are enabled ๐งฏ. This affects how FP instructions get scheduled on some processors. By default, FP exceptions are enabled ๐. For instance, on the SB-1, if FP exceptions are disabled and we're emitting 64-bit code, then we can use both FP pipes ๐ถ. Otherwise, we can only use one FP pipe ๐ค.-mvr4130-align,-mno-vr4130-alignโ the VR4130 pipeline is two-way superscalar, but it can only issue two instructions together if the first one is 8-byte aligned ๐. When this option is on, GCC aligns pairs of instructions that it thinks should execute in parallel ๐ซ. It only does anything when you're optimizing for the VR4130 ๐ฏ. It usually makes code faster, but at the cost of making it bigger ๐. It's enabled by default at optimization level-O3๐ฅ.-msynci,-mno-synciโ enables or disables generation ofsynciinstructions on architectures that support them ๐. If enabled, thesynciinstructions get generated when__builtin___clear_cacheis compiled ๐ ๏ธ. This option defaults to-mno-synci, but you can override the default by configuring GCC with--with-synciโ๏ธ. Compiling for single processor systems? It's generally safe to usesynci๐. But on many multi-core (SMP) systems, it doesn't invalidate the instruction caches on all cores, and it may lead to undefined behavior ๐จ.-mrelax-pic-calls,-mno-relax-pic-callsโ tries to turn PIC calls that are normally dispatched via register$25into direct calls ๐ฏ. This only works if the linker can resolve the destination at link time, and if the destination is within range for a direct call ๐.-mrelax-pic-callsis the default if GCC was configured to use an assembler and linker that support the.relocassembly directive and-mexplicit-relocsis in effect ๐งฉ. With-mno-explicit-relocs, this optimization can be done by the assembler and the linker alone, without help from the compiler ๐ค.-mmcount-ra-address,-mno-mcount-ra-addressโ emits (or doesn't emit) code that lets_mcountmodify the calling function's return address ๐ช. When enabled, this extends the usual_mcountinterface with a new ra-address parameter. It has typeintptr_t *and gets passed in register$12๐งต._mcountcan then modify the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in
*ra-address, if ra-address is nonnull. The default is-mno-mcount-ra-address๐ .
- Returning the new address in register
-mframe-header-opt,-mno-frame-header-optโ enables (or disables) frame header optimization in the o32 ABI ๐งบ. With the o32 ABI, calling a function allocates 16 bytes on the stack for the called function to write out register arguments. When enabled, this optimization skips allocating the frame header if it can be determined that it's unused ๐งน. Heads up, it's off by default at all optimization levels ๐ โโ๏ธ.-mlxc1-sxc1,-mno-lxc1-sxc1โ when applicable, enables (or disables) generation oflwxc1,swxc1,ldxc1,sdxc1instructions ๐. Enabled by default ๐.-mmadd4,-mno-madd4โ when applicable, enables (or disables) generation of 4-operandmadd.s,madd.dand related instructions ๐งฎ. Enabled by default โจ.
๐ MMIX Options ๐
These options are defined for the MMIX ๐งโ๐ป:
-mlibfuncs,-mno-libfuncsโ specifies that intrinsic library functions are being compiled, passing all values in registers, no matter the size ๐ฆ.-mepsilon,-mno-epsilonโ generates floating-point comparison instructions that compare with respect to therEepsilon register ๐ฏ.-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code that passes function parameters and return values that (in the called function) are seen as registers$0and up ๐งบ.-mabi=gnuuses the GNU ABI instead, which uses global registers$231and up ๐.-mzero-extend,-mno-zero-extendโ when reading data from memory in sizes shorter than 64 bits, uses (or doesn't use) zero-extending load instructions by default, instead of sign-extending ones ๐ข.-mknuthdiv,-mno-knuthdivโ makes the result of a division that yields a remainder have the same sign as the divisor ๐ง . With the default,-mno-knuthdiv, the sign of the remainder follows the sign of the dividend. Both methods are arithmetically valid, though the latter is almost exclusively used ๐ค.-mtoplevel-symbols,-mno-toplevel-symbolsโ prepends (or doesn't prepend) a:to all global symbols, so the assembly code can be used with thePREFIXassembly directive ๐ท๏ธ.-melfโ generates an executable in the ELF format, instead of the default mmo format used by the mmix simulator ๐.-mbranch-predict,-mno-branch-predictโ uses (or doesn't use) the probable-branch instructions when static branch prediction indicates a probable branch ๐ฎ.-mbase-addresses,-mno-base-addressesโ okay so this one decides if your code uses base addresses ๐ When it does, the assembler and linker set up a constant in a global register, and then a bunch of base address requests within 0 to 255 get measured from whatever's sitting in that register โจ Generally that means short, fast code ๐ฅ BUT only a limited number of different data items can be addressed this way, so if your program uses lots of static data, you might need-mno-base-addresses๐-msingle-exit,-mno-single-exitโ this either forces or doesn't force the generated code to have one single exit point in each function ๐ฆ-mset-data-start=addressโ when linking, this sets the start of the data section toaddress๐-mset-program-start=address,-mno-set-program-startโ when linking, this sets the program start address toaddress๐ธ It defaults to0x100, unless you use-mno-set-program-start, which shuts this option off completely ๐
๐ฆ MN10300 Options ๐ฆ
These -m options are defined for Matsushita MN10300 architectures ๐
-mmult-bug,-mno-mult-bugโ when enabled, it generates code that dodges bugs in the multiply instructions for MN10300 processors ๐ก๏ธ This one's the default, periodt โจ-mam33,-mno-am33โ generates code using features specific to the AM33 processor ๐ The default is-mno-am33.-mam33-2,-mno-am33-2โ generates code using features specific to the AM33/2.0 processor ๐ซถ The default is-mno-am33-2.-mam34,-mno-am34โ generates code using features specific to the AM34 processor ๐ The default is-mno-am34.-mtune=cpu-typeโ uses the timing characteristics of the CPU type you pick when scheduling instructions โฑ๏ธ This does not change the targeted processor type, so don't panic ๐ญ The CPU type has to be one ofmn10300,am33,am33-2oram34.-mreturn-pointer-on-d0,-mno-return-pointer-on-d0โ when generating a function that returns a pointer, this returns the pointer in both"a0"and"d0"๐ Otherwise, the pointer only comes back in"a0", and trying to call those functions without a prototype throws errors ๐ This option is on by default. To turn it off, use-mno-return-pointer-on-d0๐ โโ๏ธ-mno-crt0โ do not link in the C run-time initialization object file ๐ง-mrelaxโ tells the linker to run a relaxation optimization pass that shortens branches, calls and absolute memory addresses ๐ฅ This only has an effect when you use it on the command line for the final link step.
Heads up bestie: this option makes symbolic debugging impossible ๐
-mliw,-mno-liwโ lets the compiler generate Long Instruction Word instructions if the target is AM33 or later ๐ This is enabled by default.-mliwdefines the preprocessor macro"__LIW__", and-mno-liwdefines the preprocessor macro"__NO_LIW__"๐-msetlb,-mno-setlbโ lets the compiler generate the SETLB and Lcc instructions if the target is AM33 or later ๐ฆ This is enabled by default.-msetlbdefines the preprocessor macro"__SETLB__", and-mno-setlbdefines the preprocessor macro"__NO_SETLB__"โจ
๐ธ Moxie Options ๐ธ
-mebโ generates big-endian code ๐ This is the default formoxie-*-*configurations.-melโ generates little-endian code ๐-mmul.x,-mno-mul.xโ generatesmul.xandumul.xinstructions ๐ง This option is enabled by default formoxiebox-*-*configurations.-mno-crt0โ do not link in the C run-time initialization object file ๐ง
๐ MSP430 Options ๐
These options are defined for the MSP430 โจ
-masm-hexโ forces assembly output to always use hex constants ๐ข Normally these constants are signed decimals, but this one's around for testsuite and/or aesthetic purposes ๐จ-mmcu=nameโ selects the MCU you're targeting ๐ฏ This creates a C preprocessor symbol based on the MCU name, converted to upper case and wrapped in__on both ends. Themsp430.hheader file then uses that symbol to pick an MCU-specific supplementary header file ๐ซง
The option also sets the ISA to use ๐ง If the MCU name is one that's known to only support the 430 ISA, that one gets selected. Otherwise, the 430X ISA gets selected. The generic MCU name msp430 can also select the 430 ISA, and the generic msp430x MCU name selects the 430X ISA ๐
On top of that, an MCU-specific linker script gets added to the linker command line ๐ The script's name is the MCU name with .ld tacked on the end. So -mmcu=xxx defines the C preprocessor symbol "__XXX__" and makes the linker search for a script called xxx.ld ๐ฅฐ
The ISA and hardware multiply support for each MCU is hard-coded into GCC ๐๏ธ However, an external devices.csv file can extend device support beyond those hard-coded ones, which is lowkey amazing ๐
GCC searches for the devices.csv file using the methods below, in precedence order. The first method beats the second, and the second beats the third ๐
- Include path specified with
-Iand-Lโdevices.csvgets searched for in each of the directories specified by the include paths and linker library search paths ๐ - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIRโ define the global environment variableMSP430_GCC_INCLUDE_DIRas the full path to the directory containingdevices.csv, and GCC will search that directory for it ๐๏ธ Ifdevices.csvis found there, this directory also gets registered as an include path and linker library path. That means header files and linker scripts in this directory can be used without manually specifying-Iand-Lon the command line ๐ซถ - The
msp430-elf{,bare}/include/devicesdirectory โ finally, GCC checksmsp430-elf{,bare}/include/devicesfrom the toolchain root directory ๐ฒ This directory doesn't exist in a default installation. But if you've created it and copieddevices.csvin there, the MCU data gets read. Like before, this directory is also registered as an include path and linker library path ๐
If none of the above search methods find devices.csv, then the hard-coded MCU data gets used ๐ฅน
-mwarn-mcu,-mno-warn-mcuโ this turns warnings on or off about conflicts between the MCU name from-mmcuand the ISA set by-mcpu, and/or the hardware multiply support set by-mhwmult๐จ It also toggles warnings about unrecognized MCU names. This option is on by default โ-msimโ links to the simulator runtime libraries and linker script ๐งช This overrides any scripts that would've been picked by-mmcu=๐-mlargeโ uses large-model addressing, with 20-bit pointers and a 20-bit"size_t"๐-msmallโ uses small-model addressing, with 16-bit pointers and a 16-bit"size_t"๐-mrelaxโ this gets passed to the assembler and linker, and lets the linker do certain optimizations that can't happen until the final link ๐งโโ๏ธmhwmult=typeโ describes the type of hardware multiply the target supports ๐งฎ The accepted values fortypeare:nonefor no hardware multiply ๐16bitfor the original 16-bit-only multiply supported by early MCUs ๐ฆ32bitfor the 16/32-bit multiply supported by later MCUs ๐ฆf5seriesfor the 16/32-bit multiply supported by F5-series MCUs ๐auto, which tells GCC to figure out the hardware multiply support from the MCU name you gave with-mmcu๐ต๏ธโโ๏ธ
If there's no -mmcu option, or the MCU name isn't recognized, then no hardware multiply support is assumed. "auto" is the default setting ๐
Hardware multiplies are normally performed by calling a library routine, which saves space in the generated code ๐ฆ When compiling at -O3 or higher, though, the hardware multiplier gets invoked inline. That makes the code bigger but faster ๐
The hardware multiply routines disable interrupts while they're running and restore the previous interrupt state when they finish ๐ This makes them safe to use inside interrupt handlers as well as in normal code ๐ซถ
-minrtโ enables a minimum runtime environment with no support for static initializers or constructors ๐ชถ This is meant for memory-constrained devices. The compiler puts special symbols in some objects that tell the linker and runtime which code fragments are required ๐งฉ-mtiny-printfโ enables reduced code size"printf"and"puts"library functions ๐ฃ
These tiny implementations are not reentrant, so be careful using them in multi-threaded applications ๐ฌ
Support for streams has been removed, and the string to be printed is always sent to stdout via the "write" syscall ๐จ The string isn't buffered before it's sent to write.
This option requires Newlib Nano IO, so GCC must be configured with --enable-newlib-nano-formatted-io โ๏ธ
-mmax-inline-shift=nโ this takes an integernbetween 0 and 64 inclusive, and sets the maximum number of inline shift instructions that can be emitted to perform a shift by a constant amount ๐ When that limit needs to be exceeded, anmspabihelper function is used instead. The default value is 4 ๐ฐ
This only affects cases where a shift by multiple positions can't be finished with a single instruction, like all shifts greater than 1 on the 430 ISA ๐ซง
Shifts of a 32-bit value are at least twice as costly, so the value you pass for this option gets divided by 2, and that resulting value is used instead ๐งฎ
-mcode-region=where,-mdata-region=whereโ these tell the compiler where to place functions and data that don't have one of the"lower","upper","either"or"section"attributes ๐บ๏ธ The possible values forwherearelower,upper,eitherorany. The first three behave like the corresponding attribute. The fourth value,any, is the default, and it leaves placement entirely up to the linker script and how it assigns the standard sections (".text",".data", etc.) to the memory regions ๐-muse-lower-region-prefixโ adds the.lowerprefix to section names when compiling with-mcode-region=loweror-mdata-region=lower๐ This is disabled by default.-msilicon-errata=name[,name...]: okay bestie, this one passes your request along to the assembler so it turns on the fixes for the silicon errata you name ๐งโจ For the full scoop, check the assembler docs.-msilicon-errata-warn=name[,name...]: same vibe, but instead of fixing things, the assembler just warns you when a named silicon errata might need a fix ๐ Again, the assembler docs have the details.-mwarn-devices-csv,-mno-warn-devices-csv: this one warns you ifdevices.csvis missing or if there are problems parsing it. It's on by default ๐
โจ NDS32 Options โจ
These options are defined for NDS32 implementations ๐ธ
-mbig-endian,-EB: generates code in big-endian mode ๐ฆ-mlittle-endian,-EL: generates code in little-endian mode ๐ซถ-mabi=2,-mfloat-abi=soft: uses the soft floating-point ABI ๐-mabi=2fp+,-mfloat-abi=hard: uses the hard floating-point ABI ๐ฅ-mreduced-regs: uses the reduced-set registers for register allocation ๐-mfull-regs: uses the full-set registers for register allocation ๐-malways-align: always aligns function entry, jump targets, and return address. Main character alignment energy ๐ง-malign-functions: aligns function entry to 4 bytes ๐-mfp-as-gp,-mno-fp-as-gp: enables or disables the fp-as-gp optimization ๐-mcmov,-mno-cmov: enables or disables generation of conditional move instructions โจ-mhw-abs,-mno-hw-abs: enables or disables generation of hardware abs instructions ๐-mext-perf,-mno-ext-perf: enables or disables generation of performance extension instructions โญ-mext-perf2,-mno-ext-perf2: enables or disables generation of performance extension 2 instructions ๐-mext-string,-mno-ext-string: enables or disables generation of string extension instructions ๐ซถ-mext-dsp,-mno-ext-dsp: enables or disables generation of DSP extension instructions ๐ฆ-mext-fpu-fma,-mno-ext-fpu-fma: enables or disables generation of floating-point multiply-accumulation instructions ๐ฅ-mext-fpu-sp,-mno-ext-fpu-sp: enables or disables generation of single-precision floating-point instructions ๐ธ-mext-fpu-dp,-mno-ext-fpu-dp: enables or disables generation of double-precision floating-point instructions ๐-mv3push,-mno-v3push: enables or disables generation of v3push25/pop25instructions ๐-m16-bit,-mno-16-bit: enables or disables generation of 16-bit instructions ๐-mvh,-mno-vh: enables or disables Virtual Hosting support ๐-misr-vector-size=num: specifies the size of each interrupt vector, which must be4or16๐ง-misr-secure=num: specifies the security level of c-isr for the whole file ๐-mcache-block-size=num: specifies the size of each cache block, which must be a power of 2 between 4 and 512 ๐-march=arch: specifies the target architecture.archmay be one ofv2,v3,v3j,v3m,v3f, orv3sโจ-mcpu=cpu: specifies the CPU to compile for.cpumay be one ofn6,n650,n7,n705,n8,n801,sn8,sn801,s8,s801,e8,e801,n820,s830,e830,n9,n903,n903a,n968,n968a,n10,n1033,n1033a,n1033-fpu,n1033-spu,n1068,n1068a,n1068-fpu,n1068a-fpu,d10,d1088,d1088-fpu,d1088-spu,n15,d15,n15s,d15s,n15f,d15f,n12,n1213,n1233,n1233-fpu,n1233-spu,n13,n1337,n1337-fpu,n1337-spu, orsimple๐-mconfig-fpu=num: specifies an FPU configuration value from0to7.0--3is as the FPU spec says, and4--7correspond to0--3๐ซถ-mconfig-mul=type: specifies the configuration for the multiply instruction.typecan be one offast,fast1(equivalent tofast),fast2, orslow. The default isfast1๐ฆ-mconfig-register-ports=kind: specifies the numbers of read/write ports for n9/n10 cores. The value should be3r2wor2r1w๐-mcmodel=code-model: sets the code model to one of the following ๐ธsmall: all the data and read-only data segments must be within 512KB addressing space. The text segment must be within 16MB addressing space.medium: the data segment must be within 512KB while the read-only data segment can be within 4GB addressing space. The text segment should be still within 16MB addressing space.large: all the text and data segments can be within 4GB addressing space.
The default is large on GNU/Linux targets and medium on other ELF targets ๐
-mctor-dtor,-mno-ctor-dtor: enables or disables the constructor/destructor feature ๐ง-mrelax,-mno-relax: enables or disables the linker option to relax instructions ๐-mrelax-hint,-mno-relax-hint: enables or disables insertion of hints for the linker to do relaxation ๐-msched-prolog-epilog,-mno-sched-prolog-epilog: enables or disables scheduling of a function's prologue and epilogue sequence ๐-mret-in-naked-func,-mno-ret-in-naked-func: enables or disables generation of return instructions in naked functions. This option is enabled by default ๐-malways-save-lp,-mno-always-save-lp: enables or disables always saving$lpon the stack ๐-munaligned-access,-mno-unaligned-access: enables or disables unaligned word and halfword accesses to packed data ๐-minline-asm-r15,-mno-inline-asm-r15: allows or disallows use ofr15for inline asm ๐ซถ
โจ Nvidia PTX Options โจ
These options are defined for Nvidia PTX ๐
-m64: ignored, but preserved for backward compatibility. Only the 64-bit ABI is supported ๐ฅ-march=architecture-string: generates code for the specified PTX ISA target architecture. Valid architecture strings aresm_30,sm_35,sm_37,sm_52,sm_53,sm_61,sm_70,sm_75,sm_80, andsm_89. The default depends on how the compiler has been configured, see--with-archโจ
This option sets the value of the preprocessor macro "__PTX_SM__". For instance, for sm_35, it has the value 350 ๐ง
-misa=architecture-string: an alias of-march=๐ธ-march-map=architecture-string: selects the closest available-march=value that is not more capable. For instance, for-march-map=sm_50it selects-march=sm_37, and for-march-map=sm_53it selects-march=sm_53๐บ๏ธ-mptx=version-string: generates code for the specified PTX ISA version. Valid version strings are3.1,4.1,4.2,5.0,6.0,6.3,7.0,7.3, and7.8. The default PTX ISA version is the one that added support for the selected PTX ISA target architecture, see-march=, but at least6.3, or7.3for-march=sm_52and higher ๐
This option sets the values of the preprocessor macros "__PTX_ISA_VERSION_MAJOR__" and "__PTX_ISA_VERSION_MINOR__". For instance, for 3.1 the macros have the values 3 and 1, respectively ๐ฆ
-mmainkernel: links in code for a__mainkernel. This is for stand-alone instead of offloading execution ๐ซถ-moptimize,-mno-optimize: enables or disables partitioned execution optimizations. This option is enabled by default when any level of optimization is selected ๐-msoft-stack,-mno-soft-stack: ๐
For -mno-soft-stack (the default, unless -mgomp has been specified), use PTX "native" stacks, that is, generate code that uses ".local" memory or PTX "alloca" directly for stack storage. Unless -mptx=7.3 or higher and -march=sm_52 or higher are active, variable-length arrays and dynamically allocating memory on the stack with "alloca" are not supported.
For -msoft-stack (implied by -mgomp), generate code that does not use ".local" memory or PTX "alloca" directly for stack storage. Instead, a per-warp stack pointer is maintained explicitly. This enables variable-length stack allocation (with variable-length arrays or "alloca"), and when global memory is used for underlying storage, makes it possible to access automatic variables from other threads, or with atomic instructions. This code generation variant is used for OpenMP offloading, but the option is exposed on its own for the purpose of testing the compiler. To generate code suitable for linking into programs using OpenMP offloading, use option -mgomp ๐ง
-msoft-stack-reserve-local=size: specifies the size of".local"memory used for the stack when the exact amount is not known. It defaults to128๐-muniform-simt,-mno-uniform-simt: enables or disables a code generation variant that allows execution of all threads in each warp, while maintaining memory state and side effects as if only one thread in each warp was active outside of OpenMP SIMD regions. All atomic operations and calls to runtime ("malloc","free","vprintf") are conditionally executed (iff current lane index equals the master lane index), and the register being assigned is copied via a shuffle instruction from the master lane. Outside of SIMD regions lane 0 is the master; inside, each thread sees itself as the master. Shared memory array"int __nvptx_uni[]"stores all-zeros or all-ones bitmasks for each warp, indicating current mode (0 outside of SIMD regions). Each thread can bitwise-and the bitmask at position"tid.y"with current lane index to compute the master lane index ๐-mgomp,-mno-gomp: enables or disables generation of code for use in OpenMP offloading.-mgompenables-msoft-stackand-muniform-simtoptions, and selects a corresponding multilib variant ๐ธ
โจ OpenRISC Options โจ
These options are defined for OpenRISC ๐
-mboard=name: configures a board specific runtime. This is passed to the linker for newlib board library linking. The default is"or1ksim"๐ฆ-msoft-div,-mhard-div: selects software or hardware divide ("l.div","l.divu") instructions. The default is hardware divide ๐-msoft-mul,-mhard-mul: selects software or hardware multiply ("l.mul","l.muli") instructions. The default is hardware multiply ๐-msoft-float,-mhard-float: selects software or hardware for floating point operations. The default is software ๐ซถ-mdouble-float: when-mhard-floatis selected, enables generation of double-precision floating point instructions. By default, functions from libgcc are used to perform double-precision floating point operations ๐ฅ-munordered-float: when-mhard-floatis selected, enables generation of unordered floating point compare and set flag ("lf.sfun*") instructions. By default, functions from libgcc are used to perform unordered floating point compare and set flag operations ๐-mcmovโ okay so this turns on conditional move (l.cmov) instructions ๐ . Without it, GCC builds the same effect with set and branch instead.-mrorโ enablesl.rorrotate-right instructions โจ. By default, rotate-right operations go through functions from libgcc.-mroriโ enablesl.rorirotate-right-with-immediate instructions ๐ฆ. By default, these also go through libgcc functions.-msextโ enablesl.ext*sign extension instructions ๐. By default, sign extension is handled with memory loads.-msfimmโ enablesl.sf*icompare-and-set-flag-with-immediate instructions ๐ฅ. By default, GCC adds extra instructions to store the immediate in a register first.-mshftimmโ enablesl.srai,l.srli, andl.sllishift-with-immediate instructions ๐. By default, extra instructions store the immediate in a register first.-mcmodel=smallโ generates OpenRISC code for the small model ๐ธ. The GOT is limited to 64k, and function call jumps are limited to 64M offsets. This is the default model.-mcmodel=largeโ generates OpenRISC code for the large model ๐. The GOT can grow up to 4G in size, and function call jumps can target the full 4G address space.
๐ธ PDP-11 Options ๐ธ
These options are defined for the PDP-11 ๐:
-mfpuโ uses hardware FPP floating point ๐ฅ. This is the default. (FIS floating point on the PDP-11/40 is not supported.) Implies-m45.-msoft-floatโ skips hardware floating point ๐.-mac0,-mno-ac0โ with-mac0, floating-point results come back inac0(fr0in Unix assembler syntax) ๐ . The default,-mno-ac0, returns floating-point results in memory.-m40โ generates code for a PDP-11/40 ๐ฆ. Implies-msoft-float -mno-split.-m45โ generates code for a PDP-11/45 โจ. This is the default.-m10โ generates code for a PDP-11/10 ๐ง. Implies-msoft-float -mno-split.-mint16,-mno-int32โ uses a 16-bitint๐. This is the default.-mint32,-mno-int16โ uses a 32-bitint๐.-msplitโ the target has split instruction and data space ๐. Implies-m45.-munix-asmโ uses Unix assembler syntax ๐ง.-mdec-asmโ uses DEC assembler syntax ๐.-mgnu-asmโ uses GNU assembler syntax ๐ . This is the default.-mlraโ uses the new LRA register allocator ๐ฅ. By default, the oldreloadallocator is used.
๐ง PowerPC Options ๐ง
These are listed under ๐
๐ PRU Options ๐
These command-line options are defined for the PRU target ๐ :
-minrtโ links with a minimum runtime environment ๐ฆ. This can seriously shrink the final ELF binary, but some standard C runtime features get removed.
This option disables support for static initializers and constructors. Beware, because the compiler could still generate code with static initializers and constructors. It's up to the programmer to make sure the source program doesn't use those features.
The minimal startup code does not pass argc and argv arguments to main, so main has to be declared as int main (void). This is already the norm for most firmware projects โจ.
-mmcu=mcuโ picks the PRU hardware variant to use ๐ฅ. A correspondingly named spec file gets loaded, which passes the memory region sizes to the linker and defines hardware-specific C macros.
Newlib only provides the sim spec, which is meant for running regression tests with a simulator ๐. Specs for real hardware can be obtained by installing the GnuPruMcu package at https://github.com/dinuxbg/gnuprumcu/ ๐ซถ.
-mno-relaxโ makes GCC pass--no-relaxto the linker instead of--relax๐.-mloop,-mno-loopโ allows (or doesn't allow) GCC to use theLOOPinstruction ๐.-mmul,-mno-mulโ allows (or doesn't allow) GCC to use the PRU multiplier unit ๐.-mfillzero,-mno-fillzeroโ allows (or doesn't allow) GCC to use theFILLandZEROinstructions ๐ธ.-mabi=variantโ picks the ABI variant to output code for ๐.-mabi=tiselects the unmodified TI ABI, while-mabi=gnuselects a GNU variant that copes more naturally with certain GCC assumptions. Here's how they differ:- Function Pointer Size โ TI ABI says function (code) pointers are 16-bit, whereas GNU only supports 32-bit data and code pointers ๐.
- Optional Return Value Pointer โ return values larger than 64 bits get passed through a hidden pointer as the first argument of the function ๐ฆ. TI ABI mandates that this pointer can be
NULLif the caller isn't using the returned value. GNU always passes and expects a valid return value pointer ๐ . - Size Of Struct Containing Bit-fields โ TI ABI says the struct size is determined by the bit-field type, if it has any ๐ง. GNU allocates the smallest number of bytes that would fit the bit-field โจ.
For example, TI ABI reserves 4 bytes for this struct, whereas GNU reserves a single byte ๐:
struct S { int i:1; };
- Access Size For Volatile Bit-fields โ TI ABI mandates that volatile bit-fields are accessed using their type ๐ฅ. GNU ABI instead uses the smallest integer type that fits the bit-field ๐.
For example, TI ABI requires a single load of 4 bytes for the following bit-field. GNU generates a load of 1 byte ๐:
struct S { volatile int i:1; };
The current -mabi=ti implementation just raises a compile error whenever any of the above code constructs shows up ๐ญ. As a result, the standard C library can't be built, so it's omitted when linking with -mabi=ti.
Relaxation is a GNU feature, and for safety reasons it's disabled when using -mabi=ti. The TI toolchain doesn't emit relocations for QBBx instructions, so the GNU linker can't adjust them when it shortens adjacent LDI32 pseudo instructions.
๐ฆ RISC-V Options ๐ฆ
These command-line options are defined for RISC-V targets ๐:
-mbranch-cost=nโ sets the cost of branches to roughlyninstructions ๐ .-mabi=ABI-stringโ picks the integer and floating-point calling convention โจ. An ABI string has two parts: the size of integer types, and the registers used for floating-point types ๐ง. For example,-march=rv64ifd -mabi=lp64dmeanslongand pointers are 64-bit (which implicitly makesint32-bit), and floating-point values up to 64 bits wide are passed in F registers ๐ฅ. Compare that with-march=rv64ifd -mabi=lp64f, which still lets the compiler generate code that uses the F and D extensions, but only allows floating-point values up to 32 bits long to be passed in registers ๐. Or there's-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers ๐.
The default for this argument is system dependent, so if you want a specific calling convention, you should specify one explicitly ๐ซถ. The valid calling conventions are ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d ๐. Some calling conventions are impossible on some ISAs. For example, -march=rv32if -mabi=ilp32d is invalid, because the ABI requires 64-bit values to be passed in F registers, but F registers are only 32 bits wide ๐ญ. There's also the ilp32e ABI, which can only be used with the rv32e architecture, and the lp64e ABI, which can only be used with rv64e ๐.
Theilp32eandlp64eABIs aren't well-specified at present, and they're subject to change.
-mfdiv,-mno-fdivโ does (or doesn't) use hardware floating-point divide and square root instructions ๐ฆ. This requires the F or D extensions for floating-point registers. The default is to use them if the specified architecture has these instructions ๐ฅ.-mfence-tso,-mno-fence-tsoโ does (or doesn't) use thefence.tsoinstruction ๐ . It's unimplemented on some processors, including those from T-Head ๐. If thefence.tsoinstruction isn't available, a stronger fence is used instead ๐ซถ.-mdiv,-mno-divโ does (or doesn't) use hardware instructions for integer division โจ. This requires the M extension. The default is to use them if the specified architecture has these instructions ๐.-misa-spec=ISA-spec-stringโ picks the version of the RISC-V Unprivileged (formerly User-Level) ISA specification that generated code should conform to ๐ง. The possible values forISA-spec-stringare:2.2โ produces code conforming to version 2.2 ๐.20190608โ produces code conforming to version 20190608 ๐.20191213โ produces code conforming to version 20191213 ๐ธ.
The default is -misa-spec=20191213, unless GCC has been configured with --with-isa-spec= specifying a different default version ๐.
-march=[ISA|Profile|Profile_ISA|processor-string]โ generates code for a given RISC-V ISA, profile, or a combination of them (for example,rv64im,rvi20u64, orrvi20u64_zbb) ๐. ISA and profile names must be lower case. Examples includerv64i,rv32g,rv32e,rv32imaf,rva22u64, andrva23u64๐ . To combine a named profile with optional RISC-V ISA extensions, put the profile first and then append the extension name(s) with an underscore as the delimiter (for example,rvi20u64_zca_zcborrva23u64_zacas) โจ. There's also a special value,help(-march=help), which lists all supported extensions ๐ฅ.
-march=unset makes the compiler ignore any -march=... options that appear earlier on the command line, behaving as if that option was never passed ๐ฆ. This is handy for making sure the architecture comes from the -mcpu option. An error results if no -mcpu option is given when -march=unset is used ๐.
The syntax of the ISA string is defined as follows:
- The string must start with
rv32orrv64, followed byi,e, org. These are called the base ISA ๐ง. - The rest of the string is a list of extension names. Extension names can be multi-letter (for example,
zba) or single-letter (for example,v). Single-letter extensions can appear back to back, but multi-letter extensions must be separated by underscores ๐. - An underscore can appear anywhere after the base ISA. It has no specific effect, but it's used to improve readability and can act as a separator ๐ซถ.
okay so extension names can carry a version too ๐
the syntax is <major>p<minor> or just <major>, so m2p1 or m2 both work ๐ฆ here's the full lineup, with the version(s) each one supports and what it's about. quick heads up: a version of - just means there isn't one listed ๐ซถ
g(version-) โ the general-purpose computing base extension โจgis shorthand that expands toi,m,a,f,d,zicsrandzifencei, so you get all of them in one go ๐e(version 2.0) โ the reduced base integer extension ๐ธi(versions 2.0 and 2.1) โ the base integer extension ๐m(version 2.0) โ integer multiplication and division, obsessed ๐ฅa(versions 2.0 and 2.1) โ the atomic extension ๐f(versions 2.0 and 2.2) โ single-precision floating-point ๐ฆd(versions 2.0 and 2.2) โ double-precision floating-point, iconic ๐c(version 2.0) โ the compressed extension ๐งb(version 1.0) โ the standard extension for bit manipulation functions ๐v(version 1.0) โ the vector extension โจh(version 1.0) โ the hypervisor extension ๐zic64b(version 1.0) โ cache block size is 64 bytes ๐zicbom(version 1.0) โ cache-block management, main character energy ๐zicbop(version 1.0) โ cache-block prefetch ๐ธzicboz(version 1.0) โ cache-block zero ๐ฆziccamoa(version 1.0) โ main memory supports all atomics inA๐ziccif(version 1.0) โ main memory supports instruction fetch with an atomicity requirement ๐ซถzicclsm(version 1.0) โ main memory supports misaligned loads and stores ๐ziccrse(version 1.0) โ main memory supports forward progress onLR/SCsequences โจzicfilp(version 1.0) โ control-flow integrity landing pad extension ๐ฅzicfiss(version 1.0) โ control-flow integrity shadow stack extension ๐zicntr(version 2.0) โ the standard extension for base counters and timers โญzicond(version 1.0) โ integer conditional operations ๐งzicsr(version 2.0) โ control and status register access, slay ๐zifencei(version 2.0) โ instruction-fetch fence ๐zihintntl(version 1.0) โ non-temporal locality hints ๐ธzihintpause(version 2.0) โ pause hint ๐ฆzihpm(version 2.0) โ the standard extension for hardware performance counters ๐zimop(version 1.0) โ may-be-operations ๐zilsd(version 1.0) โ load/store pair instructions โจzmmul(version 1.0) โ integer multiplication ๐za128rs(version 1.0) โ reservation set size of 128 bytes ๐za64rs(version 1.0) โ reservation set size of 64 bytes ๐zaamo(version 1.0) โ atomic memory operations ๐ฅzabha(version 1.0) โ byte and halfword atomic memory operations ๐zacas(version 1.0) โ atomic compare-and-swap instructions ๐zalrsc(version 1.0) โ the load-reserved/store-conditional subset of theAextension ๐ซถzawrs(version 1.0) โ wait-on-reservation-set ๐งzama16b(version 1.0) โ misaligned loads, stores, and AMOs that are fully contained within a naturally-aligned 16-byte boundary are atomic ๐ธzfa(version 1.0) โ additional floating-point ๐ฆzfbfmin(version 1.0) โ minimal BF16 support ๐zfh(version 1.0) โ half-precision floating-point ๐zfhmin(version 1.0) โ minimal half-precision floating-point โจzfinx(version 1.0) โ single-precision floating-point in integer registers ๐zdinx(version 1.0) โ double-precision floating-point in integer registers ๐ฅzca(version 1.0) โ integer compressed instructions ๐งzcb(version 1.0) โ simple compressed instructions ๐zcd(version 1.0) โ compressed double-precision floating-point loads and stores ๐ธzce(version 1.0) โ compressed instruction extensions for embedded processors ๐zcf(version 1.0) โ compressed single-precision floating-point loads and stores ๐ฆzcmop(version 1.0) โ compressed may-be-operations ๐zcmp(version 1.0) โ compressed push and pop ๐zcmt(version 1.0) โ table jump instructions ๐zclsd(version 1.0) โ compressed load/store pair instructions ๐ซถzba(version 1.0) โ address calculation ๐zbb(version 1.0) โ basic bit manipulation ๐ฅzbc(version 1.0) โ carry-less multiplication โจzbkb(version 1.0) โ cryptography bit-manipulation ๐zbkc(version 1.0) โ cryptography carry-less multiply ๐zbkx(version 1.0) โ cryptography crossbar permutation ๐งzbs(version 1.0) โ single-bit operations ๐zk(version 1.0) โ the standard scalar cryptography extension ๐โจzkn(version 1.0) โ the NIST algorithm suite extension ๐ธzknd(version 1.0) โ AES decryption ๐ฆzkne(version 1.0) โ AES encryption ๐zknh(version 1.0) โ hash functions ๐zkr(version 1.0) โ entropy source โจzks(version 1.0) โ the ShangMi algorithm suite extension ๐zksed(version 1.0) โ SM4 block cipher ๐ฅzksh(version 1.0) โ SM3 hash function ๐งzkt(version 1.0) โ data independent execution latency ๐ztso(version 1.0) โ total store ordering ๐zvbb(version 1.0) โ vector basic bit-manipulation ๐ซถzvbc(version 1.0) โ vector carry-less multiplication ๐ธzve32f(version 1.0) โ vector extensions for embedded processors ๐zve32x(version 1.0) โ vector extensions for embedded processors ๐zve64d(version 1.0) โ vector extensions for embedded processors ๐ฆzve64f(version 1.0) โ vector extensions for embedded processors ๐ฆzve64x(version 1.0) โ vector extensions for embedded processors ๐zvfbfmin(version 1.0) โ vector BF16 converts ๐zvfbfwma(version 1.0) โ vector BF16 widening multiply/add ๐zvfh(version 1.0) โ vector half-precision floating-point ๐zvfhmin(version 1.0) โ vector minimal half-precision floating-point ๐ฅzvkb(version 1.0) โ vector cryptography bit-manipulation โจzvkg(version 1.0) โ vector GCM/GMAC ๐zvkn(version 1.0) โ vector NIST Algorithm Suite, wherezvknwill expand to (the page just trails off right there ๐)zvknc(version 1.0) โ vector NIST Algorithm Suite with carry-less multiply,zvknc๐งzvkned(version 1.0) โ vector AES block cipher ๐zvkng(version 1.0) โ vector NIST Algorithm Suite with GCM, wherezvkngwill expand (again, cut off here ๐)zvknha(version 1.0) โ vector SHA-2 secure hash ๐ธzvknhb(version 1.0) โ vector SHA-2 secure hash ๐ฆzvks(version 1.0) โ vector ShangMi algorithm suite, wherezvkswill expand (cut off ๐)zvksc(version 1.0) โ vector ShangMi algorithm suite with carry-less multiplication, and the page stops right after the comma ๐zvksed(version 1.0) โ vector SM4 block cipher ๐zvksg(version 1.0) โ vector ShangMi algorithm suite with GCM ๐zvksh(version 1.0) โ vector SM3 secure hash โจzvkt(version 1.0) โ vector data independent execution latency ๐zvl1024b(version 1.0) โ minimum vector length standard extensions ๐ฅzvl128b(version 1.0) โ minimum vector length standard extensions ๐งzvl16384b(version 1.0) โ minimum vector length standard extension ๐zvl2048b(version 1.0) โ minimum vector length standard extensions ๐zvl256b(version 1.0) โ minimum vector length standard extensions ๐ซถzvl32768b(version 1.0) โ minimum vector length standard extension ๐ธzvl32b(version 1.0) โ minimum vector length standard extensions ๐zvl4096b(version 1.0) โ minimum vector length standard extensions ๐ฆzvl512b(version 1.0) โ minimum vector length standard extensions ๐zvl64b(version 1.0) โ minimum vector length standard extensions ๐zvl65536b(version 1.0) โ minimum vector length standard extension ๐zvl8192b(version 1.0) โ minimum vector length standard extension ๐zhinx(version 1.0) โ half-precision floating-point in integer registers ๐ฅzhinxmin(version 1.0) โ minimal half-precision floating-point in integer registers โจsdtrig(version 1.0) โ debug triggers ๐sha(version 1.0) โ the augmented hypervisor extension ๐shcounterenw(version 1.0) โ writeable enables for any supported counter ๐งshgatpa(version 1.0) โSvNNx4mode supported for all modes thatsatpsupports ๐shlcofideleg(version 1.0) โ delegating LCOFI interrupts to VS-mode ๐shtvala(version 1.0) โ thehtvalregister provides all the values needed ๐ซถshvstvala(version 1.0) โ thevstvalregister provides all the values needed ๐ธshvstvecd(version 1.0) โ thevstvecregister supports direct mode ๐shvsatpa(version 1.0) โ thevsatpregister supports all modes thatsatpsupports ๐ฆsmaia(version 1.0) โ advanced interrupt architecture ๐smcntrpmf(version 1.0) โ cycle and instret privilege mode filtering ๐smcsrind(version 1.0) โ machine-level indirect CSR access ๐smepmp(version 1.0) โ PMP enhancements for memory access and execution prevention in machine mode ๐smmpm(version 1.0) โ supervisor-mode pointer masking ๐ฅsmnpm(version 1.0) โ supervisor-mode pointer masking, same vibe assmmpmโจsmrnmi(version 1.0) โ resumable non-maskable interrupts ๐smstateen(version 1.0) โ state enable ๐smdbltrp(version 1.0) โ double trap extensions ๐งssaia(version 1.0) โ advanced interrupt architecture for supervisor mode ๐
Okay so the extension list keeps going, bestie ๐ซถ and every single one of these is giving main character energy โจ
ssccptr(v1.0) โ main memory supports page table reads ๐sscofpmf(v1.0) โ count overflow and filtering extension ๐ฆsscounterenw(v1.0) โ writeable enables for any supported counter, iconic ๐ธsscsrind(v1.0) โ supervisor-mode indirect CSR accessssnpm(v1.0) โ supervisor-mode pointer masking extensionsspm(v1.0) โ same vibe asssnpm, supervisor-mode pointer masking extension ๐ssstateen(v1.0) โ supervisor-mode state-enable extensionsstc(v1.0) โ supervisor-mode timer interrupts extension โฐsstvala(v1.0) โ stval provides all the values you need โจsstvecd(v1.0) โ stvec supports direct mode ๐ssstrict(v1.0) โ unimplemented reserved encodings raise illegal instruction exceptions, and no non-conforming extensions are present ๐ssdbltrp(v1.0) โ double trap extensionsssu64xl(v1.0) โUXLEN=64must be supportedsupm(v1.0) โ user-mode pointer masking extensionsvinval(v1.0) โ fine-grained address-translation cache invalidation extensionsvnapot(v1.0) โ NAPOT translation contiguity extension ๐svpbmt(v1.0) โ page-based memory types extensionsvvptc(v1.0) โ extension that makes memory-management instructions unnecessary after you mark PTEs valid ๐งsvadu(v1.0) โ hardware updating of A/D bits extensionsvade(v1.0) โ cause exception when hardware updating of A/D bits is disabledsvbare(v1.0) โ satp mode bare is supportedxcvalu(v1.0) โ Core-V miscellaneous ALU extensionxcvbi(v1.0) โ Core-V immediate branch extensionxcvelw(v1.0) โ Core-V event load word extensionxcvmac(v1.0) โ Core-V multiply-accumulate extensionxcvsimd(v1.0) โ Core-V SIMD extensionxsfcease(v1.0) โ SiFive CEASE instruction extensionxsfvcp(v1.0) โ SiFive VCIX vector coprocessor extensionxsfvfnrclipxfqf(v1.0) โ SiFive FP32-to-int8 ranged clip instructionsxsfvqmaccdod(v1.0) โ SiFive int8 matrix multiplication extensionxsfvqmaccqoq(v1.0) โ SiFive int8 matrix multiplication extension ๐ฅxtheadba(v1.0) โ T-head address calculation extensionxtheadbb(v1.0) โ T-head basic bit-manipulation extensionxtheadbs(v1.0) โ T-head single-bit instructions extensionxtheadcmo(v1.0) โ T-head cache management operations extensionxtheadcondmov(v1.0) โ T-head conditional move extensionxtheadfmemidx(v1.0) โ T-head indexed memory operations for floating-point registers extensionxtheadfmv(v1.0) โ T-head double floating-point high-bit data transmission extensionxtheadint(v1.0) โ T-head acceleration interruption extensionxtheadmac(v1.0) โ T-head multiply-accumulate extensionxtheadmemidx(v1.0) โ T-head indexed memory operation extensionxtheadmempair(v1.0) โ T-head two-GPR memory operation extensionxtheadsync(v1.0) โ T-head multi-core synchronization extensionxtheadvector(v1.0) โ T-head vector extensionxventanacondops(v1.0) โ Ventana integer conditional operations extensionxmipscmov(v1.0) โ Mips conditional move extensionxmipscbop(v1.0) โ Mips prefetch extensionxandesperf(v5.0) โ Andes performance extension ๐xandesbfhcvt(v5.0) โ Andes bfloat16 conversion extensionxandesvbfhcvt(v5.0) โ Andes vector bfloat16 conversion extensionxandesvsintload(v5.0) โ Andes vector INT4 load extensionxandesvpackfph(v5.0) โ Andes vector packed FP16 extensionxandesvdot(v5.0) โ Andes vector dot product extensionxsmtvdot(v1.0) โ SpacemiT vector dot product extension ๐
When -march= is not specified, GCC uses the setting from -mcpu.
If both -march and -mcpu= are not specified, the default for this argument is system dependent. So if you want a specific architecture extension, you should specify one explicitly, no excuses ๐
When the RISC-V specifications define an extension as depending on other extensions, GCC implicitly adds the dependent extensions to the enabled extension set if they weren't added explicitly. It's like the extensions come as a package deal ๐ซถ
๐ Core Name
-mcpu=processor-stringโ use the architecture of, and optimize the output for, the given processor, specified by a particular CPU name. Permissible values for this option are:
sifive-e20, sifive-e21, sifive-e24, sifive-e31, sifive-e34, sifive-e76, sifive-s21, sifive-s51, sifive-s54, sifive-s76, sifive-u54, sifive-u74, sifive-x280, sifive-p450, sifive-p670, thead-c906, xt-c908, xt-c908v, xt-c910, xt-c910v2, xt-c920, xt-c920v2, tt-ascalon-d8, xiangshan-nanhu, xiangshan-kunminghu, mips-p8700, andes-n22, andes-n25, andes-a25, andes-nx25, andes-ax25, andes-a27, andes-ax27, andes-n225, andes-d23, andes-n45, andes-nx45, andes-a45, andes-ax45, spacemit-x60.
Note that -mcpu does not override -march or -mtune. Don't expect it to ๐
โโ๏ธ
๐ Tune Name
-mtune=processor-stringโ optimize the output for the given processor, specified by microarchitecture or a particular CPU name. Permissible values for this option are:
generic, rocket, sifive-3-series, sifive-5-series, sifive-7-series, sifive-p400-series, sifive-p600-series, tt-ascalon-d8, thead-c906, xt-c908, xt-c908v, xt-c910, xt-c910v2, xt-c920, xt-c920v2, xiangshan-nanhu, xiangshan-kunminghu, spacemit-x60, generic-ooo, size, mips-p8700, andes-25-series, andes-23-series, andes-45-series, and all valid options for -mcpu=.
When -mtune= is not specified, GCC uses the setting from -mcpu. The default is generic if neither is specified.
The size choice is not intended for use by end-users, bestie. It's used when -Os is specified. It overrides the instruction cost info provided by -mtune=, but it does not override the pipeline info. This helps reduce code size while still giving good performance ๐
-mpreferred-stack-boundary=numโ attempt to keep the stack boundary aligned to a 2 raised to num byte boundary. If-mpreferred-stack-boundaryis not specified, the default is4(16 bytes or 128-bits).
โ ๏ธ Warning: if you use this switch, you must build all modules with the same value, including any libraries. That means the system libraries and startup modules too. Don't skip this one, it's serious ๐
-msmall-data-limit=nโ put global and static data smaller than n bytes into a special section (on some targets) ๐ฆ-msave-restore,-mno-save-restoreโ do or don't use smaller but slower prologue and epilogue code that uses library function calls. The default is to use fast inline prologues and epilogues โก-mmovcc,-mno-movccโ do or don't produce branchless conditional-move code sequences, even on targets that don't have specific instructions for conditional operations. If enabled, sequences of ALU operations are produced using base integer ISA instructions where profitable ๐ง-minline-atomics,-mno-inline-atomicsโ do or don't use smaller but slower subword atomic emulation code that useslibatomicfunction calls. The default is to use fast inline subword atomics that don't requirelibatomic๐ฅ-minline-strlen,-mno-inline-strlenโ do or do not attempt to inlinestrlencalls if possible. Inlining can only be done if the string is properly aligned and instructions for accelerated processing are available. The default is to inlinestrlencalls โจ-minline-strcmp,-mno-inline-strcmpโ do or do not attempt to inlinestrcmpcalls if possible. Inlining can only be done if the strings are properly aligned and instructions for accelerated processing are available. The default is to inlinestrcmpcalls ๐-minline-strncmp,-mno-inline-strncmpโ do or do not attempt to inlinestrncmpcalls if possible. Inlining can only be done if the strings are properly aligned and instructions for accelerated processing are available. The default is to inlinestrncmpcalls ๐ฆ-mstringop-strategy=strategyโ pick a specific strategy for inlining string and memory operations. strategy may be one ofauto,libcall,scalar, orvector๐ธ-mshorten-memrefs,-mno-shorten-memrefsโ do or do not try to make more use of compressed load/store instructions, by replacing a load/store of 'base register + large offset' with a new load/store of 'new base + small offset'. If the new base gets stored in a compressed register, then the new load/store can be compressed. Currently this only targets 32-bit integer load/stores ๐ง-mstrict-align,-mno-strict-alignโ this one is a lot: it controls whether unaligned memory accesses get generated or not. The default depends on whether the processor you're optimizing for supports fast unaligned access or not ๐-mscalar-strict-align,-mno-scalar-strict-alignโ same deal as the one above, it controls unaligned memory accesses, with the default depending on fast unaligned access support. This is an alias for-mstrict-align๐ซถ
-mvector-strict-align, -mno-vector-strict-align ๐ โ bestie, these decide whether GCC is allowed to generate unaligned vector memory accesses ๐ซถ Default is off, unless the processor you're optimizing for explicitly supports element-misaligned vector memory access โจ
-menable-vectorization-overrideโ no wait, scratch that. Here's the real one:-mmax-vectorization,-mno-max-vectorization๐ โ this turns an override on or off for the vectorizer's cost model, so vectorization always looks profitable ๐ฅ Unlike-fno-vect-cost-modelor-fvect-cost-model=unlimited, this one does not turn off the cost comparison between different vector modes ๐ง-mcmodel=medlow๐ธ โ generates code for the medium-low code model. The program and its statically defined symbols have to live inside one single 2 GiB address range, sitting between absolute addresses-2 GiBand+2 GiB๐ Programs can be statically or dynamically linked. This is the default code model, unless GCC was configured with--with-cmodel=pointing at a different default ๐ง-mcmodel=medany๐ฆ โ generates code for the medium-any code model. The program and its statically defined symbols just need to fit in any single 2 GiB address range. Programs can be statically or dynamically linked โจ
The medium-any code model produces position-independent code, but it is not guaranteed to function correctly when linked into position-independent executables or libraries ๐
-mcmodel=large๐ โ generates code for a large code model with no restrictions on the size or placement of symbols ๐-mexplicit-relocs,-mno-explicit-relocs๐ง โ use or skip assembler relocation operators when dealing with symbolic addresses. The other route is assembler macros, which may limit optimization ๐ฅบ-mrelax,-mno-relaxโญ โ takes advantage of linker relaxations to cut down the number of instructions needed to materialize symbol addresses. The default is to take advantage of them ๐-mriscv-attribute,-mno-riscv-attribute๐ โ emits (or doesn't emit) a RISC-V attribute that records extra info into ELF objects. This feature needs at leastbinutils 2.32๐ซถ-mcsr-check,-mno-csr-check๐ฅ โ enables or disables CSR checking. Simple as that ๐-momit-leaf-frame-pointer๐ฆ โ don't keep the frame pointer in a register for leaf functions. This skips the instructions for saving, setting up, and restoring frame pointers, and frees up an extra register in leaf functions ๐ธ-malign-data=type๐ โ controls how GCC aligns variables and constants of array, structure, or union types. The supported values fortypearexlen, which uses the x register width as the alignment value, andnatural, which uses natural alignment.xlenis the default โจ-mbig-endian๐ โ generates big-endian code. This is the default when GCC is configured for ariscv64be-*-*orriscv32be-*-*target. Heads up, though: support for RISC-V big-endian is experimental ๐
The ABI isn't stable yet, so it could change in incompatible ways in future releases โ ๏ธ
-mlittle-endian๐ โ generates little-endian code. This is the default when GCC is configured for ariscv64-*-*orriscv32-*-*target, but not ariscv64be-*-*orriscv32be-*-*target ๐ง-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset๐ก๏ธ โ generates stack protection code using a canary atguard. The supported locations areglobal(a global canary) ortls(a per-thread canary in the TLS block) ๐งต
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to decide which register is the base register for reading the canary, and what offset from that base register it lives at ๐ฏ There is no default register or offset here, because this is entirely for use within the Linux kernel ๐ง
-mtls-dialect=descโจ โ uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables ๐-mtls-dialect=trad๐ธ โ uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables. This is the default ๐-mrvv-vector-bits=value๐ฆ โ specifies how the number of bits for an RVV vector register (taken from the-march=option) gets interpreted.valueis a string keyword that can bescalableorzvl. The default isscalable, which tells GCC to treat the number as a minimum, whilezvltells GCC to use exactly the number of bits you specified ๐ฅ-mrvv-max-lmul=value๐ โ gives you explicit control over the maximum length multiplier (LMUL) used when generating code for the RISC-V Vector Extensions (RVV).valueis a string keyword that can bem1,m2,m4,m8, ordynamic. The default ism1, for compatibility with existing hardware that doesn't support the other options ๐ซถ-madjust-lmul-cost,-mno-adjust-lmul-cost๐ง โ adjusts the cost model used to schedule vector instructions so the latency of instructions gets multiplied by the RVV length multiplier, LMUL. It's disabled by default ๐-mautovec-segment,-mno-autovec-segment๐ โ enables or disables generation of vector segment load/store instructions. This option is enabled by default โจ
โจ RL78 Options โจ
-msim๐ง โ links in additional target libraries so things can run inside a simulator ๐-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78๐ฅ โ specifies the type of hardware multiplication and division support to use. The simplest one is"none", which uses software for both multiplication and division, and it's the default ๐"g13"is for the hardware multiply/divide peripheral found on the RL78/G13 (S2 core) targets ๐ธ"g14"selects the multiplication and division instructions supported by the RL78/G14 (S3 core) parts โญ The value"rl78"is an alias for"g14", and the value"mg10"is an alias for"none"๐ฆ
In addition, a C preprocessor macro gets defined based on this option's setting. The possible values are "__RL78_MUL_NONE__", "__RL78_MUL_G13__", or "__RL78_MUL_G14__" ๐ง
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78๐ โ specifies the RL78 core to target. The default is the G14 core, also known as an S3 core or just RL78 โจ The G13 (or S2) core doesn't have multiply or divide instructions, and uses a hardware peripheral for those operations instead ๐ ๏ธ The G10 (or S1) core doesn't have register banks, so it uses a different calling convention ๐
If this option is set, it also picks the type of hardware multiply support to use, unless you override it with an explicit -mmul=none on the command line ๐ฏ So -mcpu=g13 turns on the G13 hardware multiply peripheral, and -mcpu=g10 turns off hardware multiplications altogether ๐
Note, though: even though the RL78/G14 core is the default target, specifying -mcpu=g14 or -mcpu=rl78 on the command line does change the toolchain's behavior, because it also enables G14 hardware multiply support ๐ If these options aren't specified on the command line, software multiplication routines get used even though the code targets the RL78 core ๐ข That's for backward compatibility with older toolchains that didn't have hardware multiply and divide support ๐ซถ
In addition, a C preprocessor macro gets defined based on this option's setting. The possible values are "__RL78_G10__", "__RL78_G13__", or "__RL78_G14__" ๐ง
-mg10,-mg13,-mg14,-mrl78๐ฐ๏ธ โ these are aliases for the corresponding-mcpu=option. They're only here for backwards compatibility ๐-mallregs๐ธ โ lets the compiler use all of the available registers. By default, registersr24..r31are reserved for use in interrupt handlers, but with this option enabled, they can be used in ordinary functions too ๐ฅ-mrelax,-mno-relaxโญ โ enables or disables assembler and linker relaxation. This is enabled by default at-Os๐-mes0๐ฆ โ assumes"ES"is zero throughout program execution, and uses it to address read-only data ๐-msave-mduc-in-interrupts,-mno-save-mduc-in-interrupts๐ก๏ธ โ specifies that interrupt handler functions should preserve the MDUC registers. This is only necessary if normal code might use the MDUC registers, for example because it does multiplication and division operations ๐งฎ The default is to ignore the MDUC registers, because that makes the interrupt handlers faster โก The target option-mg13needs to be passed for this to work, since this feature is only available on the G13 target (S2 core) ๐ The MDUC registers only get saved if the interrupt handler performs a multiplication or division operation, or calls another function ๐ซถ
โจ IBM RS/6000 and PowerPC Options โจ
These -m options are defined for the IBM RS/6000 and PowerPC ๐
-mcpu=cpu_type๐ โ sets the architecture type, register usage, and instruction scheduling parameters for the machine typecpu_type. The supported values forcpu_typeare401,403,405,405fp,440,440fp,464,464fp,476,476fp,505,601,602,603,603e,604,604e,620,630,740,7400,7450,750,801,821,823,860,970,8540,a2,e300c2,e300c3,e500mc,e500mc64,e5500,e6500,ec603e,G3,G4,G5,titan,power3,power4,power5,power5+,power6,power6x,power7,power8,power9,power10,power11,powerpc,powerpc64,powerpc64le,rs64, andnative๐
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le specify pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC architecture machine types ๐ง Each one gets an appropriate, generic processor model assumed for scheduling purposes โจ
Specifying native as the cpu type detects and selects the architecture option that matches the host processor of the system doing the compilation ๐ฅ๏ธ -mcpu=native has no effect if GCC doesn't recognize the processor ๐
The other options specify a specific processor ๐ฏ Code generated under those options runs best on that processor, and may not run at all on others ๐
The -mcpu options automatically enable or disable the following options ๐ซถ
-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple -mpopcntb
-mpopcntd -mpowerpc64 -mpowerpc-gpopt -mpowerpc-gfxopt -mmulhw
-mdlmzb -mmfpgpr -mvsx -mcrypto -mhtm -mpower8-fusion
-mquad-memory -mquad-memory-atomic -mfloat128 -mfloat128-hardware
-mprefixed -mpcrel -mmma -mrop-protect
So the exact settings for each CPU can shift between compiler versions ๐
It's whatever looks fastest for that chip, so it doesn't always match what the hardware can actually do ๐คทโโ๏ธ If you want one specific option set to a certain value, just put it after -mcpu, like -mcpu=970 -mno-altivec ๐
On AIX, -mcpu doesn't turn -maltivec or -mpowerpc64 on or off right now, because AIX doesn't fully support those options yet ๐ You can still toggle them yourself if you're sure it'll work in your setup ๐
Honestly? For most cases we'd recommend -mcpu=cpu_type over the switches that control specific instructions. It's the cleaner move ๐ซถ
-mtune=cpu_typeโ Sets the instruction scheduling parameters for the machine typecpu_type, but it leaves the architecture and register usage alone, unlike-mcpu=cpu_typeโจ You use the samecpu_typevalues for-mtuneas you would for-mcpu. If you specify both, the code uses the architecture and registers from-mcpu, but the scheduling comes from-mtune๐ง-mpowerpc64,-mno-powerpc64โ-mpowerpc64lets GCC generate the extra 64-bit instructions from the full PowerPC64 architecture, and treats GPRs as 64-bit doubleword quantities ๐ GCC defaults to-mno-powerpc64๐ธ-mcmodel=smallโ Generates PowerPC64 code for the small model, where the TOC is limited to 64k ๐ฆ-mcmodel=mediumโ Generates PowerPC64 code for the medium model, where the TOC and other static data can total up to 4G ๐ This is the default for 64-bit Linux ๐-mcmodel=largeโ Generates PowerPC64 code for the large model, where the TOC can be up to 4G. Other data and code are only limited by the 64-bit address space ๐-mprofile-kernelโ Only on PowerPC64 GNU/Linux targets. When you use it with-pg, calls to"mcount"get inserted before the function prologue instead of after it ๐ฅ-maltivec,-mno-altivecโ Generates code that does (or doesn't) use AltiVec instructions, and also turns on built-in functions that give you more direct access to the AltiVec instruction set ๐ You might also need-mabi=altivecto adjust the current ABI with the AltiVec ABI enhancements ๐ฆ
When you use-maltivec, the element order for AltiVec intrinsics likevec_splat,vec_extract, andvec_insertmatches the array element order for the target's endianness ๐ญ Element zero is the leftmost element in a vector register on a big-endian target, and the rightmost element in a vector register on a little-endian target.
-mpowerpc-gpopt,-mno-powerpc-gpoptโ Specifying-mpowerpc-gpoptlets GCC use the optional PowerPC instructions in the General Purpose group, including floating-point square root โจ Specifying-mpowerpc-gfxopt,-mno-powerpc-gfxoptโ-mpowerpc-gfxoptlets GCC use the optional PowerPC instructions in the Graphics group, including floating-point select ๐-mmfcrf,-mno-mfcrfโ-mmfcrflets GCC generate the move-from-condition-register-field instruction, which is on the POWER4 and other processors that support PowerPC V2.01 ๐ง-mpopcntb,-mno-popcntbโ-mpopcntblets GCC generate the popcount and double-precision FP reciprocal estimate instruction, which is on the POWER5 and other processors that support PowerPC V2.02 ๐-mpopcntd,-mno-popcntdโ-mpopcntdlets GCC generate the popcount instruction, which is on the POWER7 and other processors that support PowerPC V2.06 ๐-mfprnd,-mno-fprndโ-mfprndlets GCC generate the FP round-to-integer instructions, which are on the POWER5+ and other processors that support PowerPC V2.03 ๐ธ-mcmpb,-mno-cmpbโ-mcmpblets GCC generate the compare bytes instruction, which is on the POWER6 and other processors that support PowerPC V2.05 ๐ฆ-mhard-dfp,-mno-hard-dfpโ-mhard-dfplets GCC generate the decimal floating-point instructions found on some POWER processors ๐-mvrsave,-mno-vrsaveโ Generates VRSAVE instructions when generating AltiVec code ๐-msecure-pltโ Generates code so thatldandld.socan build executables and shared libraries with non-executable".plt"and".got"sections ๐ฅ This is a PowerPC 32-bit SYSV ABI option ๐-mbss-pltโ Generates code that uses a BSS".plt"section thatld.sofills in. It requires".plt"and".got"sections that are both writable and executable ๐ญ This is a PowerPC 32-bit SYSV ABI option ๐-msplit-patch-nopsโ When you add NOPs for a patchable area with the-fpatchable-function-entryoption, this emits the "before" NOPs in front of the global entry point and the "after" NOPs after the local entry point ๐ง That makes the NOP sequence non-consecutive when a global entry point is generated. Without this option, the NOPs go directly before and after the local entry point, so they're consecutive, but the global and local entry points end up further apart ๐ซถ If only a single entry point is generated, this option does nothing โจ-misel,-mno-iselโ This switch enables or disables the generation of ISEL instructions ๐-mvsx,-mno-vsxโ Generates code that does (or doesn't) use vector/scalar (VSX) instructions, and also turns on built-in functions that give you more direct access to the VSX instruction set ๐ฆ-mcrypto,-mno-cryptoโ Enables (or disables) the built-in functions that give direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐-mhtm,-mno-htmโ Enables (or disables) the built-in functions that give direct access to the Hardware Transactional Memory (HTM) instructions added in version 2.07 of the PowerPC ISA ๐ธ-mpower8-fusion,-mno-power8-fusionโ Generates code that keeps some integer operations next to each other, so the instructions can be fused together on power8 and later processors ๐-mquad-memory,-mno-quad-memoryโ Generates code that does (or doesn't) use the non-atomic quad word memory instructions ๐-mquad-memoryrequires 64-bit mode ๐-mquad-memory-atomic,-mno-quad-memory-atomicโ Generates code that does (or doesn't) use the atomic quad word memory instructions ๐ฅ-mquad-memory-atomicrequires 64-bit mode โญ-mfloat128,-mno-float128โ Enables or disables the__float128keyword for IEEE 128-bit floating point, and picks either software emulation or hardware instructions for it ๐
The VSX instruction set (-mvsx) has to be enabled to use IEEE 128-bit floating point support ๐ IEEE 128-bit floating point is only supported on Linux ๐ง
-mfloat128 is enabled by default on PowerPC Linux systems using the VSX instruction set, and disabled on other systems โจ
If you use the ISA 3.0 instruction set (-mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support also enables generation of ISA 3.0 IEEE 128-bit floating point instructions ๐ง Otherwise, if you don't specify ISA 3.0 instruction generation, or you're targeting a 32-bit big-endian system, IEEE 128-bit floating point is handled with software emulation ๐
-mfloat128-hardware,-mno-float128-hardwareโ Enables or disables using ISA 3.0 hardware instructions to support the__float128data type ๐ฆ
-mfloat128-hardware is enabled by default on PowerPC Linux systems using the ISA 3.0 instruction set, and disabled on other systems ๐
-m32,-m64โ Generates code for 32-bit or 64-bit environments of Darwin and SVR4 targets (including GNU/Linux) ๐ The 32-bit environment setsint,long, and pointer to 32 bits, and generates code that runs on any PowerPC variant ๐ The 64-bit environment setsintto 32 bits, andlongand pointer to 64 bits, and generates code for PowerPC64, as for-mpowerpc64๐-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ These modify how the TOC (Table Of Contents) gets generated, which happens for every executable file ๐-mfull-tocis selected by default ๐ In that case, GCC allocates at least one TOC entry for each unique non-automatic variable reference in your program. GCC also puts floating-point constants in the TOC ๐ซถ Heads up: only 16,384 entries are available in the TOC ๐ญ
If the linker throws an error saying you've overflowed the available TOC space, you can shrink the TOC usage with -mno-fp-in-toc and -mno-sum-in-toc ๐ฅ -mno-fp-in-toc stops GCC from putting floating-point constants in the TOC, and -mno-sum-in-toc makes GCC generate code that calculates the sum of an address and a constant at run time, instead of storing that sum in the TOC ๐ง You can use one or both of these. Each one makes GCC produce very slightly slower and larger code, but it saves TOC space ๐ธ
If you're still out of TOC space even with both of those options, try -mminimal-toc instead ๐ It makes GCC create only one TOC entry for every file. The code comes out slower and larger, but it uses extremely little TOC space ๐ You might want to use this only on files with less frequently executed code ๐ฆ
-maix64,-maix32โ Enables the 64-bit AIX ABI and calling convention: 64-bit pointers, a 64-bit"long"type, and the infrastructure needed to support them ๐-maix64implies-mpowerpc64, while-maix32disables the 64-bit ABI and implies-mno-powerpc64โจ GCC defaults to-maix32๐-mxl-compat,-mno-xl-compatโ okay so these make your code act more like IBM XL compiler output when you're using the AIX-compatible ABI ๐ . With-mxl-compat, floating-point args to prototyped functions also go on the stack past the register save area (RSA), on top of the argument FPRs. It also stops assuming the most significant double in a 128-bitlong doubleis properly rounded when comparing and converting todouble, and it uses XL symbol names for thelong doublesupport routines.- The AIX calling convention got extended without any initial docs to cover an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than it declares ๐. IBM XL compilers read floating-point args that don't fit in the RSA from the stack, but only when a subroutine is compiled without optimization.
- Always storing FP args on the stack is inefficient and rarely needed, so this is not on by default. You only need it when calling subroutines built by IBM XL compilers without optimization.
-mpeโ this one's giving IBM RS/6000 SP Parallel Environment (PE) support ๐ง. It links an app that uses message passing with special startup code so it can actually run. Your system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you override the specs file with-specs=to point at the right directory.
The Parallel Environment doesn't support threads, so-mpeand-pthreadare incompatible. Don't pair them, bestie ๐ญ.
-malign-natural,-malign-powerโ on AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux,-malign-naturaloverrides the ABI's alignment for bigger types (like floating-point doubles) and puts them on their natural size-based boundary โจ.-malign-powertells GCC to follow the ABI's alignment rules instead. GCC defaults to the standard ABI alignment.- On 64-bit Darwin, natural alignment is the default, and
-malign-poweris not supported ๐.
- On 64-bit Darwin, natural alignment is the default, and
-msoft-float,-mhard-floatโ-msoft-floatgenerates code that skips the floating-point register set, and-mhard-floatgenerates code that uses it ๐ฆ. With-msoft-float, software floating-point emulation gets provided, but you have to pass the option to GCC when linking too.-mmultiple,-mno-multipleโ-mmultipleuses the load multiple word and store multiple word instructions, and-mno-multipledoesn't. These are generated by default on POWER systems but not on PowerPC systems ๐ธ.
Don't use -mmultiple on little-endian PowerPC systems, because those instructions don't work when the processor is in little-endian mode. The exceptions are PPC740 and PPC750, which allow them in little-endian mode.
-mupdate,-mno-updateโ-mupdateuses the load or store instructions that update the base register to the calculated memory address, and-mno-updateskips them. These are generated by default ๐.
If you use -mno-update, there's a small window between when the stack pointer gets updated and when the address of the previous frame gets stored. That means code that walks the stack frame across interrupts or signals might end up with corrupted data.
-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ-mavoid-indexed-addressestries to avoid indexed load or store instructions, and-mno-avoid-indexed-addressestries not to avoid them ๐ง . Indexed instructions can cost you performance on Power6 processors in certain situations, like stepping through large arrays that cross a 16M boundary. This is enabled by default when targeting Power6 and disabled otherwise.-mfused-madd,-mno-fused-maddโ-mfused-madduses the floating-point multiply and accumulate instructions, and-mno-fused-madddoesn't ๐. These are generated by default when hardware floating point is used.- The machine-dependent
-mfused-maddoption is now mapped to the machine-independent-ffp-contract=fastoption. -mno-fused-maddis mapped to-ffp-contract=off.
- The machine-dependent
-mmulhw,-mno-mulhwโ-mmulhwuses the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors, and-mno-mulhwdoesn't โญ. These are generated by default when targeting those processors.-mdlmzb,-mno-dlmzbโ-mdlmzbuses the string-searchdlmzbinstruction on the IBM 405, 440, 464 and 476 processors, and-mno-dlmzbdoesn't ๐ฅ. This instruction is generated by default when targeting those processors.-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems,-mno-bit-aligndoes not force structures and unions with bit-fields to align to the base type of the bit-field, and-mbit-aligndoes ๐.- For example, by default a struct with nothing but 8
"unsigned"bit-fields of length 1 gets aligned to a 4-byte boundary and ends up 4 bytes in size. With-mno-bit-align, that same struct is aligned to a 1-byte boundary and is just 1 byte. Iconic ๐.
- For example, by default a struct with nothing but 8
-mbit-word,-mno-bit-wordโ allows bit-fields to cross word boundaries ๐.-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems,-mno-strict-aligndoes not assume unaligned memory references are handled by the system, and-mstrict-aligndoes assume that ๐ซถ.-mrelocatable,-mno-relocatableโ-mrelocatablegenerates code that lets a static executable be relocated to a different address at run time, and-mno-relocatabledoesn't allow that ๐ฆ. A simple embedded PowerPC system loader should relocate the entire contents of".got2"and the 4-byte locations listed in the".fixup"section. That's a table of 32-bit addresses this option generates.- For this to work, every object linked together must be compiled with
-mrelocatableor-mrelocatable-lib. -mrelocatablecode aligns the stack to an 8-byte boundary.
- For this to work, every object linked together must be compiled with
-mrelocatable-lib,-mno-relocatable-libโ same vibe as-mrelocatable: it generates a".fixup"section so static executables can be relocated at run time ๐ง. The difference is that-mrelocatable-libdoesn't use the smaller stack alignment that-mrelocatabledoes.- Objects compiled with
-mrelocatable-libcan be linked with objects compiled with any combination of the-mrelocatableoptions ๐.
- Objects compiled with
-mlittle,-mlittle-endianโ on System V.4 and embedded PowerPC systems, this compiles code for the processor in little-endian mode ๐ธ.-mlittle-endianis the same as-mlittle.-mbig,-mbig-endianโ on System V.4 and embedded PowerPC systems, this compiles code for the processor in big-endian mode ๐.-mbig-endianis the same as-mbig.-mdynamic-no-picโ on Darwin / macOS systems, this compiles code so it's not relocatable, but its external references are ๐. The result is suitable for applications, but not shared libraries.-msingle-pic-baseโ this treats the register used for PIC addressing as read-only, instead of loading it in the prologue for each function โจ. The runtime system is responsible for initializing this register with an appropriate value before execution begins.-mprioritize-restricted-insns=priorityโ controls the priority given to dispatch-slot restricted instructions during the second scheduling pass ๐. Thepriorityargument takes0,1, or2, which assigns no, highest, or second-highest (respectively) priority to those instructions.-msched-costly-dep=dependence_typeโ controls which dependences the target considers costly during instruction scheduling ๐ง . Thedependence_typeargument takes one of these values:noโ no dependence is costly.allโ all dependences are costly.true_store_to_loadโ a true dependence from store to load is costly.store_to_loadโ any dependence from store to load is costly.numberโ any dependence whose latency is greater than or equal tonumberis costly.
-minsert-sched-nops=schemeโ controls which NOP insertion scheme gets used during the second scheduling pass ๐ . Theschemeargument takes one of these values:noโ don't insert NOPs.padโ pad with NOPs any dispatch group that has vacant issue slots, according to the scheduler's grouping.regroup_exactโ insert NOPs to force costly dependent insns into separate groups. It inserts exactly as many NOPs as needed to push an insn into a new group, according to the estimated processor grouping.numberโ insert NOPs to force costly dependent insns into separate groups. It insertsnumberNOPs to force an insn into a new group.
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code using calling conventions that follow the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement ๐. This is the default, unless you configured GCC usingpowerpc-*-eabiaix.-mcall-sysv-eabi,-mcall-eabiโ same as specifying both-mcall-sysvand-meabi๐ซถ.-mcall-sysv-noeabiโ same as specifying both-mcall-sysvand-mno-eabi๐ธ.-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐ฆ.-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง.-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐.-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐.-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐.-mtraceback=traceback_typeโ picks the type of traceback table โจ. Valid values fortraceback_typearefull,part, andno.-maix-struct-returnโ returns all structures in memory, as the AIX ABI specifies ๐.-msvr4-struct-returnโ returns structures smaller than 8 bytes in registers, as the SVR4 ABI specifies ๐ฅ.-mabi=abi-typeโ extends the current ABI with a particular extension, or removes one ๐ง. Valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1,elfv2, and, for AIX,vec-extabiandvec-default.-mabi=ibmlongdoubleโ okay bestie, this one flips the ABI over to IBM extended-precisionlong double๐. Heads up, it's not likely to work if your system already defaults to IEEE extended-precisionlong double๐. If you switchlong doubleaway from IEEE extended-precision, the compiler warns you unless you add-Wno-psabi. You also need-mlong-double-128turned on for it to work ๐-mabi=ieeelongdoubleโ the mirror image of the one above โจ. It's switching the ABI to IEEE extended-precisionlong double, and it's probably not going to work if your system defaults to IBM extended-precisionlong double๐. If you changelong doubleaway from IBM extended-precision, you'll get a warning unless you use-Wno-psabi. And yep, you still need-mlong-double-128enabled ๐ฆ-mabi=elfv1โ this sets the ABI to ELFv1, which is the default for big-endian PowerPC 64-bit Linux ๐ธ. Overriding the default needs special system support, and honestly it's likely to fail in spectacular ways ๐ญ-mabi=elfv2โ the ELFv2 ABI, which is the default for little-endian PowerPC 64-bit Linux ๐ง. Same warning applies: overriding it needs special system support and will probably fail in spectacular ways ๐-mgnu-attribute,-mno-gnu-attributeโ this tells GCC to emit.gnu_attributeassembly directives ๐ซถ. Those set tag/value pairs in a.gnu.attributessection, which describe ABI variations in function parameters or return values โจ-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems, this lets you assume every call to a variable argument function is properly prototyped ๐. Without it, GCC has to slip an instruction in before every non-prototyped call to set or clear bit 6 of the condition code register (CR). That bit says whether floating-point values are being passed in the floating-point registers, just in case the function takes variable arguments ๐ค. With-mprototype, only calls to prototyped variable argument functions set or clear that bit ๐-msimโ on embedded PowerPC systems, this assumes the startup module is calledsim-crt0.o, and that the standard C libraries arelibsim.aandlibc.a๐. It's the default forpowerpc-*-eabisimconfigurations ๐-mmvmeโ on embedded PowerPC systems, the startup module iscrt0.oand the standard C libraries arelibmvme.aandlibc.aโญ-madsโ on embedded PowerPC systems, the startup module iscrt0.oand the standard C libraries arelibads.aandlibc.a๐ฅ-myellowknifeโ on embedded PowerPC systems, the startup module iscrt0.oand the standard C libraries arelibyk.aandlibc.a๐ธ-mvxworksโ on System V.4 and embedded PowerPC systems, this tells GCC you're compiling for a VxWorks system ๐ฆ-membโ on embedded PowerPC systems, this sets thePPC_EMBbit in the ELF flags header ๐. That's how you indicate that eabi extended relocations are being used ๐-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems, this either adheres to (-meabi) or doesn't adhere to (-mno-eabi) the Embedded Applications Binary Interface (EABI) ๐ซถ. EABI is basically a set of modifications to the System V.4 specifications, so it's a whole vibe โจ- With
-meabi, the stack is aligned to an 8-byte boundary, a function__eabiis called frommainto set up the EABI environment, and the-msdataoption can use bothr2andr13to point to two separate small data areas ๐ - With
-mno-eabi, the stack is aligned to a 16-byte boundary, no EABI initialization function is called frommain, and the-msdataoption only usesr13to point to a single small data area ๐ - The
-meabioption is on by default if you configured GCC using one of thepowerpc*-*-eabi*options โญ
- With
-msdata=eabiโ on System V.4 and embedded PowerPC systems, small initializedconstglobal and static data goes in the.sdata2section, which is pointed to by registerr2๐. Small initialized non-constglobal and static data goes in the.sdatasection, pointed to by registerr13๐. Small uninitialized global and static data goes in the.sbsssection, which sits right next to.sdata๐ฅ. Heads up,-msdata=eabiis incompatible with-mrelocatable, and it also sets-memb๐-msdata=sysvโ on System V.4 and embedded PowerPC systems, small global and static data goes in the.sdatasection, pointed to by registerr13๐ง. Small uninitialized global and static data goes in.sbss, which is adjacent to.sdata๐ฆ. This one's incompatible with-mrelocatabletoo ๐-msdata=default,-msdataโ on System V.4 and embedded PowerPC systems, if-meabiis used, the code gets compiled the same as-msdata=eabi๐ธ. Otherwise it's compiled the same as-msdata=sysvโจ-msdata=dataโ on System V.4 and embedded PowerPC systems, small global data goes in the.sdatasection ๐ . Small uninitialized global data goes in.sbss๐ซถ. The catch is that registerr13is not used to address small data here ๐. This is the default behaviour unless other-msdataoptions are used ๐-msdata=none,-mno-sdataโ on embedded PowerPC systems, all initialized global and static data goes in the.datasection, and all uninitialized data goes in the.bsssection ๐-mreadonly-in-sdataโ read-only objects get put in the.sdatasection as well ๐. This is the default ๐-mblock-move-inline-limit=numโ this inlines all block moves (like calls tomemcpyor structure copies) that are less than or equal tonumbytes โญ. The minimum value fornumis 32 bytes on 32-bit targets and 64 bytes on 64-bit targets ๐ฅ. The default value depends on the target ๐ธ-mblock-compare-inline-limit=numโ this generates non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal tonumbytes ๐ฆ. Ifnumis0, all inline expansion of block compares is disabled, both the non-loop and loop kinds ๐. The default value depends on the target ๐-mblock-compare-inline-loop-limit=numโ this generates an inline expansion using loop code for all block compares that are less than or equal tonumbytes, but greater than the limit for non-loop inline block compare expansion ๐ง. If the block length isn't constant, at mostnumbytes get compared beforememcmpis called to handle the rest of the block ๐ . The default value depends on the target ๐-mstring-compare-inline-limit=numโ this compares at mostnumstring bytes with inline code ๐ซถ. If the difference or the end of the string isn't found at the end of the inline compare, a call tostrcmporstrncmptakes care of the rest of the comparison ๐. The default is 64 bytes ๐-G numโ on embedded PowerPC systems, global and static items less than or equal tonumbytes go into the small data or BSS sections instead of the normal data or BSS section ๐. By default,numis 8 โจ. The-G numswitch is also passed to the linker ๐. All modules should be compiled with the same-G numvalue, no exceptions ๐ฅ-mregnames,-mno-regnamesโ on System V.4 and embedded PowerPC systems, this does (-mregnames) or doesn't (-mno-regnames) emit register names in the assembly output using symbolic forms ๐-mlongcall,-mno-longcallโ by default, GCC assumes all calls are far away, so it uses a longer and more expensive calling sequence ๐ข. That's required for calls farther than 32 megabytes (33,554,432 bytes) from the current location โญ. A short call only gets generated if the compiler knows the call can't be that far away ๐ฆ. This setting can be overridden by theshortcallfunction attribute, or by#pragma longcall(0)๐- Some linkers can detect out-of-range calls and generate glue code on the fly โจ. On those systems, long calls are unnecessary and generate slower code ๐. As of this writing, the AIX linker can do this, and so can the GNU linker for PowerPC/64 ๐ง. It's planned to add this feature to the GNU linker for 32-bit PowerPC systems as well ๐ธ
- On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see
-mpltseq) ๐ซถ. Heads up, PowerPC with-mbss-pltand PowerPC64 ELFv1 (big-endian) do not support inline PLT calls ๐ - On Darwin/PPC systems,
#pragma longcallgeneratesjbsr callee, L42, plus a branch island (glue code) ๐. The two target addresses represent the callee and the branch island ๐ . The Darwin/PPC linker prefers the first address and generates abl calleeif the PPCblinstruction reaches the callee directly ๐. Otherwise, the linker generatesbl L42to call the branch island ๐. The branch island is appended to the body of the calling function, and it computes the full 32-bit address of the callee and jumps to it ๐ฅ - On Mach-O (Darwin) systems, this option directs the compiler to emit the glue for every direct call, and the Darwin linker decides whether to use it or discard it ๐
- In the future, GCC may ignore all
longcallspecifications when the linker is known to generate glue ๐ฎ
-mpltseq,-mno-pltseqโ this implements (-mpltseq) or doesn't implement (-mno-pltseq)-fno-pltand long calls using an inline PLT call sequence ๐ฆ. That sequence supports lazy linking and long calls to functions indlopen'd shared libraries ๐. Inline PLT calls are only supported on PowerPC64 ELFv2 and on 32-bit PowerPC systems with newer GNU linkers โจ. They're enabled by default if the support is detected when configuring GCC ๐. For 32-bit PowerPC, they're also enabled if GCC is configured with--enable-secureplt๐. Watch out:-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together ๐-mtls-markers,-mno-tls-markersโ this marks (-mtls-markers) or doesn't mark (-mno-tls-markers) calls to__tls_get_addrwith a relocation that specifies the function argument ๐ง. That relocation lets the linker reliably associate the function call with the argument setup instructions for TLS optimization ๐ . In turn, that lets GCC schedule the sequence better ๐ซถ-mrecip,-mno-recipโ okay so this one flips on the reciprocal estimate and reciprocal square root estimate instructions ๐ , plus extra Newton-Raphson steps to win back precision, instead of doing a straight divide (or a square root and then a divide) on floating-point arguments ๐ฆ. Bestie, you should pair-mrecipwith-ffast-math(or at least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math) ๐ซถ. ngl the throughput is usually higher than the non-reciprocal instruction, BUT the precision can drop by up to 2 ulp for reciprocal square roots (like, the inverse of1.0comes out as0.99999994) ๐ญ-mrecip=opt โ this is the picky version ๐ where you choose which reciprocal estimate instructions get to show up. opt is a comma-separated list, and you can put a "!" in front of any option to invert it ๐allโ enable all estimate instructions โจdefaultโ enable the default instructions, same as-mrecip๐ธnoneโ disable all estimate instructions, same as-mno-recip๐divโ enable the reciprocal approximation instructions for both single and double precision ๐divfโ enable the single-precision reciprocal approximation instructions ๐งdivdโ enable the double-precision reciprocal approximation instructions ๐rsqrtโ enable the reciprocal square root approximation instructions for both single and double precision ๐rsqrtfโ enable the single-precision reciprocal square root approximation instructions ๐ฆrsqrtdโ enable the double-precision reciprocal square root approximation instructions ๐
So, for example, -mrecip=all,!rsqrtd turns on every reciprocal estimate instruction except for FRSQRTE, XSRSQRTEDP, and XVRSQRTEDP, which are the ones handling double-precision reciprocal square root math ๐ฅ
-mrecip-precision,-mno-recip-precisionโ this one lets GCC assume (or not assume ๐) that the reciprocal estimate instructions are more precise than the PowerPC ABI actually requires. Picking-mcpu=power6,-mcpu=power7or-mcpu=power8automatically selects-mrecip-precisionfor you โจ. Also, the double-precision square root estimate instructions are NOT generated by default on low-precision machines, because they don't converge after three steps ๐-mveclibabi=type โ this sets the ABI type used when vectorizing intrinsics with an external library ๐ง. The only type supported right now ismass, which tells GCC to use IBM's Mathematical Acceleration Subsystem (MASS) libraries for that job ๐ . GCC currently emits calls to the following when generating code for power7 ๐ซถ:
acosd2, acosf4, acoshd2, acoshf4, asind2, asinf4, asinhd2, asinhf4,
atan2d2, atan2f4, atand2, atanf4, atanhd2, atanhf4, cbrtd2, cbrtf4,
cosd2, cosf4, coshd2, coshf4, erfcd2, erfcf4, erfd2, erff4,
exp2d2, exp2f4, expd2, expf4, expm1d2, expm1f4, hypotd2, hypotf4,
lgammad2, lgammaf4, log10d2, log10f4, log1pd2, log1pf4, log2d2, log2f4,
logd2, logf4, powd2, powf4, sind2, sinf4, sinhd2, sinhf4,
sqrtd2, sqrtf4, tand2, tanf4, tanhd2, tanhf4
Both -ftree-vectorize and -funsafe-math-optimizations must ALSO be enabled ๐ฅ, and the MASS libraries must be specified at link time ๐
-mfriz,-mno-frizโ okay so this decides whether GCC generates thefrizinstruction when-funsafe-math-optimizationsis used to speed up rounding floating-point values to 64-bit integers and back to floating point ๐ธ
Warning, bestie ๐ญ the friz instruction does NOT return the same value if the floating-point number is too large to fit in an integer.
-mpointers-to-nested-functions,-mno-pointers-to-nested-functionsโ this controls whether GCC generates code that loads up the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems ๐ง. On those systems a function pointer points to a 3-word descriptor that gives the function address, the TOC value to load into registerr2, and the static chain value to load into registerr11๐.-mpointers-to-nested-functionsis on by default ๐
Heads up, bestie ๐ if you use -mno-pointers-to-nested-functions, you can't call through pointers to nested functions, or through pointers to functions compiled in other languages that use the static chain.
-msave-toc-indirect,-mno-save-toc-indirectโ this generates (or doesn't generate ๐) code that saves the TOC value in the reserved stack location in the function prologue, if the function calls through a pointer on AIX and 64-bit Linux systems โจ. If the TOC value isn't saved in the prologue, it gets saved just before the call through the pointer ๐ฆ. The-mno-save-toc-indirectoption is the default ๐-mcompat-align-parm,-mno-compat-align-parmโ this generates (or doesn't generate) code that passes structure parameters with a maximum alignment of 64 bits, so it matches older versions of GCC ๐
Older versions of GCC (prior to 4.9.0) incorrectly did not align a structure parameter on a 128-bit boundary when that structure had a member needing 128-bit alignment ๐ญ. This got fixed in more recent versions of GCC, but this option can help you make code that plays nicely with functions compiled by those older versions ๐ซถ
The -mno-compat-align-parm option is the default ๐ธ
-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset โ these generate stack protection code using a canary at guard ๐ฅ. The supported locations areglobal(a global canary) ortls(a per-thread canary in the TLS block, which is the default with GNU libc version 2.4 or later) ๐
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to decide which register is used as the base register for reading the canary, and what offset from that base register to use ๐
. The defaults for those are whatever the relevant ABI specifies โจ
-mpcrel,-mno-pcrelโ this generates (or doesn't generate ๐) pc-relative addressing ๐ฆ. The-mpcreloption requires that the medium code model (-mcmodel=medium) AND prefixed addressing (-mprefixed) options are enabled ๐ซถ-mprefixed,-mno-prefixedโ this generates (or doesn't generate) addressing modes that use prefixed load and store instructions ๐ง. The-mprefixedoption requires that-mcpu=power10(or later) is enabled ๐-mmma,-mno-mmaโ this generates (or doesn't generate) the MMA instructions ๐. The-mmaoption requires that-mcpu=power10(or later) is enabled ๐ฅ-mrop-protect,-mno-rop-protectโ this generates (or doesn't generate) ROP protection instructions when the target processor supports them ๐ก๏ธ Currently, this option disables the shrink-wrap optimization (-fshrink-wrap) ๐-mprivileged,-mno-privilegedโ this generates (or doesn't generate) code that runs in privileged state ๐-mblock-ops-unaligned-vsx,-mno-block-ops-unaligned-vsxโ this generates (or doesn't generate) unaligned VSX loads and stores for inline expansion ofmemcpyandmemmoveโจ-msplat-word-constant,-mno-splat-word-constantโ this generates (or doesn't generate) code that uses theXXSPLTIWinstruction ๐ธ. This option is enabled by default ๐-msplat-float-constant,-mno-splat-float-constantโ this generates (or doesn't generate) code that uses theXXSPLTIDPinstruction ๐ฆ. This option is enabled by default ๐-mieee128-constant,-mno-ieee128-constantโ this generates (or doesn't generate) code that uses theLXVKQinstruction ๐ง. This option is enabled by default ๐ซถ-mwarn-altivec-long,-mno-warn-altivec-longโ this turns warnings on or off about deprecated vector long ... Altivec type usage โ ๏ธ This option is enabled by default ๐
๐ฆ RX Options ๐ฆ
These command-line options are defined for RX targets ๐
-m64bit-doubles,-m32bit-doublesโ this makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size ๐ The default is-m32bit-doubles. Note that RX floating-point hardware only works on 32-bit values, which is exactly why the default is-m32bit-doubles๐-fpu,-nofpuโ this enables (-fpu) or disables (-nofpu) the use of RX floating-point hardware ๐ฅ The default is enabled for the RX600 series and disabled for the RX200 series ๐
Floating-point instructions are only generated for 32-bit floating-point values, though, so the FPU hardware is not used for doubles if the -m64bit-doubles option is used ๐
Note: if the-fpuoption is enabled, then-funsafe-math-optimizationsis also enabled automatically ๐ญ This is because the RX FPU instructions are themselves unsafe.
-mcpu=name โ this selects the type of RX CPU to target ๐ง Right now three types are supported: the generic RX600 and RX200 series hardware, and the specific RX610 CPU ๐ The default is RX600.
The only difference between RX600 and RX610 is that the RX610 does not support the MVTIPL instruction ๐ธ
The RX200 series does not have a hardware floating-point unit, so -nofpu is enabled by default when this type is selected ๐ซถ
-mbig-endian-data,-mlittle-endian-dataโ this stores data (but NOT code) in the big-endian format ๐ The default is-mlittle-endian-data, which means data is stored in the little-endian format ๐-msmall-data-limit=N โ this specifies the maximum size in bytes of global and static variables that can be placed into the small data area โจ Using the small data area can lead to smaller and faster code ๐ฆ, BUT the size of the area is limited and it's up to the programmer to make sure the area doesn't overflow ๐ญ
Also, when the small data area is used, one of the RX's registers (usually r13) is reserved for pointing to this area, so the compiler can't use it anymore ๐
This could result in slower and/or larger code if variables get pushed onto the stack instead of being held in that register ๐
Note, bestie: common variables (variables that have not been initialized) and constants are NOT placed into the small data area, because they get assigned to other sections in the output executable ๐ซถ
okay so the default value is zero, which disables this feature ๐
โโ๏ธ and bestie, it is not switched on by default at higher optimization levels (-O2 etc) because reserving a register can be kinda detrimental ๐ฌ. It's up to you to experiment and see whether it actually helps your program โจ. Peep the -mpid description for how the register holding the small data area pointer gets picked ๐ง
-msim,-mno-simโ Use the simulator runtime ๐ฎ. The default is the libgloss board-specific runtime.-mas100-syntax,-mno-as100-syntaxโ When GCC spits out assembler output, this makes it use a syntax that plays nice with Renesas's AS100 assembler ๐งธ. GAS can read it too, but it has some restrictions, so it is not generated by default ๐-mmax-constant-size=Nโ Sets the biggest a constant can be (in bytes) and still be used as an operand in an RX instruction ๐. RX instructions can take constants up to 4 bytes, but a longer value means a longer instruction, so sometimes it's lowkey beneficial to restrict this ๐ . Constants that are too big get tossed into a constant pool and referenced through register indirection ๐ซถ
N can be between 0 and 4. A value of 0 (the default) or 4 means constants of any size are allowed โจ
-mrelaxโ Turns on linker relaxation ๐ฆ. The linker tries to shrink your program by finding shorter versions of various instructions. It's disabled by default.-mint-register=Nโ Reserves registers for fast interrupt handler functions ๐.Ncan be between0and4:1reserves"r13"for the exclusive use of fast interrupt handlers2reserves"r13"and"r12"3reserves"r13","r12"and"r11"4reserves"r13"through"r10"0, the default, reserves nothing ๐ธ
-msave-acc-in-interruptsโ Tells interrupt handlers to preserve the accumulator register ๐ฅ. This is only needed if normal code might use the accumulator, like when it does 64-bit multiplications. The default is to ignore the accumulator, because that keeps the interrupt handlers faster โก-mpid,-mno-pidโ Enables position-independent data ๐งโโ๏ธ. When it's on, any access to constant data happens via an offset from a base address held in a register. This lets the location of constant data get figured out at run time without the executable needing to be relocated, which is a huge win for embedded apps with tight memory constraints ๐
Heads up, this reserves a register (usually "r13") for the constant data base address ๐ญ. That can make code slower and/or bigger, especially in complicated functions.
Which register ends up holding that base address depends on whether -msmall-data-limit and/or -mint-register are on. Starting at "r13" and working downwards, registers get allocated first for -mint-register, then -mpid, and finally -msmall-data-limit. So the small data area register can be "r8" if both -mint-register=4 and -mpid are specified on the command line ๐
By default this feature is not enabled. You can restore the default with -mno-pid ๐
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interruptsโ Stops GCC from yelling with a warning if it finds more than one fast interrupt handler while compiling a file ๐ฃ. The default is to warn for each extra fast interrupt handler, since the RX only supports one of them ๐-mallow-string-insns,-mno-allow-string-insnsโ Turns the string manipulation instructions"SMOVF","SCMPU","SMOVB","SMOVU","SUNTIL""SWHILE"and also the"RMPA"instruction on or off ๐งต. These can prefetch data, which is not safe if you're touching an I/O register ๐ฑ (see section 12.2.7 of the RX62N Group User's Manual for more info).
The default is to allow them. GCC can't reliably detect every situation where a string instruction might touch an I/O register, so it can't turn them off automatically. It's on you to use -mno-allow-string-insns if your program accesses I/O space ๐ซถ
When these instructions are enabled, GCC defines the C preprocessor symbol"__RX_ALLOW_STRING_INSNS__". Otherwise it defines"__RX_DISALLOW_STRING_INSNS__"๐จ
-mjsr,-mno-jsrโ Use only (or not only)"JSR"instructions to access functions ๐งญ. This can help when your code size goes beyond the range of"BSR"instructions. Note that-mno-jsrdoesn't mean "don't useJSR" ๐ โโ๏ธ. It just means any type of branch may be used.-mlraโ Uses the new LRA register allocator ๐. By default the old"reload"allocator is used.
Note: the generic GCC command-line option -ffixed-reg has special significance for the RX port when used with the "interrupt" function attribute ๐ซ. That attribute marks a function meant to process fast interrupts. GCC makes sure it only uses the registers "r10", "r11", "r12" and/or "r13", and only when the normal use of those registers has been restricted with -ffixed-reg or -mint-register ๐
๐ธ S/390 and zSeries Options ๐ธ
These are the -m options defined for the S/390 and zSeries architecture ๐ง
-mhard-float,-msoft-floatโ Use (or don't use) the hardware floating-point instructions and registers for floating-point operations ๐ข. With-msoft-float, functions inlibgcc.ado the floating-point work. With-mhard-float, the compiler generates IEEE floating-point instructions. This is the default โจ-mhard-dfp,-mno-hard-dfpโ Use (or don't use) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐งฎ. With-mno-hard-dfp, functions inlibgcc.ahandle decimal-floating-point operations. With-mhard-dfp, the compiler generates decimal-floating-point hardware instructions. This is the default for-march=z9-ecor higher ๐ฆ-mlong-double-64,-mlong-double-128โ These switches control the size of the"long double"type ๐. A size of 64 bits makes"long double"equivalent to"double". This is the default ๐-mbackchain,-mno-backchainโ Stores (or doesn't store) the address of the caller's frame as a backchain pointer in the callee's stack frame ๐. A backchain may be needed to debug with tools that don't understand DWARF call frame information ๐. When-mno-packed-stackis in effect, the backchain pointer is stored at the bottom of the stack frame. When-mpacked-stackis in effect, the backchain goes into the topmost word of the 96/160 byte register save area ๐
Code compiled with -mbackchain is call-compatible with code compiled with -mno-backchain. However, using the backchain for debugging usually requires the whole binary to be built with -mbackchain ๐
The combination of-mbackchain,-mpacked-stackand-mhard-floatis not supported ๐. To build a Linux kernel, use-msoft-float.
The default is to not maintain the backchain.
-mpacked-stack,-mno-packed-stackโ Uses (or doesn't use) the packed stack layout ๐ฆ. With-mno-packed-stack, the compiler uses all the fields of the 96/160 byte register save area only for their default purpose, so unused fields still take up stack space ๐ค. With-mpacked-stack, register save slots are densely packed at the top of the register save area, and unused space gets reused for other purposes, which is much more efficient with the stack space ๐
When -mbackchain is also in effect, the topmost word of the save area is always used to store the backchain, and the return address register is always saved two words below the backchain ๐ซถ
As long as the stack frame backchain isn't used, code generated with -mpacked-stack is call-compatible with code generated with -mno-packed-stack. Heads up though: some non-FSF releases of GCC 2.95 for S/390 or zSeries generated code that uses the stack frame backchain at run time, not just for debugging. That code is not call-compatible with code compiled with -mpacked-stack ๐ฌ. Also, the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported. To build a Linux kernel, use -msoft-float.
The default is to not use the packed stack layout.
-msmall-exec,-mno-small-execโ Generates (or doesn't generate) code that uses the"bras"instruction for subroutine calls ๐. This only works reliably if the total executable size doesn't go over 64k ๐ซ. The default is to use the"basr"instruction instead, which doesn't have that limitation ๐-m64,-m31โ With-m31, GCC generates code compliant with the GNU/Linux for S/390 ABI ๐ฅ๏ธ. With-m64, it generates code compliant with the GNU/Linux for zSeries ABI. This lets GCC generate 64-bit instructions ๐. For the s390 targets the default is-m31, while the s390x targets default to-m64โจ
-m31 is deprecated and support will be removed ๐ญ
-mzarch,-mesaโ With-mzarch, GCC generates code using the instructions available on z/Architecture ๐. With-mesa, it generates code using the instructions available on ESA/390. Note that-mesais not possible with-m64๐ โโ๏ธ. When generating code compliant with the GNU/Linux for S/390 ABI, the default is-mesa. When generating code compliant with the GNU/Linux for zSeries ABI, the default is-mzarch๐-mhtm,-mno-htmโ โจ okay so-mhtmunlocks a set of S/390 System z Built-in Functions that use instructions from the transactional execution facility, introduced with the IBM zEnterprise EC12 machine generation ๐ง. It's on by default when you use-march=zEC12๐.-mvx,-mno-vxโ bestie,-mvxmakes GCC generate code with the vector extension facility from the IBM z13 machine generation ๐ฆ. It also changes the ABI for some vector type values when it comes to alignment and calling conventions ๐. If vector types show up somewhere ABI-relevant, GCC adds a GAS.gnu_attributecommand so the binary is marked with the ABI it used ๐.-mvxis on by default with-march=z13โจ.-mzvector,-mno-zvectorโ this one is giving vector language extensions ๐ .-mzvectorturns on vector language extensions and builtins using the z13 vector extension facility, and it lets you usevectoras a keyword for vector type variables and arguments ๐. Heads up:vectoronly works when GNU extensions are on, and it's not expanded when you ask for strict standard compliance, like with-std=c99๐. On top of the GCC low-level builtins,-mzvectoralso adds builtins for compatibility with AltiVec-style implementations like Power and Cell ๐. To actually use them, you have to include the header filevecintrin.h๐.-mzvectoris disabled by default ๐ซถ.-mmvcle,-mno-mvcleโ-mmvcletells GCC to generate code that uses themvcleinstruction for block moves ๐. With-mno-mvcle, it uses anmvcloop instead ๐. This is the default unless you're optimizing for size ๐ธ.-mdebug,-mno-debugโ-mdebugmakes the compiler print extra debug info while it compiles ๐.-mno-debugkeeps it quiet, and quiet is the default ๐คซ.-march=cpu-typeโ the big one ๐. This generates code that runs on cpu-type, which is the name of a system representing a certain processor type โญ. The possible values arez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12,z15/arch13,z16/arch14,z17/arch15, andnative๐ง.
The default is -march=z900 ๐.
Using native as the cpu type picks the best architecture option for your host processor ๐. Just know that -march=native does nothing if GCC doesn't recognize the processor ๐.
-mtune=cpu-typeโ-mtunetells GCC to tune everything applicable in the generated code to cpu-type ๐ฏ. The one exception is the ABI and the set of available instructions, which it leaves alone ๐ โโ๏ธ. The list of values is the same as for-marchโจ. The default is whatever value was used for-march๐ .-mtpf-trace,-mno-tpf-traceโ-mtpf-tracemakes GCC add TPF OS specific branches to trace routines in the operating system ๐ฐ๏ธ.-mno-tpf-traceskips adding them. This option is off by default, even when you're compiling for TPF OS ๐.-mtpf-trace-skip,-mno-tpf-trace-skipโ-mtpf-trace-skipchanges the default branch targets enabled by-mtpf-traceso they point at specialized trace routines ๐ฏ. These let you selectively skip function trace entries for TPF OS ๐ฆ.-mno-tpf-trace-skipleaves those targets alone. This is also off by default, even when you're compiling for TPF OS and passing-mtpf-trace๐ญ.-mmainโ for the TPF OS target, use this one when linking ๐. It adds the startup code and other linker options so you get a main object ๐.-mfused-madd,-mno-fused-maddโ-mfused-maddmakes GCC use the floating-point multiply and accumulate instructions โโ๏ธ.-mno-fused-maddtells it not to ๐ โโ๏ธ. These instructions get generated by default when hardware floating point is in use ๐.-mwarn-framesize=framesizeโ this one's a little warning guard ๐จ. It makes GCC emit a warning if the current function goes over the frame size you give it ๐. It's a compile-time check, so it doesn't have to be a real problem when the program runs ๐ซถ. It's meant to flag functions that will most likely cause a stack overflow ๐. It's super useful in environments with a limited stack size, like the Linux kernel ๐ง. A value of zero turns this warning off, and zero is the default ๐ธ.-mwarn-dynamicstack,-mno-warn-dynamicstackโ-mwarn-dynamicstackmakes GCC warn if a function callsallocaor uses dynamically-sized arrays โ ๏ธ. This is generally a bad idea when the stack size is limited ๐.-mno-warn-dynamicstackturns the warning off.-mstack-guard=stack-guard,-mstack-size=stack-size,-mno-stack-guard,-mno-stack-sizeโ these are the stack overflow detectives ๐ต๏ธโโ๏ธ. When they're enabled, the S/390 back end adds extra instructions to the function prologue that trigger a trap if the stack goes stack-guard bytes above stack-size ๐ชค. (Remember, the stack on S/390 grows downward โฌ๏ธ.) If you leave outstack-guard, GCC picks the smallest power of 2 that's larger than the frame size of the compiled function ๐งฎ.
These are meant for debugging stack overflow problems ๐ง. The extra code only adds a little overhead, so it can run on production-like systems without a big performance hit ๐.
Some rules, bestie: the given values have to be exact powers of 2, and stack-size has to be greater than stack-guard without going over 64k ๐ซ. To be efficient, the extra code assumes the stack starts at an address aligned to the value given by stack-size ๐. The -mstack-guard= option only works together with -mstack-size= ๐ซ. You can override these on the command line with -mno-stack-guard and -mno-stack-size, respectively ๐ฆ.
-mhotpatch=pre-halfwords,post-halfwordsโ if hotpatch is enabled, GCC generates a "hot-patching" function prologue for every function in the compilation unit ๐ฅ. The function label gets prepended with the given number of two-byte NOP instructions (pre-halfwords, max1000000) ๐ซง. After the label,2 * post-halfwordsbytes get appended, using the largest NOP-like instructions the architecture allows (max1000000) ๐งฉ.
If both arguments are zero, hotpatching is disabled ๐
โโ๏ธ. You can override this for individual functions with the hotpatch attribute โจ.
-mpic-data-is-text-relative,-mno-pic-data-is-text-relativeโ when you compile for S/390 with-fpicor-fPIC, GCC normally uses relative addressing between code and data ๐บ๏ธ. But for hotpatching, you might need to add new.textparts while still using the existing.dataand.bsssections ๐ง . In that case, use-mno-pic-data-is-text-relativeto force addressing through the GOT instead ๐.-mstack-protector-guard=guardโ this generates stack protection code using a canary at guard ๐ค. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default) ๐งต.-mstack-protector-guard-recordโ this one results in a section called__stack_protector_locthat holds pointers to every instruction that loads the address of the global guard ๐. So it only does something alongside-mstack-protector-guard=global๐ซถ. It's intended for the Linux kernel ๐ง.-mindirect-branch=choice,-mindirect-branch-jump=choice,-mindirect-branch-call=choice,-mfunction-return=choice,-mfunction-return-mem=choice,-mfunction-return-reg=choiceโ this whole group is about security ๐ก๏ธ. It deals with vulnerabilities around speculative execution and indirect branch prediction by swapping indirect branches and function returns for direct branches to a thunk ๐งตโจ.
Here's how the choice values work, bestie ๐ :
keepgives you the default code.thunkgenerates out-of-line thunks and replaces the old indirect branch with a direct branch to the thunk.thunk-externdoes the same branch replacement asthunk, but doesn't emit the thunks ๐ซฅ.thunk-inlineis only available with-mindirect-branch-jump. You should prefer it overthunkin user-space applications, since it keeps stack unwinding and exception handling correct ๐ง .
-mindirect-branch sets both -mindirect-branch-jump and -mindirect-branch-call ๐. -mfunction-return sets both -mfunction-return-reg and -mfunction-return-mem ๐. And you can set all of these per function using function attributes ๐ฏ.
-mindirect-branch-table,-mno-indirect-branch-tableโ this is a team player ๐ค. It works with-mindirect-branchand-mfunction-return. When enabled, it generates tables pointing to the branch locations those options patched ๐๏ธ. The tables live in sections named.s390_indirect_jump,.s390_indirect_call,.s390_return_reg, and.s390_return_mem๐ฆ. Each section is an array of 32-bit elements, and each entry holds the offset from the entry to the patched location ๐ข.-mfentry,-mno-fentryโ used together with-pg,-mfentryemits profiling code using the__fentry__hook that GLIBC 2.29 or later provides ๐. This is only available for 64-bit code ๐ป. If you don't enable it, profiling falls back to the less efficient_mcounthook ๐ข.-mrecord-mcount,-mno-record-mcountโ when enabled, GCC generates a__mcount_locsection that holds the locations of all the generated profiling calls to_mcountor__fentry__๐.mnop-mcount,mno-nop-mcountโ instead of generating calls to_mcountor__fentry__with-pg, this inserts a sequence of no-op instructions of the same length right where those calls would have gone ๐ด. Pair it with-mrecord-mcountand you can patch the call sequences into the object file without recompiling it ๐งฉโจ.-mpreserve-args,-mno-preserve-argsโ when enabled, GCC saves all the argument registers to the stack and generates the matching CFI information ๐๏ธ. This is handy for apps that want to build their own stack unwinding and need access to function arguments ๐ซถ.-munaligned-symbols,-mno-unaligned-symbolsโ this tells GCC to assume that external symbols with a natural alignment of 1 might be unaligned ๐. By default, every symbol without explicit alignment is assumed to be aligned on a 2-byte boundary, as the IBM Z ABI requires ๐.
๐ฆ SH Options
These -m options are defined for the SH implementations ๐.
-m1โ generates code for the SH1 ๐.-m2โ generates code for the SH2 ๐ธ.-m2eโ generates code for the SH2e โจ.-m2a-nofpuโ okay bestie, this one is for the SH2a, or an SH2a-FPU that you want to act like it has no FPU ๐ฆ. The floating-point unit never gets used.-m2a-single-onlyโ SH2a-FPU code that never does double-precision floating-point math. Very single-precision core ๐.-m2a-singleโ SH2a-FPU code that assumes the FPU starts out in single-precision mode โจ.-m2aโ SH2a-FPU code that assumes the FPU starts out in double-precision mode ๐.-m3โ SH3 code, plain and simple ๐ธ.-m3eโ SH3e code ๐ง.-m4-nofpuโ SH4 code with no floating-point unit at all ๐ซถ.-m4-single-onlyโ SH4 code for a floating-point unit that can only do single-precision arithmetic ๐ .-m4-singleโ SH4 code that assumes the FPU is in single-precision mode by default ๐.-m4โ SH4 code, the classic ๐.-m4-100โ SH4-100 code ๐.-m4-100-nofpuโ SH4-100 code that keeps the floating-point unit out of it completely ๐.-m4-100-singleโ SH4-100 code that assumes the FPU is in single-precision mode by default โญ.-m4-100-single-onlyโ SH4-100 code where no double-precision floating-point operations sneak in ๐ฅ.-m4-200โ SH4-200 code ๐.-m4-200-nofpuโ SH4-200 code, written so the floating-point unit is not used. The wording in the original is a bit garbled here, but the vibe is "no FPU, please" ๐.-m4-200-singleโ SH4-200 code that assumes the FPU is in single-precision mode by default ๐ฆ.-m4-200-single-onlyโ SH4-200 code where no double-precision floating-point operations are used ๐ธ.-m4-300โ SH4-300 code ๐ง.-m4-300-nofpuโ SH4-300 code, again written so the floating-point unit is not used. Same little wording glitch as the SH4-200 one ๐.-m4-300-singleโ SH4-300 code where no double-precision floating-point operations are used. Yes, the original says exactly that, so we're keeping it ๐ซถ.-m4-300-single-onlyโ SH4-300 code where no double-precision floating-point operations are used. Same as the one right above it, periodt ๐ .-m4-340โ SH4-340 code. No MMU, no FPU, very minimal, very iconic โจ.-m4-400โ SH4-400 code. Also no MMU and no FPU ๐.-m4-500โ SH4-500 code with no FPU ๐ฅ. It also passes-isa=sh4-nofputo the assembler, so the assembler knows the deal too ๐ง.-m4a-nofpuโ code for the SH4al-dsp, or for an SH4a that doesn't touch the floating-point unit ๐.-m4a-single-onlyโ SH4a code where no double-precision floating-point operations are used ๐.-m4a-singleโ SH4a code that assumes the FPU is in single-precision mode by default ๐.-m4aโ SH4a code ๐.-m4alโ basically the same as-m4a-nofpu, except it also quietly passes-dspto the assembler. Also, GCC doesn't generate any DSP instructions right now, so that part is more of a heads-up than a feature ๐.-mbโ compiles for big-endian mode ๐.-mlโ compiles for little-endian mode ๐.-mdalignโ aligns doubles on 64-bit boundaries ๐. Heads up though: this changes the calling conventions, so some standard C library functions won't work unless you recompile them with-mdalignfirst. Not a vibe, that's a warning โ ๏ธ.
Heads up:-mdalignchanges the calling conventions, so standard C library functions that weren't recompiled with-mdalignmay break. Recompile first, bestie ๐.
-mrelaxโ shortens some address references at link time when it's possible, and it does this by using the linker option-relax๐ฆ.-mbigtableโ uses 32-bit offsets in"switch"tables. The default is 16-bit offsets, so this one is the upgrade ๐ง.-mbitopsโ turns on bit manipulation instructions on SH2A ๐ .-mfmovdโ turns on thefmovdinstruction ๐ธ. Check-mdalignfor the alignment rules that come with it ๐ซถ.-mrenesas,-mno-renesasโ-mrenesasmakes the compiler follow the calling conventions defined by Renesas ๐. The default for every SH toolchain target is-mno-renesas, which uses the calling conventions GCC had before the Renesas ones existed โจ.-mnomacsaveโ marks the"MAC"register as call-clobbered, even when-mrenesasis also given ๐.-mieee,-mno-ieeeโ these control how IEEE compliant floating-point comparisons are, which affects what happens when a comparison result is unordered ๐ฅ.-mieeeis implicitly on by default. If-ffinite-math-onlyis on,-mno-ieeegets implicitly set, and that makes floating-point greater-equal and less-equal comparisons faster โญ. You can override the implicit setting by explicitly passing either-mieeeor-mno-ieee๐ .-minline-ic_invalidate,-mno-inline-ic_invalidateโ inlines code that invalidates instruction cache entries after setting up nested function trampolines ๐ง. This option does nothing if-musermodeis in effect and your code generation option (like-m4) doesn't allow theicbiinstruction ๐. If the code generation option doesn't allowicbiand-musermodeisn't in effect, the inlined code pokes the instruction cache address array directly with an associative write. That needs privileged mode at run time, and it also breaks if the cache line was mapped through the TLB and has since become unmapped ๐.-misizeโ dumps instruction size and location into the assembly code ๐.-matomic-model=modelโ sets the model for atomic operations, plus any extra parameters, as a comma-separated list ๐. For the full scoop on atomic built-in functions, check__atomic Builtins. These are the models and parameters you can pick from:noneโ turns off compiler-generated atomic sequences and emits library calls for atomic operations instead ๐ซถ. This is the default when the target isn'tsh*-*-linux*.soft-gusaโ generates GNU/Linux-compatible gUSA software atomic sequences for the atomic built-ins ๐ฆ. These need extra help from the system's interrupt and exception handling code, and they're only good for single-core SH3* and SH4* systems ๐. This option is on by default when the target issh*-*-linux*and the chip is SH3* or SH4*. When the target is SH4A, it also partly uses the hardware atomic instructionsmovli.landmovco.lto make the code faster, unless you specifystrict๐ฅ.soft-tcbโ generates software atomic sequences that use a variable in the thread control block โญ. It's basically a variation of gUSA sequences that also works on SH1* and SH2* targets ๐ธ. These sequences also need extra help from the interrupt and exception handling code, and they're only suitable for single-core systems ๐. When you use this model, you have to specify thegbr-offset=parameter too ๐ง.soft-imaskโ generates software atomic sequences that temporarily turn interrupts off by settingSR.IMASK = 1111๐. This model only works when the program runs in privileged mode, and it's only for single-core systems ๐ . It doesn't need extra help from the system's interrupt and exception handling code ๐ซถ. It's on by default when the target issh*-*-linux*and the chip is SH1* or SH2* ๐.hard-llcsโ generates hardware atomic sequences using only themovli.landmovco.linstructions ๐. It's only available on SH4A and is good for multi-core systems ๐. Those hardware instructions only support 32-bit atomic variables, so 8-bit and 16-bit access gets emulated with 32-bit accesses ๐ฅ. Code built with this option is still compatible with other software atomic model interrupt and exception handling systems, as long as it runs on an SH4A system โจ. It doesn't need any extra help from the system's interrupt and exception handling code ๐ฆ.gbr-offset=โ this parameter sets the offset in bytes of the variable in the thread control block structure that the generated atomic sequences use whensoft-tcbis picked ๐ง. For other models it gets ignored ๐. The value has to be an integer multiple of four and in the range 0-1020 ๐.strictโ stops you from mixing multiple atomic models, even if they'd be compatible, and makes the compiler generate atomic sequences for only the model you specified ๐.
-mtasโ generates thetas.bopcode for__atomic_test_and_set๐ฅ. Heads up, this can hurt overall performance depending on your hardware and software setup, becausetas.bforces operand cache line flushes โ ๏ธ. On multi-core SH4A processors,tas.bhas to be used with real caution, since it can corrupt data with certain cache configurations ๐.-mprefergotโ when generating position-independent code, makes function calls go through the Global Offset Table instead of the Procedure Linkage Table ๐ธ.-musermode,-mno-usermodeโ-musermodestops the compiler from generating privileged mode code, and-mno-usermodelets it do so ๐.-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode ๐.-musermodeis the default when the target issh*-*-linux*๐ซถ. If the target is SH1* or SH2*,-musermodedoes nothing, because those chips have no user mode ๐ .-multcost=numberโ sets the cost the compiler assumes for a multiply instruction ๐งฎ.-mdiv=strategyโ picks the division strategy for integer division operations ๐. Thestrategycan be one of these:call-div1โ calls a library function that does the operation with the single-step division instructiondiv1๐. Dividing by zero gives an unspecified result and doesn't trap ๐. This is the default, except for SH4, SH2A and SHcompact โจ.call-fpโ calls a library function that does the operation in double-precision floating point ๐. Dividing by zero causes a floating-point exception โญ. This is the default for SHcompact with an FPU ๐. If you specify this on a target that doesn't have a double-precision FPU, it falls back tocall-div1๐ฆ.
call-tableโ okay so this one calls a library function that uses a lookup table for small divisors ๐, and for bigger divisors it switches to thediv1instruction with case distinction ๐ . Dividing by zero gives an unspecified result and does not trap. This is the default for SH4 ๐ธ. Picking it for targets without dynamic shift instructions makescall-div1the default instead โจ.
When you don't pick a division strategy, GCC chooses one based on the current target ๐. For SH2A, the default is to use the divs and divu instructions instead of library function calls ๐ฆ.
-maccumulate-outgoing-args,-mno-accumulate-outgoing-argsโ reserve space once for outgoing arguments in the function prologue, instead of around each call ๐ง. This is generally great for performance and size, and it's also needed for unwinding so the stack frame doesn't change around conditional code ๐.-maccumulate-outgoing-argsis enabled by default.-mdivsi3_libfunc=nameโ sets the name of the library function used for 32-bit signed division to name ๐ฅ. This only changes the name used in the call division strategies. The compiler still expects the same sets of input, output, and clobbered registers as if this option weren't there ๐ซถ.-mfixed-range=register-rangeโ tells GCC to treat the given register range as fixed registers ๐. A fixed register is one the register allocator can't use, which is super useful when compiling kernel code ๐. A register range is written as two registers separated by a dash, and you can list multiple ranges separated by a comma โจ.-mbranch-cost=numโ assumes num is the cost of a branch instruction ๐. Higher numbers make the compiler try to generate more branch-free code when it can ๐. If you don't specify it, the value depends on the processor type you're compiling for ๐.-mzdcbranch,-mno-zdcbranchโ these assume (or don't assume) that zero displacement conditional branch instructionsbtandbfare fast โก. With-mzdcbranch, the compiler prefers zero displacement branch code sequences ๐ฆ. It's enabled by default when generating code for SH4 and SH4A, and you can explicitly turn it off with-mno-zdcbranch๐.-mcbranch-force-delay-slotโ forces the use of delay slots for conditional branches, filling the delay slot with anopif a suitable instruction can't be found ๐งธ. It's disabled by default. You can turn it on to work around hardware bugs like the ones found in the original SH7055 ๐ ๏ธ.-mfsca,-mno-fscaโ allows or disallows the compiler from emitting thefscainstruction for sine and cosine approximations ๐.-mfscahas to be used together with-funsafe-math-optimizations๐ . It's enabled by default when generating code for SH4A. Using-mno-fscadisables sine and cosine approximations even if-funsafe-math-optimizationsis in effect ๐ซ.-mfsrra,-mno-fsrraโ allows or disallows the compiler from emitting thefsrrainstruction for reciprocal square root approximations ๐.-mfsrrahas to be used with-funsafe-math-optimizationsand-ffinite-math-only๐ซง. It's enabled by default when generating code for SH4A. Using-mno-fsrradisables reciprocal square root approximations even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect ๐.-mpretend-cmove,-mno-pretend-cmoveโ prefer or don't prefer zero-displacement conditional branches for conditional move instruction patterns ๐. This can make code faster on the SH4 processor ๐.-mfdpic,-mno-fdpicโ generates code using the FDPIC ABI ๐ธ.-mlra,-mno-lraโ uses the new LRA register allocator ๐. By default, the oldreloadallocator is used ๐ฐ๏ธ.
๐ธ Solaris 2 Options ๐ธ
These options are supported on Solaris 2 ๐:
-mclear-hwcap,-mno-clear-hwcapโ-mclear-hwcaptells the compiler to remove the hardware capabilities generated by the Solaris assembler ๐งน. You only need this when object files use ISA extensions the current machine doesn't support, but the code checks at runtime whether or not to use them ๐.-mimpure-text,-mno-impure-textโ used together with-shared,-mimpure-texttells the compiler not to pass-z textto the linker when linking a shared object ๐. With this option, you can link position-dependent code into a shared object ๐งฉ.
Yikes, read this part ๐ญ:-mimpure-textsuppresses the "relocations remain against allocatable but non-writable sections" linker error message. However, the necessary relocations trigger copy-on-write, so the shared object is not actually shared across processes ๐. Instead of using-mimpure-text, you should compile all source code with-fpicor-fPICโจ.
-gsctfโ generates Solaris CTF ๐ฆ. It needs to be used for both compilation and linking ๐. Seectf(7)for more information ๐. This is only supported since Solaris 11.4 SRU 84, where the necessary toolchain support was added ๐.
๐ SPARC Options ๐
These -m options are supported on the SPARC ๐ฆ:
-mno-app-regs,-mapp-regsโ-mapp-regsgenerates output using the global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐. Like global register 1, each of global registers 2 through 4 is then treated as an allocable register that gets clobbered by function calls ๐ . This is the default.
To be fully SVR4 ABI-compliant (with some performance loss) use -mno-app-regs ๐ซถ. You should compile libraries and system software with this option ๐.
-mflat,-mno-flatโ with-mflat, the compiler doesn't generate save/restore instructions and uses a "flat" or single register window model โจ. This model is compatible with the regular register window model ๐ง. The local registers and the input registers (0--5) are still treated as "call-saved" registers and are saved on the stack as needed ๐ฅ.
With -mno-flat (the default), the compiler generates save/restore instructions, except for leaf functions ๐ท. This is the normal operating mode ๐.
-mfpu,-mhard-floatโ generates output containing floating-point instructions ๐ฅ. This is the default ๐.-mno-fpu,-msoft-floatโ generates output containing library calls for floating point ๐.
Warning โ ๏ธ: the requisite libraries are not available for all SPARC targets ๐ฌ. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation ๐. You must make your own arrangements to provide suitable library functions for cross-compilation ๐ ๏ธ. The embedded targetssparc-*-aoutandsparclite-*-*do provide software floating-point support ๐ธ.
-msoft-float changes the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐จ. In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work ๐งฉ.
-mhard-quad-floatโ generates output containing quad-word (long double) floating-point instructions ๐ซ.-msoft-quad-floatโ generates output containing library calls for quad-word (long double) floating-point instructions ๐. The functions called are the ones specified in the SPARC ABI, and this is the default ๐.
As of this writing, there are no SPARC implementations with hardware support for the quad-word floating-point instructions ๐ญ. They all invoke a trap handler for one of these instructions, and then the trap handler emulates the effect of the instruction ๐ซ . Because of that trap handler overhead, this is much slower than calling the ABI library routines ๐ข. That's why -msoft-quad-float is the default ๐.
-mno-unaligned-doubles,-munaligned-doublesโ-mno-unaligned-doublesassumes that doubles have 8-byte alignment. This is the default ๐.
With -munaligned-doubles, GCC assumes doubles have 8-byte alignment only if they're contained in another type or have an absolute address ๐ง. Otherwise, it assumes they have 4-byte alignment ๐ค. Using this option avoids some rare compatibility problems with code generated by other compilers ๐ซถ. It isn't the default because it causes a performance loss, especially for floating-point code ๐.
-muser-mode,-mno-user-modeโ-mno-user-modedoesn't generate code that can only run in supervisor mode ๐ . This only matters for thecasainstruction emitted for the LEON3 processor ๐ง . This is the default โจ.-mfaster-structs,-mno-faster-structsโ with-mfaster-structs, the compiler assumes structures should have 8-byte alignment ๐. This enables pairs oflddandstdinstructions for copies in structure assignment, in place of twice as manyldandstpairs ๐๏ธ. However, this changed alignment directly violates the SPARC ABI ๐ซ. So it's only meant for targets where the developer acknowledges their resulting code isn't directly in line with the ABI rules ๐.-mstd-struct-return,-mno-std-struct-returnโ with-mstd-struct-return, the compiler generates checking code in functions returning structures or unions to detect size mismatches between the two sides of function calls, as per the 32-bit ABI ๐. The default is-mno-std-struct-return๐ . This option has no effect in 64-bit mode ๐ซ.-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for the machine type cpu_type ๐ฅ๏ธ. Supported values forcpu_typearev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,leon5,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8๐.
Native Solaris and GNU/Linux toolchains also support the value native, which picks the best architecture option for the host processor ๐ง โจ. -mcpu=native has no effect if GCC doesn't recognize the processor ๐คท.
Default instruction scheduling parameters are used for values that select an architecture rather than an implementation ๐๏ธ. Those are v7, v8, sparclite, sparclet, and v9 ๐.
Here's the lineup of each supported architecture and its implementations ๐ :
v7โcypress,leon3v7๐ทv8โsupersparc,hypersparc,leon,leon3,leon5๐sparcliteโf930,f934,sparclite86x๐ฆsparcletโtsc701๐งv9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8๐
By default (unless it's been configured otherwise), GCC cooks up code for the V7 flavour of SPARC ๐ธ Add -mcpu=cypress and it also gets tuned for the Cypress CY7C602 chip, the one living in the SPARCStation/SPARCServer 3xx series ๐
It's also a great fit for the older SPARCStation 1, 2, IPX etc. ๐ซถ
With -mcpu=v8, GCC generates code for the V8 variant of SPARC โจ The only real difference from V7 code is that the compiler emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not in SPARC-V7 ๐ฅ Add -mcpu=supersparc and it's additionally optimized for the SuperSPARC chip, the one in the SPARCStation 10, 1000 and 2000 series ๐
With -mcpu=sparclite, GCC generates code for the SPARClite variant ๐ง This adds the integer multiply, integer divide step and scan ("ffs") instructions that exist in SPARClite but not in SPARC-V7. Then -mcpu=f930 further optimizes it for the Fujitsu MB86930 chip, which is the original SPARClite and has no FPU ๐ And -mcpu=f934 optimizes it for the Fujitsu MB86934 chip, the more recent SPARClite that does have an FPU ๐ฆ
With -mcpu=sparclet, GCC generates code for the SPARClet variant of SPARC ๐ This adds the integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions that exist in SPARClet but not in SPARC-V7. Add -mcpu=tsc701 and it's optimized for the TEMIC SPARClet chip ๐
With -mcpu=v9, GCC generates code for the V9 variant of SPARC, and it's giving upgrade ๐ This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers and conditional move instructions. Then:
-mcpu=ultrasparcoptimizes for the Sun UltraSPARC I/II/IIi chips ๐-mcpu=ultrasparc3optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips โจ-mcpu=niagaraoptimizes for Sun UltraSPARC T1 chips ๐-mcpu=niagara2optimizes for Sun UltraSPARC T2 chips ๐ธ-mcpu=niagara3optimizes for Sun UltraSPARC T3 chips ๐ฆ-mcpu=niagara4optimizes for Sun UltraSPARC T4 chips ๐-mcpu=niagara7optimizes for Oracle SPARC M7 chips ๐-mcpu=m8optimizes for Oracle M8 chips ๐ฅ-mtune=cpu_typeโ sets the instruction scheduling parameters for machine typecpu_type, but it does not touch the instruction set or register set the way-mcpu=cpu_typedoes ๐ง
The same values you can use for -mcpu=cpu_type work for -mtune=cpu_type, but only the ones that pick out a particular CPU implementation are actually useful: cypress, supersparc, hypersparc, leon, leon3, leon3v7, leon5, f930, f934, sparclite86x, tsc701, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7 and m8. With native Solaris and GNU/Linux toolchains, native can also be used ๐ซถ
Hmm, the bullet list for -mcpu was list items with chips; fineโthey're not option lists exactly. Good.
Continue with the rest. Ensure "-mcpu=v9..." list, "-mtune" bullets, etc. Write final.With -mcpu=v8, GCC generates code for the V8 variant of SPARC โจ The only real difference from V7 code is that the compiler emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not in SPARC-V7 ๐ฅ Add -mcpu=supersparc and it's also optimized for the SuperSPARC chip, the one in the SPARCStation 10, 1000 and 2000 series ๐
With -mcpu=sparclite, GCC generates code for the SPARClite variant ๐ง This adds the integer multiply, integer divide step and scan ("ffs") instructions that exist in SPARClite but not in SPARC-V7. Then -mcpu=f930 further optimizes it for the Fujitsu MB86930 chip, the original SPARClite, which has no FPU ๐ And -mcpu=f934 optimizes it for the Fujitsu MB86934 chip, the more recent SPARClite with an FPU ๐ฆ
With -mcpu=sparclet, GCC generates code for the SPARClet variant of SPARC ๐ This adds the integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions that exist in SPARClet but not in SPARC-V7. Add -mcpu=tsc701 and it's optimized for the TEMIC SPARClet chip ๐
With -mcpu=v9, GCC generates code for the V9 variant of SPARC, and it's giving upgrade ๐ This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers and conditional move instructions. Then the chip-specific flavours go like this:
-mcpu=ultrasparcoptimizes for the Sun UltraSPARC I/II/IIi chips ๐-mcpu=ultrasparc3optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips โจ-mcpu=niagaraoptimizes for Sun UltraSPARC T1 chips ๐-mcpu=niagara2optimizes for Sun UltraSPARC T2 chips ๐ธ-mcpu=niagara3optimizes for Sun UltraSPARC T3 chips ๐ฆ-mcpu=niagara4optimizes for Sun UltraSPARC T4 chips ๐-mcpu=niagara7optimizes for Oracle SPARC M7 chips ๐-mcpu=m8optimizes for Oracle M8 chips ๐ฅ-mtune=cpu_typeโ sets the instruction scheduling parameters for machine typecpu_type, but it does not set the instruction set or register set the way-mcpu=cpu_typedoes ๐ง
The same values you can use for -mcpu=cpu_type work for -mtune=cpu_type, but only the ones that pick out a particular CPU implementation are actually useful: cypress, supersparc, hypersparc, leon, leon3, leon3v7, leon5, f930, f934, sparclite86x, tsc701, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7 and m8. With native Solaris and GNU/Linux toolchains, native can also be used ๐ซถ
-mv8plus,-mno-v8plusโ with-mv8plus, GCC generates code for the SPARC-V8+ ABI ๐ซ The difference from the V8 ABI is that the global and out registers are treated as 64 bits wide. This is enabled by default on Solaris in 32-bit mode for all SPARC-V9 processors.-mvis,-mno-visโ with-mvis, GCC takes advantage of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mno-vis.-mvis2,-mno-vis2โ with-mvis2, GCC takes advantage of version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mvis2when targeting a cpu that supports such instructions, such as UltraSPARC-III and later. Setting-mvis2also sets-mvis.-mvis3,-mno-vis3โ with-mvis3, GCC takes advantage of version 3.0 of the UltraSPARC Visual Instruction Set extensions ๐ฆ The default is-mvis3when targeting a cpu that supports such instructions, such as niagara-3 and later. Setting-mvis3also sets-mvis2and-mvis.-mvis3b,-mno-vis3bโ with-mvis3b, GCC takes advantage of version 3.0 of the UltraSPARC Visual Instruction Set extensions, plus the additional VIS instructions introduced in the Oracle SPARC Architecture 2011 ๐ฅ The default is-mvis3bwhen targeting a cpu that supports such instructions, such as niagara-7 and later. Setting-mvis3balso sets-mvis3,-mvis2and-mvis.-mvis4,-mno-vis4โ with-mvis4, GCC takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mvis4when targeting a cpu that supports such instructions, such as niagara-7 and later. Setting-mvis4also sets-mvis3b,-mvis3,-mvis2and-mvis.-mvis4b,-mno-vis4bโ with-mvis4b, GCC takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions, plus the additional VIS instructions introduced in the Oracle SPARC Architecture 2017 ๐ธ The default is-mvis4bwhen targeting a cpu that supports such instructions, such as m8 and later. Setting-mvis4balso sets-mvis4,-mvis3b,-mvis3,-mvis2and-mvis.-mcbcond,-mno-cbcondโ with-mcbcond, GCC takes advantage of the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ The default is-mcbcondwhen targeting a CPU that supports such instructions, such as Niagara-4 and later.-mfmaf,-mno-fmafโ with-mfmaf, GCC takes advantage of the UltraSPARC Fused Multiply-Add Floating-point instructions โจ The default is-mfmafwhen targeting a CPU that supports such instructions, such as Niagara-3 and later.-mfsmuld,-mno-fsmuldโ with-mfsmuld, GCC takes advantage of the Floating-point Multiply Single to Double (FsMULd) instruction ๐ The default is-mfsmuldwhen targeting a CPU supporting the architecture versions V8 or V9 with FPU, except-mcpu=leon.-mpopc,-mno-popcโ with-mpopc, GCC takes advantage of the UltraSPARC Population Count instruction ๐ง The default is-mpopcwhen targeting a CPU that supports such an instruction, such as Niagara-2 and later.-msubxc,-mno-subxcโ with-msubxc, GCC takes advantage of the UltraSPARC Subtract-Extended-with-Carry instruction ๐ The default is-msubxcwhen targeting a CPU that supports such an instruction, such as Niagara-7 and later.-mfix-at697fโ enables the documented workaround for the single erratum of the Atmel AT697F processor (which corresponds to erratum #13 of the AT697E processor) ๐ ๏ธ-mfix-ut699โ enables the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor ๐ ๏ธ-mfix-ut700โ enables the documented workaround for the back-to-back store errata of the UT699E/UT700 processor ๐ ๏ธ-mfix-gr712rcโ enables the documented workaround for the back-to-back store errata of the GR712RC processor ๐ ๏ธ
These -m options are supported in addition to the above on SPARC-V9 processors in 64-bit environments ๐
-m32,-m64โ generates code for a 32-bit or 64-bit environment ๐ The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits.-mptr32,-mptr64โ uses 32- or 64-bit pointers, respectively ๐ Unlike the-m32and-m64options, this only affects the pointer size and not the ABI.-mcmodel=whichโ sets the code model to one of the following ๐ฆmedlowโ the Medium/Low code model: 64-bit addresses, and programs must be linked in the low 32 bits of memory. Programs can be statically or dynamically linked.medmidโ the Medium/Middle code model: 64-bit addresses, and programs must be linked in the low 44 bits of memory. The text and data segments must be less than 2GB in size, and the data segment must be located within 2GB of the text segment.medanyโ the Medium/Anywhere code model: 64-bit addresses, and programs may be linked anywhere in memory. The text and data segments must be less than 2GB in size, and the data segment must be located within 2GB of the text segment.embmedanyโ the Medium/Anywhere code model for embedded systems: 64-bit addresses, and the text and data segments must be less than 2GB in size, both starting anywhere in memory (determined at link time). The global register%g4points to the base of the data segment. Programs are statically linked and PIC is not supported.
-mmemory-model=mem-modelโ sets the memory model in force on the processor to one of the following ๐งdefaultโ the default memory model for the processor and operating system.rmoโ Relaxed Memory Orderpsoโ Partial Store Ordertsoโ Total Store Orderscโ Sequential Consistency
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, as set in the processor's "PSTATE.MM" field ๐
-mstack-bias,-mno-stack-biasโ with-mstack-bias, GCC assumes that the stack pointer, and frame pointer if present, are offset by-2047, which must be added back when making stack frame references. This is the default in 64-bit mode. Otherwise, it assumes no such offset is present ๐
โจ Options for System V โจ
These additional options are available on System V Release 4 for compatibility with other compilers on those systems ๐ง
-Gโ creates a shared object. It is recommended that-symbolicor-sharedbe used instead. ๐-YP,dirsโ searches the directoriesdirs, and no others, for libraries specified with-l๐-Ym,dirโ looks in the directorydirto find the M4 preprocessor. The assembler uses this option. ๐ซถ
๐ท V850 Options ๐ท
These -m options are defined for V850 implementations ๐ฆ
-mlong-calls,-mno-long-callsโ treats all calls as being far away (near). If calls are assumed to be far away, the compiler always loads the function's address into a register, and calls indirect through the pointer ๐ซ-mno-ep,-mepโ Skips (or turns on) the optimization that copies a pointer into theepregister when a basic block uses the same index pointer 4 or more times, which also lets the compiler use the shortersldandsstinstructions.-mepis on by default when you optimize. ๐ธ-mno-prolog-function,-mprolog-functionโ Stops (or starts) using external functions to save and restore registers in a function's prologue and epilogue. Those helper functions are slower, but they take up less code space when more than one function saves the same number of registers.-mprolog-functionis on by default when you optimize. ๐-mspaceโ Tries to make the code as tiny as possible. Right now it only switches on-mepand-mprolog-function. ๐ง-mtda=nโ Puts static or global variables that arenbytes or smaller into the tiny data area that theepregister points to. That area holds up to 256 bytes total, or 128 bytes for byte references. ๐ฆ-msda=nโ Puts static or global variables that arenbytes or smaller into the small data area that thegpregister points to. That area can hold up to 64 kilobytes. โจ-mzda=nโ Puts static or global variables that arenbytes or smaller into the first 32 kilobytes of memory. ๐-mv850โ Tells GCC the target processor is the V850. ๐-mv850e3v5โ Tells GCC the target processor is the V850E3V5. The preprocessor constant__v850e3v5__gets defined when you use this. ๐-mv850e2v4โ Tells GCC the target processor is the V850E3V5. It's an alias for-mv850e3v5. ๐ซถ-mv850e2v3โ Tells GCC the target processor is the V850E2V3. The preprocessor constant__v850e2v3__gets defined when you use this. ๐ฅ-mv850e2โ Tells GCC the target processor is the V850E2. The preprocessor constant__v850e2__gets defined when you use this. ๐-mv850e1โ Tells GCC the target processor is the V850E1. The preprocessor constants__v850e1__and__v850e__get defined when you use this. ๐-mv850esโ Tells GCC the target processor is the V850ES. It's an alias for-mv850e1. ๐ธ-mv850eโ Tells GCC the target processor is the V850E. The preprocessor constant__v850e__gets defined when you use this. โญ
If none of -mv850, -mv850e, -mv850e1, -mv850e2, -mv850e2v3 or -mv850e3v5 is set, GCC picks a default target processor and defines the matching __v850*__ preprocessor constant. ๐ง
The preprocessor constants __v850 and __v851__ are always defined, no matter which processor variant you're targeting. ๐
-mdisable-callt,-mno-disable-calltโ Suppresses generation of theCALLTinstruction for the v850e, v850e1, v850e2, v850e2v3 and v850e3v5 flavors of the v850 architecture. This is on by default when the RH850 ABI is in use (see-mrh850-abi) and off by default when the GCC ABI is in use. IfCALLTinstructions are being generated, the C preprocessor symbol__V850_CALLT__gets defined. ๐-mrelax,-mno-relaxโ Passes (or doesn't pass) the-mrelaxcommand-line option along to the assembler. ๐ฆ-mlong-jumps,-mno-long-jumpsโ Turns off (or back on) generating PC-relative jump instructions. โจ-msoft-float,-mhard-floatโ Turns off (or back on) generating hardware floating point instructions. This only matters when the target architecture is V850E2V3 or higher. If hardware floating point instructions are being generated, the C preprocessor symbol__FPU_OK__gets defined. Otherwise,__NO_FPU__gets defined. ๐-mloopโ Turns on the e3v5LOOPinstruction. It isn't enabled by default when the e3v5 architecture is selected, because it's still experimental. ๐งช-mrh850-abi,-mghsโ Turns on support for the RH850 version of the V850 ABI. This is the default. With this ABI version, these rules apply:- Integer sized structures and unions get returned through a memory pointer instead of a register.
- Large structures and unions (more than 8 bytes in size) get passed by value.
- Functions get aligned to 16-bit boundaries.
- The
-m8byte-aligncommand-line option is supported. - The
-mdisable-calltcommand-line option is enabled by default. The-mno-disable-calltcommand-line option is not supported.
When this ABI version is on, the C preprocessor symbol __V850_RH850_ABI__ gets defined. ๐
-mgcc-abiโ Turns on support for the old GCC version of the V850 ABI. With this ABI version, these rules apply:- Integer sized structures and unions get returned in register
r10. - Large structures and unions (more than 8 bytes in size) get passed by reference.
- Functions get aligned to 32-bit boundaries, unless you're optimizing for size.
- The
-m8byte-aligncommand-line option is not supported. - The
-mdisable-calltcommand-line option is supported, but not enabled by default.
When this ABI version is on, the C preprocessor symbol __V850_GCC_ABI__ gets defined. ๐ซถ
-m8byte-align,-mno-8byte-alignโ Letsdoubleandlong longtypes align on 8-byte boundaries. By default, every object is restricted to at most 4-byte alignment. When-m8byte-alignis in effect, the C preprocessor symbol__V850_8BYTE_ALIGN__gets defined. ๐-mbig-switch,-mno-big-switchโ Generates code that works with big switch tables. Only use this if the assembler or linker complains about out of range branches inside a switch table. ๐ญ-mapp-regs,-mno-app-regsโ-mapp-regsmakes the compiler user2andr5in the code it generates. This is the default.-mno-app-regsmakesr2andr5fixed registers that the compiler won't touch. ๐ฅ-msmall-sld,-mno-small-sldโ Turns on (or off) the use of the short load instructions. ๐ธ-mno-strict-alignโ Doesn't enforce strict data alignment. ๐-mjump-tables-in-data-section,-mno-jump-tables-in-data-sectionโ Puts jump tables forswitchstatements in the.datasection instead of the.codesection (or keeps them in.code). The default is-mno-jump-tables-in-data-section. ๐ง
โจ VAX Options โจ
These -m options are defined for the VAX: ๐ฆ
-munixโ Doesn't output certain jump instructions (aobleqand so on) that the Unix assembler for the VAX can't handle across long ranges. ๐-mgnuโ Does output those jump instructions, on the assumption that you're using the GNU assembler. โจ-md,-md-floatโ Uses the D_floating data format for double-precision floating-point numbers instead of G_floating. ๐-mg,-mg-floatโ Uses the G_floating data format for double-precision floating-point numbers instead of D_floating. ๐-mlra,-mno-lraโ Enables Local Register Allocation. It's still experimental for the VAX, so by default the compiler uses standard reload. ๐งช-mvaxc-alignmentโ Uses VAXC conventions for aligning structure members. ๐-mqmath,-mno-qmathโ Turns new instruction patterns for 64-bit integer addition and subtraction on or off. โญ
โจ Visium Options โจ
-mdebugโ Use this when linking programs that do file I/O and are meant to run on an MCM target. It links the librarieslibc.aandlibdebug.a. You should run the program on the target under the control of the GDB remote debugging stub. ๐ฅ-msimโ Use this when linking programs that do file I/O and are meant to run on the simulator. It links the librarieslibc.aandlibsim.a. ๐-mfpu,-mhard-floatโ Generates code with floating-point instructions. This is the default. ๐-mno-fpu,-msoft-floatโ Generates code with library calls for floating-point instead. ๐
-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile your whole program with this option. You also need to compilelibgcc.a(the library that comes with GCC) with-msoft-floatfor this to work. ๐
-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for the machine typecpu_type. Supported values forcpu_typearemcm,gr5andgr6. ๐
mcm is a synonym for gr5, kept around for backward compatibility. ๐
By default (unless configured otherwise), GCC generates code for the GR5 variant of the Visium architecture. ๐ฆ
With -mcpu=gr6, GCC generates code for the GR6 variant of the Visium architecture. The only difference from GR5 code is that the compiler will generate block move instructions. ๐ง
-mtune=cpu_typeโ Sets the instruction scheduling parameters for the machine typecpu_type, but doesn't set the instruction set or register set that-mcpu=cpu_typewould. โจ-msv-modeโ Generates code for supervisor mode, where there are no restrictions on access to general registers. This is the default. ๐-muser-modeโ Generates code for user mode, where access to some general registers is forbidden. On the GR5, registersr24tor31can't be accessed in this mode. On the GR6, only registersr29tor31are affected. ๐
โจ VMS Options โจ
These -m options are defined for the VMS implementations: ๐ธ
-mvms-return-codesโ Returns VMS condition codes frommain. The default is to return POSIX-style condition (e.g. error) codes. ๐-mdebug-main=prefixโ Flags the first routine whose name starts withprefixas the main routine for the debugger. ๐-mmalloc64โ Defaults to 64-bit memory allocation routines. ๐-mpointer-size=sizeโ Sets the default size of pointers. Possible values forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers. Thenooption disablespragma pointer_size. ๐ซถ
โจ VxWorks Options โจ
The options in this section are defined for all VxWorks targets. Options specific to the target hardware are listed with the other options for that target. ๐
-mrtp: Okay so GCC can make code for VxWorks kernels and real time processes (RTPs) ๐ธ. This flag switches it over to RTPs, and it also defines the preprocessor macro__RTP__โจ.-msmp: This picks the SMP runtimes for linking ๐. It's only a thing on PowerPC ๐ and isn't available on VxWorks version 7 or later. On 7+, the choice is part of the VxWorks build configuration, and the library paths are the same either way ๐ง.-mvthreads: Links against the VxWorks AE vThread runtime environment ๐ฆ.-non-static: Links an RTP executable against shared libraries instead of static ones ๐.-staticand-sharedwork for RTPs too, and-staticis the default ๐ .-Bstatic,-Bdynamic: These get passed down to the linker ๐ซถ. They're here for Diab compatibility, so Diab folks feel right at home ๐ก.-Xbind-lazy: Turns on lazy binding of function calls ๐ค. It's equivalent to-Wl,-z,now, and it's defined for Diab compatibility too.-Xbind-now: Turns lazy binding off ๐ . This is the default, and it's also there for Diab compatibility.
โจ x86 Options โจ
This section is all about the -m options for the x86 family of computers ๐ป.
The next group lets you target a specific processor ๐ฏ.
-march=cpu-type: Generates instructions for the machine type cpu-type ๐. Quick difference check:-mtune=cpu-typeonly tunes the generated code for that CPU, but-march=cpu-typelets GCC generate code that may not run at all on other processors โ ๏ธ. Specifying-march=cpu-typeimplies-mtune=cpu-type, except where noted otherwise.
The choices for cpu-type are:
native: Picks the CPU to generate code for at compile time by checking the processor type of the machine doing the compiling ๐ฅ๏ธ.-march=nativeenables all instruction subsets supported by the local machine, so the result might not run on different machines ๐.-mtune=nativemakes code optimized for the local machine under the constraints of the selected instruction set.x86-64: A generic CPU with 64-bit extensions, MMX, SSE, SSE2, and FXSR instruction set support ๐.x86-64-v2,x86-64-v3,x86-64-v4: These select the corresponding micro-architecture level from the x86-64 psABI ๐. On ABIs other than the x86-64 psABI, they select the same CPU features the x86-64 psABI documents for that micro-architecture level. These values don't have a matching-mtunesetting, so using-marchwith them enables generic tuning. Want specific tuning? Use-mtune=other-cpu-typewith an appropriate other-cpu-type value.i386: Original Intel i386 CPU ๐ฆ.i486: Intel i486 CPU. No scheduling is implemented for this chip.i586,pentium: Intel Pentium CPU with no MMX support.lakemont: Intel Lakemont MCU, based on the Intel Pentium CPU.pentium-mmx: Intel Pentium MMX CPU, based on the Pentium core with MMX instruction set support.pentiumpro: Intel Pentium Pro CPU with no MMX support.i686: With-march, the Pentium Pro instruction set is used, so the code runs on all i686 family chips ๐. With-mtune, it has the same meaning asgeneric.pentium2: Intel Pentium II CPU, based on the Pentium Pro core with MMX and FXSR instruction set support.pentium3,pentium3m: Intel Pentium III CPU, based on the Pentium Pro core with MMX, FXSR and SSE instruction set support.pentium-m: Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE, SSE2 and FXSR instruction set support โ. It's used by Centrino notebooks.pentium4,pentium4m: Intel Pentium 4 CPU with MMX, SSE, SSE2 and FXSR instruction set support.prescott: An improved Intel Pentium 4 CPU with MMX, SSE, SSE2, SSE3 and FXSR instruction set support โญ.nocona: An improved Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and FXSR instruction set support โญ.core2: Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, CX16, SAHF and FXSR instruction set support ๐.nehalem,corei7: Intel Nehalem CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF and FXSR instruction set support ๐ฅ.westmere: Intel Westmere CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR and PCLMUL instruction set support ๐ธ.sandybridge,corei7-avx: Intel Sandy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE and PCLMUL instruction set support ๐ฆ.ivybridge,core-avx-i: Intel Ivy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND and F16C instruction set support โจ.haswell,core-avx2: Intel Haswell CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE and HLE instruction set support ๐ง.broadwell: Intel Broadwell CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX and PREFETCHW instruction set support ๐ .skylake: Intel Skylake CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES and SGX instruction set support ๐.skylake-avx512: Intel Skylake Server CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ and AVX512CD instruction set support ๐ฅ.cascadelake: Intel Cascade Lake CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD and AVX512VNNI instruction set support ๐.cannonlake: Intel Cannon Lake Server CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA and SHA instruction set support ๐ง.cooperlake: Intel Cooper Lake CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI and AVX512BF16 instruction set support ๐ซถ.icelake-client: Intel Ice Lake Client CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID and AVX512VPOPCNTDQ instruction set support ๐ง.icelake-server: Intel Ice Lake Server CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD and CLWB instruction set support ๐ง.tigerlake: Intel Tiger Lake CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, MOVDIRI, MOVDIR64B, CLWB, AVX512VP2INTERSECT and KEYLOCKER instruction set support ๐ฆ.rocketlake: Intel Rocket Lake CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID and AVX512VPOPCNTDQ instruction set support ๐ธ.
alderlake,raptorlake,meteorlake,gracemont: Intel Alder Lake/Raptor Lake/Meteor Lake/Gracemont CPUs, which come with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, KL, WIDEKL and AVX-VNNI instruction set support. ๐โจarrowlake: Intel Arrow Lake CPU ๐ฆ, with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, KL, WIDEKL, AVX-VNNI, UINTR, AVXIFMA, AVXVNNIINT8, AVXNECONVERT and CMPCCXADD instruction set support. ๐arrowlake-s,lunarlake: Intel Arrow Lake S/Lunar Lake CPUs, which come with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, KL, WIDEKL, AVX-VNNI, UINTR, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, AVXVNNIINT16, SHA512, SM3 and SM4 instruction set support. ๐pantherlake,wildcatlake: Intel Panther Lake/Wildcat Lake CPUs with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, AVX-VNNI, UINTR, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, AVXVNNIINT16, SHA512, SM3 and SM4 instruction set support. ๐งnovalake: Intel Nova Lake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, AVX-VNNI, UINTR, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, AVXVNNIINT16, SHA512, SM3, SM4, PREFETCHI, APX_F, AVX10.1, AVX10.2 and MOVRS instruction set support. ๐ธsapphirerapids,emeraldrapids: Intel Sapphire Rapids/Emerald Rapids CPUs with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB, MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512-FP16 and AVX512BF16 instruction set support. ๐graniterapids: Intel Granite Rapids CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB, MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512-FP16, AVX512BF16, AMX-FP16 and PREFETCHI instruction set support. ๐ฅgraniterapids-d: Intel Granite Rapids D CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB, MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16, AVX512BF16, AMX-FP16, PREFETCHI and AMX-COMPLEX instruction set support. ๐ฆdiamondrapids: Intel Diamond Rapids CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2, VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB, MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16, AVX512BF16, AMX-FP16, PREFETCHI, AMX-COMPLEX, AVX10.1-512, AVX-IFMA, AVX-NE-CONVERT, AVX-VNNI-INT16, AVX-VNNI-INT8, CMPccXADD, SHA512, SM3, SM4, AVX10.2-512, APX_F, AMX-AVX512, AMX-FP8, AMX-TF32, MOVRS and AMX-MOVRS instruction set support. ๐โจbonnell,atom: Intel Bonnell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. ๐silvermont,slm: Intel Silvermont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW and RDRND instruction set support. ๐goldmont: Intel Goldmont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW, RDRND, AES, SHA, RDSEED, XSAVE, XSAVEC, XSAVES, XSAVEOPT, CLFLUSHOPT and FSGSBASE instruction set support. ๐goldmont-plus: Intel Goldmont Plus CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW, RDRND, AES, SHA, RDSEED, XSAVE, XSAVEC, XSAVES, XSAVEOPT, CLFLUSHOPT, FSGSBASE, PTWRITE, RDPID and SGX instruction set support. โญtremont: Intel Tremont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW, RDRND, AES, SHA, RDSEED, XSAVE, XSAVEC, XSAVES, XSAVEOPT, CLFLUSHOPT, FSGSBASE, PTWRITE, RDPID, SGX, CLWB, GFNI-SSE, MOVDIRI, MOVDIR64B, CLDEMOTE and WAITPKG instruction set support. ๐sierraforest: Intel Sierra Forest CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, KL, WIDEKL, AVX-VNNI, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, ENQCMD and UINTR instruction set support. ๐ฆgrandridge: Intel Grand Ridge CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, KL, WIDEKL, AVX-VNNI, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, ENQCMD and UINTR instruction set support. ๐งclearwaterforest: Intel Clearwater Forest CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, AVX-VNNI, ENQCMD, UINTR, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, AVXVNNIINT16, SHA512, SM3, SM4, USER_MSR and PREFETCHI instruction set support. ๐k6: AMD K6 CPU with MMX instruction set support. ๐ธk6-2,k6-3: Improved versions of AMD K6 CPU with MMX and 3DNow! instruction set support. โจathlon,athlon-tbird: AMD Athlon CPU with MMX, 3dNOW!, enhanced 3DNow! and SSE prefetch instructions support. ๐ฅathlon-4,athlon-xp,athlon-mp: Improved AMD Athlon CPU with MMX, 3DNow!, enhanced 3DNow! and full SSE instruction set support. ๐k8,opteron,athlon64,athlon-fx: Processors based on the AMD K8 core with x86-64 instruction set support, including the AMD Opteron, Athlon 64, and Athlon 64 FX processors. (This supersets MMX, SSE, SSE2, 3DNow!, enhanced 3DNow! and 64-bit instruction set extensions.) ๐งk8-sse3,opteron-sse3,athlon64-sse3: Improved versions of AMD K8 cores with SSE3 instruction set support. ๐ซถamdfam10,barcelona: CPUs based on AMD Family 10h cores with x86-64 instruction set support. (This supersets MMX, SSE, SSE2, SSE3, SSE4A, 3DNow!, enhanced 3DNow!, ABM and 64-bit instruction set extensions.) ๐bdver1โ CPUs built on AMD Family 15h cores with x86-64 support ๐ (This supersets FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver2โ AMD Family 15h core CPUs with x86-64 support ๐ฆ (This supersets BMI, TBM, F16C, FMA, FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver3โ AMD Family 15h core CPUs with x86-64 support โจ (This supersets BMI, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver4โ AMD Family 15h core CPUs with x86-64 support ๐ธ (This supersets BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP, LWP, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)znver1โ AMD Family 17h core CPUs with x86-64 support ๐ (This supersets BMI, BMI2, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, and 64-bit instruction set extensions.)znver2โ AMD Family 17h core CPUs with x86-64 support ๐ง (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, and 64-bit instruction set extensions.)znver3โ AMD Family 19h core CPUs with x86-64 support ๐ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, and 64-bit instruction set extensions.)znver4โ AMD Family 19h core CPUs with x86-64 support ๐ฅ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, AVX512F, AVX512DQ, AVX512IFMA, AVX512CD, AVX512BW, AVX512VL, AVX512BF16, AVX512VBMI, AVX512VBMI2, AVX512VNNI, AVX512BITALG, AVX512VPOPCNTDQ, GFNI and 64-bit instruction set extensions.)znver5โ AMD Family 1ah core CPUs with x86-64 support ๐ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, AVX512F, AVX512DQ, AVX512IFMA, AVX512CD, AVX512BW, AVX512VL, AVX512BF16, AVX512VBMI, AVX512VBMI2, AVX512VNNI, AVX512BITALG, AVX512VPOPCNTDQ, GFNI, AVXVNNI, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, PREFETCHI and 64-bit instruction set extensions.)znver6โ AMD Family 1ah core CPUs with x86-64 support ๐ฆ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, AVX512F, AVX512DQ, AVX512IFMA, AVX512CD, AVX512BW, AVX512VL, AVX512BF16, AVX512VBMI, AVX512VBMI2, AVX512VNNI, AVX512BITALG, AVX512VPOPCNTDQ, GFNI, AVXVNNI, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, PREFETCHI, AVXVNNIINT8, AVXIFMA, AVX512FP16, AVXNECONVERT, AVX512BMM and 64-bit instruction set extensions.)btver1โ CPUs built on AMD Family 14h cores with x86-64 support ๐ (This supersets MMX, SSE, SSE2, SSE3, SSSE3, SSE4A, CX16, ABM and 64-bit instruction set extensions.)btver2โ CPUs built on AMD Family 16h cores with x86-64 support ๐ซถ This includes MOVBE, F16C, BMI, AVX, PCLMUL, AES, SSE4.2, SSE4.1, CX16, ABM, SSE4A, SSSE3, SSE3, SSE2, SSE, MMX and 64-bit instruction set extensions.winchip-c6โ IDT WinChip C6 CPU ๐ It's handled exactly like i486, plus extra MMX instruction set support.winchip2โ IDT WinChip 2 CPU ๐ It's handled exactly like i486, plus extra MMX and 3DNow! instruction set support.c3โ VIA C3 CPU with MMX and 3DNow! instruction set support ๐ธ (No scheduling is implemented for this chip.)c3-2โ VIA C3-2 (Nehemiah/C5XL) CPU with MMX and SSE instruction set support ๐ (No scheduling is implemented for this chip.)c7โ VIA C7 (Esther) CPU with MMX, SSE, SSE2 and SSE3 instruction set support โจ (No scheduling is implemented for this chip.)samuel-2โ VIA Eden Samuel 2 CPU with MMX and 3DNow! instruction set support ๐ฆ (No scheduling is implemented for this chip.)nehemiahโ VIA Eden Nehemiah CPU with MMX and SSE instruction set support ๐ง (No scheduling is implemented for this chip.)estherโ VIA Eden Esther CPU with MMX, SSE, SSE2 and SSE3 instruction set support ๐ (No scheduling is implemented for this chip.)eden-x2โ VIA Eden X2 CPU with x86-64, MMX, SSE, SSE2 and SSE3 instruction set support ๐ฅ (No scheduling is implemented for this chip.)eden-x4โ VIA Eden X4 CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 instruction set support ๐ (No scheduling is implemented for this chip.)nanoโ Generic VIA Nano CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support ๐ (No scheduling is implemented for this chip.)nano-1000โ VIA Nano 1xxx CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support ๐ (No scheduling is implemented for this chip.)nano-2000โ VIA Nano 2xxx CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support ๐ซถ (No scheduling is implemented for this chip.)nano-3000โ VIA Nano 3xxx CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support ๐ (No scheduling is implemented for this chip.)nano-x2โ VIA Nano Dual Core CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support ๐ (No scheduling is implemented for this chip.)nano-x4โ VIA Nano Quad Core CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support ๐ธ (No scheduling is implemented for this chip.)lujiazuiโ ZHAOXIN lujiazui CPU with x86-64, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, ABM, BMI, BMI2, FXSR, RDSEED instruction set support ๐ The CPUs do support AVX and F16C, but-march=lujiazuidoesn't turn these on, "for performance reasons."yongfengโ ZHAOXIN yongfeng CPU with x86-64, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, ABM, BMI, BMI2, F16C, FXSR, RDSEED, AVX2, FMA, SHA, LZCNT instruction set support โจshijidadaoโ ZHAOXIN shijidadao CPU with x86-64, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, ABM, BMI, BMI2, F16C, FXSR, RDSEED, AVX2, FMA, SHA, LZCNT instruction set support ๐งgeodeโ AMD Geode embedded processor with MMX and 3DNow! instruction set support ๐
โจ -mtune=cpu-type โจ
Tune cpu-type for everything that applies to the generated code, except the ABI and the set of available instructions ๐ Picking a specific cpu-type schedules things nicely for that exact chip, but the compiler won't spit out code that can't run on the default machine type unless you also use a -march=cpu-type option. For example, if GCC is configured for i686-pc-linux-gnu, then -mtune=pentium4 makes code tuned for Pentium 4 that still runs on i686 machines ๐
The choices for cpu-type are the same as for -march. On top of those, -mtune supports 2 extra choices for cpu-type:
genericโ Optimizes for the most common IA32/AMD64/EM64T processors ๐ If you know exactly which CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=generic. But if you have no clue what CPUs your users will have, this is the one to use ๐ซถ
As new processors hit the market, the behavior of this option changes. So if you upgrade to a newer GCC, code generation under this option will shift to match the processors that are most popular when that GCC version gets released ๐ธ
There's no -march=generic option, because -march describes the instruction set the compiler can use, and there's no generic instruction set that fits every processor. -mtune, on the other hand, describes the processor (or, in this case, the whole collection of processors) that the code is optimized for โจ
intelโ Optimizes for the most current Intel processors, which are Haswell and Silvermont for this version of GCC ๐ฅ If you know which CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=intel. But if you want your application to perform better on both Diamond Rapids and Clearwater Forest, this is the option you want ๐
As new Intel processors hit the market, this option's behavior is going to change ๐. So if you upgrade to a newer GCC, the code generated by this option will shift to match the newest Intel chips available when that GCC version comes out โจ.
There's no -march=intel option, bestie ๐
โโ๏ธ. -march controls the instruction set the compiler is allowed to use, and there's no single instruction set that every Intel processor shares. -mtune is different: it tells GCC which processor (or, in this case, group of processors) the code is optimized for ๐
.
The following options give you more detailed control over which instruction set extensions GCC targets ๐. Each one has a matching -mno- option that turns those instructions off ๐.
These extensions are also available as built-in functions. Check out x86 Built-in Functions for the details on which functions get enabled and disabled by these switches ๐ง.
These options let GCC use the extended instructions in generated code. Apps that do run-time CPU detection have to compile separate files for each supported architecture, using the right flags ๐ซถ.
Heads up ๐: the file containing the CPU detection code should be compiled without these options.
To control whether 387 or SSE/AVX instructions get generated automatically for floating-point arithmetic, see -mfpmath=, below ๐.
-mmmxโ Turns on MMX built-in functions ๐ธ.-msseโ Turns on MMX and SSE built-in functions and code generation ๐ฆ.-msse2โ Turns on MMX, SSE and SSE2 built-in functions and code generation โจ.-msse3โ Turns on MMX, SSE, SSE2 and SSE3 built-in functions and code generation โจ.-mssse3โ Turns on MMX, SSE, SSE2, SSE3 and SSSE3 built-in functions and code generation โจ.-msse4.1โ Turns on MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 built-in functions and code generation โจ.-msse4.2โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation โจ.-msse4โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation ๐.
Quick note ๐:-msse4turns on both SSE4.1 and SSE4.2 support, while-mno-sse4turns those features off. Neither form of the option touches SSE4A support, which is controlled separately by-msse4a.
-msse4aโ Turns on MMX, SSE, SSE2, SSE3 and SSE4A built-in functions and code generation ๐.-mavxโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX built-in functions and code generation ๐ฅ.-mavx2โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 built-in functions and code generation ๐ฅ.-mavx512fโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F built-in functions and code generation ๐.-mavx512cdโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512CD built-in functions and code generation ๐.-mavx512vlโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VL built-in functions and code generation ๐.-mavx512bwโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512BW built-in functions and code generation ๐.-mavx512dqโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512DQ built-in functions and code generation ๐.-mavx512ifmaโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512IFMA built-in functions and code generation ๐.-mavx512vbmiโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VBMI built-in functions and code generation ๐.-mavx512vpopcntdqโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VPOPCNTDQ built-in functions and code generation ๐.-mavx512vp2intersectโ Turns on AVX512VP2INTERSECT built-in functions and code generation ๐ฆ.-mavx512vnniโ Turns on AVX512VNNI built-in functions and code generation ๐ฆ.-mavx512vbmi2โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VBMI2 built-in functions and code generation ๐.-mavx512bf16โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512BF16 built-in functions and code generation ๐.-mavx512fp16โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512-FP16 built-in functions and code generation ๐.-mavx512bitalgโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512BITALG built-in functions and code generation ๐.-mavx512bmmโ Turns on AVX512BMM built-in functions and code generation ๐ฆ.-mavxvnniโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and AVXVNNI built-in functions and code generation ๐ธ.-mavxifmaโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and AVXIFMA built-in functions and code generation ๐ธ.-mavxvnniint8โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVXVNNIINT8 built-in functions and code generation ๐ธ.-mavxneconvertโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and AVXNECONVERT built-in functions and code generation ๐ธ.-mavxvnniint16โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVXVNNIINT16 built-in functions and code generation ๐ธ.-mavx10.1โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and AVX10.1 built-in functions and code generation ๐.-mavx10.2โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX10.1 and AVX10.2 built-in functions and code generation ๐.-mshaโ Turns on SHA1 and SHA256 built-in functions and code generation ๐.-maesโ Turns on AES built-in functions and code generation ๐.-mpclmulโ Turns on PCLMUL built-in functions and code generation ๐.-mclflushoptโ Turns on CLFLUSHOPT instructions ๐งน.-mclwbโ Turns on the CLWB instruction ๐งน.-mfsgsbaseโ Turns on FSGSBASE built-in functions and code generation ๐ง .-mptwriteโ Turns on PTWRITE built-in functions and code generation ๐ง .-mrdrndโ Turns on RDRND built-in functions and code generation ๐ฒ.-mf16cโ Turns on F16C built-in functions and code generation ๐ง .-mfmaโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation ๐ฅ.-mfma4โ Turns on FMA4 built-in functions and code generation ๐ฅ.-mpconfigโ Turns on PCONFIG built-in functions and code generation โ๏ธ.-mwbnoinvdโ Turns on WBNOINVD built-in functions and code generation โ๏ธ.-mprfchwโ Turns on the PREFETCHW instruction ๐๏ธ.-mrdpidโ Turns on RDPID built-in functions and code generation ๐.-mrdseedโ Turns on the RDSEED instruction ๐ฒ.-msgxโ Turns on SGX built-in functions and code generation ๐.-mxopโ Turns on XOP built-in functions and code generation ๐ง.-mlwpโ Turns on LWP built-in functions and code generation ๐ง.-m3dnowโ Turns on 3DNow! built-in functions ๐น๏ธ.-m3dnowaโ Turns on Athlon 3Dnow! built-in functions ๐น๏ธ.-mpopcntโ Turns on code generation for the popcnt instruction ๐ข.-mabmโ Turns on code generation for Advanced Bit Manipulation (ABM) instructions ๐ข.-madxโ Turns on flag-preserving add-carry instructions โ.-mbmiโ Turns on BMI built-in functions and code generation ๐ข.-mbmi2โ Turns on BMI2 built-in functions and code generation ๐ข.-mlzcntโ Turns on the LZCNT built-in function and code generation ๐ข.-mfxsrโ Turns on FXSAVE and FXRSTOR instructions ๐พ.-mxsaveโ Turns on XSAVE and XRSTOR instructions ๐พ.-mxsaveoptโ Turns on the XSAVEOPT instruction ๐พ.-mxsavecโ Turns on XSAVEC instructions ๐พ.-mxsavesโ Turns on XSAVES and XRSTORS instructions ๐พ.-mrtmโ Turns on RTM built-in functions and code generation ๐งต.-mhleโ Turns on Hardware Lock Elision prefixes ๐งต.-mtbmโ Turns on TBM built-in functions and code generation ๐ข.-mmwaitxโ Turns on MWAITX and MONITORX built-in functions and code generation โณ.-mclzeroโ Turns on CLZERO built-in functions and code generation ๐งน.-mpkuโ Turns on PKU built-in functions and code generation ๐.-mgfniโ Turns on GFNI built-in functions and code generation ๐.-mvaesโ Turns on VAES built-in functions and code generation ๐.-mwaitpkgโ Turns on WAITPKG built-in functions and code generation โณ.-mvpclmulqdqโ Turns on VPCLMULQDQ built-in functions and code generation ๐.-mmovdiriโ Turns on MOVDIRI built-in functions and code generation ๐.-mmovdir64bโ Turns on MOVDIR64B built-in functions and code generation ๐.-menqcmdโ Turns on ENQCMD built-in functions and code generation ๐จ.-muintrโ Turns on UINTR built-in functions and code generation ๐จ.-mtsxldtrkโ Turns on TSXLDTRK built-in functions and code generation ๐งต.-mcldemoteโ Turns on CLDEMOTE built-in functions and code generation ๐งน.-mserializeโ Turns on SERIALIZE built-in functions and code generation ๐งต.-mamx-tileโ Turns on AMX-TILE built-in functions and code generation ๐งฑ.-mamx-int8โ Turns on AMX-INT8 built-in functions and code generation ๐งฑ.-mamx-bf16โ Turns on AMX-BF16 built-in functions and code generation ๐งฑ.-mhresetโ Turns on HRESET built-in functions and code generation ๐.-mklโ Turns on KL built-in functions and code generation ๐.-mwideklโ Turns on WIDEKL built-in functions and code generation ๐.-mcmpccxaddโ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and CMPCCXADD built-in functions and code generation ๐.-mamx-fp16โ Turns on AMX-FP16 built-in functions and code generation ๐งฑ.-mprefetchiโ Turns on PREFETCHI built-in functions and code generation ๐๏ธ.-mraointโ Turns on RAOINT built-in functions and code generation ๐ง .-mamx-complexโ Turns on AMX-COMPLEX built-in functions and code generation ๐งฑ.-msm3โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and SM3 built-in functions and code generation ๐ธ.-msm4โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and SM4 built-in functions and code generation ๐ธ.-msha512โ Turns on MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and SHA512 built-in functions and code generation ๐ธ.-mapxfโ Turns on code generation for APX features, including EGPR, PUSH2POP2, NDD, PPX, NF, CCMP and ZU ๐.
Okay bestie, let's get into the x86 extras ๐ฆโจ
-musermsrโ slay ๐ this one turns onUSER_MSRbuilt-in functions and code generation ๐-mamx-avx512โ the full glow-up ๐ it supports MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX10.1, AVX10.2 and AMX-AVX512 built-in functions and code generation ๐ฅ-mamx-tf32โ adds AMX-TF32 built-in functions and code generation ๐ธ-mamx-fp8โ adds AMX-FP8 built-in functions and code generation ๐ง-mmovrsโ adds MOVRS built-in functions and code generation ๐-mamx-movrsโ adds AMX-MOVRS built-in functions and code generation ๐ซถ
These extra options are all for the x86 processor family ๐
๐ -mfpmath=unit
This one picks which unit does your floating-point math, unit. The choices are:
387โ uses the standard 387 floating-point coprocessor that's in most chips, and emulates it on the ones that don't have it ๐ซง Code built this way runs almost everywhere ๐ Temporary results get computed in 80-bit precision instead of the precision the type asks for, so you can get slightly different answers than most other chips. Check out-ffloat-storefor the more detailed deets. This is the default choice for non-Darwin x86-32 targets.sseโ uses the scalar floating-point instructions from the SSE instruction set ๐ซ Pentium III and newer chips have it, and on the AMD side it's Athlon-4, Athlon XP and Athlon MP chips. The earlier SSE version only handles single-precision arithmetic, so double and extended-precision still go through 387. A later version, found only in Pentium 4 and AMD x86-64 chips, handles double-precision too. For the x86-32 compiler you need-march=cpu-type,-msseor-msse2to turn on the SSE extensions and make this option work. For the x86-64 compiler those extensions are on by default. The result should be considerably faster in most cases and dodge the numerical instability problems of 387 code ๐โโ๏ธ but it might break existing code that expects temporaries to be 80 bits ๐ This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and x86-32 targets with the SSE2 instruction set when-ffast-mathis enabled. Also, GCC switches SSE instructions off when-mavx(or another option enabling AVX extensions) is used. Instead it generates new AVX instructions, or AVX equivalents for all SSE instructions, when needed.sse,387,sse+387,bothโ tries to use both instruction sets at once ๐ง This effectively doubles the number of available registers, and on chips with separate execution units for 387 and SSE, it doubles the execution resources too. Use this with care! It's still experimental, because the GCC register allocator doesn't model separate functional units well, which leads to unstable performance ๐ญ
-mieee-fp,-mno-ieee-fpโ controls whether or not the compiler uses IEEE floating-point comparisons ๐ These handle the case where the result of a comparison is unordered, correctly ๐-m80387,-mhard-floatโ generates output containing 80387 instructions for floating point ๐ฅ-mno-80387,-msoft-floatโ generates output containing library calls for floating point ๐
Warning: the requisite libraries are not part of GCC! Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation ๐ On machines where a function returns floating-point results in the 80387 register stack, some floating-point opcodes may still be emitted even if -msoft-float is used ๐
-mno-fp-ret-in-387โ stops using the FPU registers for function return values ๐ซ The usual calling convention has functions returnfloatanddoublevalues in an FPU register, even when there's no FPU, since the operating system is supposed to emulate one.-mno-fp-ret-in-387makes those values come back in ordinary CPU registers instead.-mno-fancy-math-387โ some 387 emulators don't support thesin,cosandsqrtinstructions for the 387, so this one stops GCC from generating them ๐ง It gets overridden when-marchsays the target CPU always has an FPU, since then the instruction doesn't need emulating. These instructions aren't generated unless you also use the-funsafe-math-optimizationsswitch.-malign-double,-mno-align-doubleโ controls whether GCC alignsdouble,long double, andlong longvariables on a two-word boundary or a one-word boundary ๐ Aligningdoublevariables on a two-word boundary makes code run somewhat faster on a Pentium, but at the expense of more memory. On x86-64,-malign-doubleis on by default.
Warning: if you use -malign-double, structures containing the above types get aligned differently than the published application binary interface specifications for x86-32, so they aren't binary compatible with structures in code compiled without that switch ๐จ
-m96bit-long-double,-m128bit-long-doubleโ these control the size of thelong doubletype ๐ The x86-32 application binary interface says the size is 96 bits, so-m96bit-long-doubleis the default in 32-bit mode. Modern architectures (Pentium and newer) preferlong doublealigned to an 8- or 16-byte boundary, but in arrays or structures that conform to the ABI, that isn't possible. So-m128bit-long-doublealignslong doubleto a 16-byte boundary by padding it with an additional 32-bit zero. In the x86-64 compiler,-m128bit-long-doubleis the default, since its ABI specifies thatlong doubleis aligned on a 16-byte boundary. Heads up: neither of these options enables any extra precision over the x87 standard of 80 bits for along double.
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, and also modifies the function calling convention for functions takinglong double. Hence they aren't binary-compatible with code compiled without that switch ๐ซฃ
-mlong-double-64โ controls the size of thelong doubletype ๐ A size of 64 bits makeslong doubleequivalent todouble. This is the default for the 32-bit Bionic C library.-mlong-double-80โ part of the same family of switches that set the size oflong double, alongside the two around it ๐-mlong-double-128โ a size of 128 bits makeslong doubleequivalent to__float128. This is the default for the 64-bit Bionic C library ๐
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, and also modifies the function calling convention for functions takinglong double. Hence they aren't binary-compatible with code compiled without that switch ๐ซฃ
-malign-data=typeโ controls how GCC aligns variables ๐งฉ The supported values for type are:compatโ uses an increased alignment value that's compatible with GCC 4.8 and earlier. This is the default.abiโ uses the alignment value specified by the psABI.cachelineโ uses an increased alignment value to match the cache line size.
-mlarge-data-threshold=thresholdโ when-mcmodel=mediumor-mcmodel=largeis specified, data objects bigger than threshold get placed in large data sections ๐ฆ The default is65535.-mrtdโ switches to a different function-calling convention ๐ In it, functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments as they return. That saves one instruction in the caller, since there's no need to pop the arguments there. You can make an individual function use this calling sequence with the function attributestdcall, and you can override the-mrtdoption for a function with the function attributecdecl.
Warning: this calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler ๐
โโ๏ธ You must provide function prototypes for all functions that take variable numbers of arguments (including printf), otherwise incorrect code gets generated for calls to those functions ๐ฌ In addition, seriously incorrect code results if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored.) ๐
-mregparm=numโ controls how many registers get used to pass integer arguments ๐ฏ By default, no registers are used to pass arguments, and at most 3 registers can be used. You can control this for a specific function with the function attributeregparm.
Warning: if you use this switch and num is nonzero, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐งฑ
-msseregparmโ uses SSE register passing conventions forfloatanddoublearguments and return values โจ You can control this for a specific function with the function attributesseregparm.
Warning: if you use this switch, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐งฑ
-mvect8-ret-in-memโ returns 8-byte vectors in memory instead of MMX registers ๐ซง This is the default on VxWorks, to match the ABI of the Sun Studio compilers until version 12. Only use this option if you need to stay compatible with existing code produced by those earlier compiler versions or older versions of GCC ๐ฐ๏ธ-mpc32,-mpc64,-mpc80โ okay so these bestie options set the 80387 floating-point precision to 32, 64 or 80 bits ๐ . With-mpc32, the significands of floating-point results get rounded to 24 bits (single precision) โจ.-mpc64rounds them to 53 bits (double precision) ๐.-mpc80rounds them to 64 bits (extended double precision) and it's the default, so it's giving classic ๐. Heads up: once you use one of these, higher precisions aren't available to you as the programmer unless you set the FPU control word explicitly ๐.
Dropping the rounding below the default 80 bits can speed some programs up by 2% or more ๐ฅ. Ngl though, some math libraries assume extended-precision (80-bit) operations are on by default. Routines in those libraries can lose a lot of accuracy, usually through so-called "catastrophic cancellation" ๐, if you set the precision to less than extended.
-mdaz-ftz,-mno-daz-ftzโ the FTZ (flush-to-zero) and DAZ (denormals-are-zero) flags in the MXCSR register are what control floating-point calculations here ๐ฆ. Normally,-Ofast,-ffast-math, or-funsafe-math-optimizationslink in startup code that sets these flags, except when you're building a shared library (-shared) ๐. Use-mdaz-ftzor-mno-daz-ftzto explicitly turn that setting on or off, no matter what other options GCC gets ๐.-mstackrealignโ realigns the stack at entry ๐ง. On x86, this generates an alternate prologue and epilogue that realigns the run-time stack when needed. It's how you mix legacy code that keeps 4-byte stack alignment with modern code that keeps 16-byte alignment for SSE compatibility ๐ซถ. See also the attribute"force_align_arg_pointer", which works on individual functions.-mstack-arg-probeโ emits stack probing code in the function prologue ๐ธ.-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐. If you don't specify this, the default is4(16 bytes, or 128 bits) ๐.
โ ๏ธ Bestie, this one is dangerous. When generating code for the x86-64 architecture with SSE extensions disabled,-mpreferred-stack-boundary=3can keep the stack boundary aligned to an 8-byte boundary. The x86-64 ABI requires 16-byte stack alignment, so this is ABI incompatible ๐ญ. It's only meant for a controlled environment where stack space is a seriously limited resource. It produces wrong code when functions compiled with 16-byte stack alignment (like functions from a standard library) get called with a misaligned stack, and then SSE instructions can cause misaligned memory access traps ๐. Variable arguments are also handled incorrectly for 16-byte aligned objects (including x87long doubleand__int128), which gives wrong results. You have to build all modules with-mpreferred-stack-boundary=3, including any libraries, and that covers the system libraries and startup modules too ๐ โโ๏ธ.
-mincoming-stack-boundary=numโ assumes the incoming stack is aligned to a 2 raised to num byte boundary ๐งธ. If you don't specify it, the one set by-mpreferred-stack-boundarygets used.
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double) or you'll take big run-time performance hits ๐ข. On Pentium III, the SSE data type __m128 may not work properly if it isn't 16-byte aligned ๐ฅบ.
To make sure these values are aligned on the stack, the stack boundary has to be at least as aligned as whatever any value on the stack requires. Every function also has to be generated so it keeps the stack aligned ๐งฉ. So calling a function compiled with a higher preferred stack boundary from one compiled with a lower one will most likely misalign the stack ๐ฌ. Libraries that use callbacks should always stick with the default setting, as recommended.
This extra alignment eats up stack space and usually bumps up code size ๐ฆ. If your code is picky about stack space, like embedded systems and operating system kernels, you might want to drop the preferred alignment to -mpreferred-stack-boundary=2 ๐.
-mdump-tune-featuresโ tells GCC to dump the names of the x86 performance tuning features and their default settings ๐. You can use those names in-mtune-ctrl=feature-list.-mtune-ctrl=feature-listโ fine-grain control of x86 code generation features ๐๏ธ.feature-listis a comma-separated list of feature names. When you specify one, it gets turned on unless it's preceded by^, in which case it gets turned off. See also-mdump-tune-features.
๐จ This one is intended for GCC developers. Using it may lead to code paths that aren't covered by testing, and it can potentially cause compiler ICEs or runtime errors.
-mno-defaultโ turns off all tunable features ๐งน. See also-mtune-ctrl=feature-listand-mdump-tune-features.-mcldโ makes GCC emit a"cld"instruction in the prologue of functions that use string instructions ๐. String instructions depend on the DF flag to pick between autoincrement and autodecrement mode. The ABI says DF should be cleared on function entry, but some operating systems don't clear it in their exception dispatchers, so the handler can run with DF set and string instructions go the wrong direction ๐ตโ๐ซ. This option can be turned on by default on 32-bit x86 targets if you configure GCC with the--enable-cldconfigure option. In that case, you can suppress generation of"cld"instructions with the-mno-cldcompiler option.-mvzeroupperโ makes GCC emit a"vzeroupper"instruction before control flow leaves the function ๐งผ. This cuts down the AVX-to-SSE transition penalty and removes unnecessary"zeroupper"intrinsics.-mstv,-mno-stvโ enable or disable the Scalar to Vectorization pass, which turns 64-bit integer computation into vector ones ๐ซ. This optimization is restricted to-O2and higher.-mprefer-avx128โ tells GCC to use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer ๐.-mprefer-vector-width=optโ tells GCC to use an opt-bit vector width in instructions instead of the default for the selected platform ๐.-mpartial-vector-fp-math,-mno-partial-vector-fp-mathโ lets GCC generate floating-point operations that might affect the floating-point status flags on partial vectors, where the vector elements live in the low part of the 128-bit SSE register ๐ง . Unless you specify-fno-trapping-math, the compiler guarantees correct behavior by sanitizing all input operands so the unused upper part of the vector register is full of zeroes ๐งฝ. Heads up though: if you use built-in functions or inline assembly with partial vector arguments, NaNs, denormal or invalid values can leak into the upper part of the vector. That can cause performance issues when-fno-trapping-mathis in effect ๐. You can fix that by manually sanitizing the upper part of the partial vector argument register, or by using-mdaz-ftzto set the denormals-are-zero (DAZ) flag in the MXCSR register.
This option is enabled by default โ .
-mmove-max=bitsโ sets the maximum number of bits that can be moved from memory to memory efficiently to bits ๐. The valid values are128,256and512.-mstore-max=bitsโ sets the maximum number of bits that can be stored to memory efficiently to bits ๐พ. The valid values are128,256and512.noneโ no extra limitations on GCC beyond whatever the selected platform defines ๐คทโโ๏ธ.128โ prefers a 128-bit vector width for instructions ๐.256โ prefers a 256-bit vector width for instructions ๐.512โ prefers a 512-bit vector width for instructions ๐ฉต.
-mnoreturn-no-callee-saved-registersโ optimizes functions with the"noreturn"attribute or the_Noreturnspecifier by not saving the callee-saved registers they use in the function prologue (except for the"BP"register) ๐ช. This can mess with debugging the caller of the"noreturn"function, or any function further up the call stack, so it's not enabled by default โ ๏ธ.-mcx16โ lets GCC generate"CMPXCHG16B"instructions in 64-bit code to do compare-and-exchange operations on 16-byte aligned 128-bit objects ๐. This is handy for atomic updates of data structures bigger than one machine word. The compiler uses this instruction to implement__syncbuiltins. For__atomicbuiltins operating on 128-bit integers, though, a library call is always used ๐.-msahfโ enables generation of"SAHF"instructions in 64-bit code ๐ง. Early Intel Pentium 4 CPUs with Intel 64 support, from before the Pentium 4 G1 step in December 2005, lacked the"LAHF"and"SAHF"instructions that AMD64 supports. These are load and store instructions, respectively, for certain status flags. In 64-bit mode, the"SAHF"instruction is used to optimize thefmod,drem, andremainderbuilt-in functions; see Other Builtins for details ๐.-mmovbeโ enables use of the"movbe"instruction to optimize byte swapping of four- and eight-byte entities ๐.-mshstkโ enables the shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ก๏ธ.-mcrc32โ enables the built-in functions"__builtin_ia32_crc32qi","__builtin_ia32_crc32hi","__builtin_ia32_crc32si"and"__builtin_ia32_crc32di"to generate the"crc32"machine instruction ๐งฎ.-mmwaitโ enables the built-in functions"__builtin_ia32_monitor"and"__builtin_ia32_mwait"to generate the"monitor"and"mwait"machine instructions ๐ด.-mrecipโ okay so this one turns on theRCPSSandRSQRTSSinstructions (plus their vectorized buddiesRCPPSandRSQRTPS) and adds an extra Newton-Raphson step for better precision. It swaps them in forDIVSSandSQRTSS(and their vectorized versions) when you're working with single-precision floating-point arguments. These only get generated when-funsafe-math-optimizationsis on together with-ffinite-math-onlyand-fno-trapping-math. Heads up: the sequence has higher throughput than the non-reciprocal instruction, but its precision can drop by up to 2 ulp. For example, the inverse of 1.0 comes out as 0.99999994 ๐
GCC already turns 1.0f/sqrtf(x) into RSQRTSS (or RSQRTPS) with -ffast-math (or that same option combo), so you don't need -mrecip for that โจ
Also, GCC emits the sequence with the extra Newton-Raphson step for vectorized single-float division and vectorized sqrtf(x) already with -ffast-math (or that same option combo). Again, no -mrecip needed ๐ซถ
-mrecip=optโ this one lets you pick exactly which reciprocal estimate instructions are allowed ๐ Theoptpart is a comma-separated list, and you can put a!in front of any option to invert it.allโ enables every estimate instruction ๐ฅdefaultโ enables the default instructions, same as-mrecip๐ธnoneโ disables all estimate instructions, same as-mno-recip๐divโ enables the approximation for scalar divisionvec-divโ enables the approximation for vectorized divisionsqrtโ enables the approximation for scalar square rootvec-sqrtโ enables the approximation for vectorized square root
So, for example, -mrecip=all,!sqrt turns on all the reciprocal approximations except square root. It's giving main character energy for picking and choosing ๐
-mveclibabi=typeโ this sets the ABI type for vectorizing intrinsics with an external library.typecan besvml(the Intel short vector math library),aocl(the LibM math library from AMD Optimizing CPU Libraries, AOCL), oracml(the end-of-life AMD core math library, which AOCL-LibM succeeded) ๐ง To use it, you need both-ftree-vectorizeand-funsafe-math-optimizationsenabled, and you have to specify an SVML or ACML ABI-compatible library at link time. Otherwise it's a no-go ๐ญ
GCC currently emits calls to these functions for svml:
vmldExp2, vmldLn2, vmldLog102, vmldPow2, vmldTanh2, vmldTan2, vmldAtan2,
vmldAtanh2, vmldCbrt2, vmldSinh2, vmldSin2, vmldAsinh2, vmldAsin2,
vmldCosh2, vmldCos2, vmldAcosh2, vmldAcos2, vmlsExp4, vmlsLn4, vmlsLog104,
vmlsPow4, vmlsTanh4, vmlsTan4, vmlsAtan4, vmlsAtanh4, vmlsCbrt4, vmlsSinh4,
vmlsSin4, vmlsAsinh4, vmlsAsin4, vmlsCosh4, vmlsCos4, vmlsAcosh4, vmlsAcos4
For aocl, it's these corresponding function types:
amd_vrs4_acosf, amd_vrs16_acosf, amd_vrd8_asin, amd_vrs4_asinf,
amd_vrs8_asinf, amd_vrs16_asinf, amd_vrd2_atan, amd_vrd8_atan,
amd_vrs4_atanf, amd_vrs8_atanf, amd_vrs16_atanf, amd_vrd2_cos, amd_vrd4_cos,
amd_vrd8_cos, amd_vrs4_cosf, amd_vrs8_cosf, amd_vrs16_cosf, amd_vrs4_coshf,
amd_vrs8_coshf, amd_vrd2_erf, amd_vrd4_erf, amd_vrd8_erf, amd_vrs4_erff,
amd_vrs8_erff, amd_vrs16_erff, amd_vrd2_exp, amd_vrd4_exp, amd_vrd8_exp,
amd_vrs4_expf, amd_vrs8_expf, amd_vrs16_expf, amd_vrd2_exp10,
amd_vrs4_exp10f, amd_vrd2_exp2, amd_vrd4_exp2, amd_vrd8_exp2, amd_vrs4_exp2f,
amd_vrs8_exp2f, amd_vrs16_exp2f, amd_vrs4_expm1f, amd_vrd2_log, amd_vrd4_log,
amd_vrd8_log, amd_vrs4_logf, amd_vrs8_logf, amd_vrs16_logf, amd_vrd2_log10,
amd_vrs4_log10f, amd_vrs8_log10f, amd_vrs16_log10f, amd_vrd2_log1p,
amd_vrs4_log1pf, amd_vrd2_log2, amd_vrd4_log2, amd_vrd8_log2, amd_vrs4_log2f,
amd_vrs8_log2f, amd_vrs16_log2f, amd_vrd2_pow, amd_vrd4_pow, amd_vrd8_pow,
amd_vrs4_powf, amd_vrs8_powf, amd_vrs16_powf, amd_vrd2_sin, amd_vrd4_sin,
amd_vrd8_sin, amd_vrs4_sinf, amd_vrs8_sinf, amd_vrs16_sinf, amd_vrd2_tan,
amd_vrd4_tan, amd_vrd8_tan, amd_vrs16_tanf, amd_vrs4_tanhf, amd_vrs8_tanhf,
amd_vrs16_tanhf
And for acml, it's these:
__vrd2_sin, __vrd2_cos, __vrd2_exp, __vrd2_log, __vrd2_log2, __vrd2_log10,
__vrs4_sinf, __vrs4_cosf, __vrs4_expf, __vrs4_logf, __vrs4_log2f,
__vrs4_log10f, __vrs4_powf
-mabi=nameโ picks the calling convention to generate code for ๐ The valid values aresysv(the ABI used on GNU/Linux and other systems) andms(the Microsoft ABI). By default you get the Microsoft ABI when targeting Microsoft Windows and the SysV ABI everywhere else. You can override this per function with thems_abiandsysv_abifunction attributes ๐-masm=dialectโ chooses the assembly dialect for output ๐ It also decides which dialect is used for basicasmand extendedasm. The choices areattorintel, and the default isatt. Fun fact (well, a limitation): Darwin doesn't supportintel๐-mforce-indirect-callโ forces all function calls to be indirect โจ This is handy with Intel Processor Trace, since it gives you more precise timing info for function calls ๐ฆ-mmanual-endbrโ only inserts theENDBRinstruction at function entry when you use thecf_checkfunction attribute ๐ซถ It's useful together with-fcf-protection=branchif you want to controlENDBRinsertion at the function entry yourself.-mcet-switchโ by default, CET instrumentation is off for switch statements that use a jump table, and indirect branch track is disabled ๐ Since jump tables live in read-only memory, that's not a direct loss of hardening. BUT if the jump table index is attacker-controlled, the indirect jump might not be constrained by CET. This option turns CET instrumentation on so indirect branch track is enabled for switch statements with jump tables, which leads to the jump targets being reachable via any indirect jumps ๐ฅ-mcall-ms2sysv-xloguesโ because of differences in 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function has to treat RSI, RDI and XMM6-15 as clobbered ๐ By default, the code for saving and restoring those registers is emitted inline, which makes the prologues and epilogues pretty lengthy. With-mcall-ms2sysv-xlogues, the prologues and epilogues use stubs in the static portion oflibgccfor those saves and restores instead. That shrinks function size, at the cost of a few extra instructions ๐ง-mtls-dialect=typeโ generates code to access thread-local storage using thegnuorgnu2conventions ๐gnuis the conservative default.gnu2is more efficient, but it may add compile- and run-time requirements that can't be satisfied on all systems, so be careful ๐ญ-mpush-args,-mno-push-argsโ uses PUSH operations to store outgoing parameters ๐ธ This method is shorter and usually just as fast as the SUB/MOV approach, and it's enabled by default. In some cases, disabling it can improve performance thanks to better scheduling and fewer dependencies.-maccumulate-outgoing-argsโ if enabled, the maximum amount of space needed for outgoing arguments gets computed in the function prologue ๐ฆ This is faster on most modern CPUs because of reduced dependencies, improved scheduling, and reduced stack usage when the preferred stack boundary is not equal to 2. The tradeoff is a notable increase in code size. This switch implies-mno-push-args๐
-mms-bitfields,-mno-ms-bitfieldsโ enables or disables bit-field layout that's compatible with the native Microsoft Windows compiler ๐
Okay, here's the tea: if packed is used on a structure, or if bit-fields are used, the Microsoft ABI might lay out the structure differently than GCC normally does. Especially when you're moving packed data between GCC-compiled functions and the native Microsoft compiler (whether through a function call or as data in a file), you might need to access either format ๐
This option is enabled by default for Microsoft Windows targets. You can also control this behavior locally with variable or type attributes. For more info, check out x86 Attributes โจ
The Microsoft structure layout algorithm is pretty simple, except for the bit-field packing. The padding and alignment of structure members, and whether a bit-field can straddle a storage-unit boundary, are determined by these rules:
- Structure members are stored sequentially, in the order they're declared. The first member has the lowest memory address and the last member has the highest.
- Every data object has an alignment requirement. For all data except structures, unions, and arrays, the alignment requirement is either the size of the object or the current packing size (set with either the
alignedattribute or thepackpragma), whichever is less. For structures, unions, and arrays, the alignment requirement is the largest alignment requirement of its members. Every object is allocated an offset so that:
offset % alignment_requirement == 0
- Adjacent bit-fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size, and if the next bit-field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit-fields ๐งฉ
MSVC interprets zero-length bit-fields in the following ways:
- If a zero-length bit-field is inserted between two bit-fields that are normally coalesced, the bit-fields are not coalesced ๐ โโ๏ธ
For example:
struct
{
unsigned long bf_1 : 12;
unsigned long : 0;
unsigned long bf_2 : 12;
} t1;
The size of t1 is 8 bytes with the zero-length bit-field. If the zero-length bit-field were removed, t1's size would be 4 bytes ๐
- okay so bestie, if a zero-length bit-field gets slotted in right after a bit-field called
foo, and its alignment is bigger than the member right after it (bar), thenbargets aligned as the type of that zero-length bit-field ๐
For example:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For t2, bar lands at offset 2 instead of offset 1, so the size of t2 is 4 โจ. For t3, the zero-length bit-field doesn't mess with the alignment of bar, so the size of the struct doesn't change ๐
Taking this into account, here's what you need to know ๐
- If a zero-length bit-field follows a normal bit-field, its type can affect the alignment of the whole structure. Like,
t2is 4 bytes big because the zero-length bit-field comes after a normal bit-field and is type short ๐ - Even if a zero-length bit-field isn't followed by a normal bit-field, it can still change the alignment of the structure ๐ญ
struct
{
char foo : 6;
long : 0;
} t4;
Here, t4 takes up 4 bytes ๐ธ
- Zero-length bit-fields that come after non-bit-field members get ignored, no cap ๐
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes ๐ฆ
-mno-align-stringopsโ Skips aligning the destination of inlined string operations ๐ซถ. This makes your code smaller and can speed things up when the destination is already aligned, but GCC doesn't know that, so it's kind of on you ๐-minline-all-stringopsโ By default GCC only inlines string operations when it knows the destination is aligned to at least a 4-byte boundary. This option makes it inline way more, which bumps up code size but can make shortmemcpyandmemsetcalls faster ๐ฅ. It also turns on inline expansion ofstrlenfor all pointer alignments โจ-minline-stringops-dynamicallyโ For string operations where the size isn't known, it adds run-time checks: inline code for small blocks, and a library call for big ones ๐ง-mstringop-strategy=algโ Overrides GCC's internal heuristic for picking which algorithm gets used to inline string operations. The allowed values for alg are:rep_byte,rep_4byte,rep_8byteโ Expands using the i386repprefix at the specified size ๐byte_loop,loop,unrolled_loopโ Expands into an inline loop ๐libcallโ Always uses a library call ๐
-mmemcpy-strategy=strategyโ Overrides the internal heuristic that decides whether__builtin_memcpygets inlined, and which inline algorithm to use when the expected size of the copy is known ๐. The strategy is a comma-separated list of alg:max_size:dest_align triplets. alg is one of the values from-mstringop-strategy, and max_size is the biggest byte size that inline algorithm is allowed to handle. The last triplet must have a max_size of-1, and the max_size values in the list must go in increasing order. The minimum byte size for alg is 0 for the first triplet, andmax_size + 1of the range before it for every other triplet ๐-mmemset-strategy=strategyโ Basically the same vibe as-mmemcpy-strategy=, except this one controls the__builtin_memsetexpansion ๐-momit-leaf-frame-pointerโ Doesn't keep the frame pointer in a register for leaf functions. That skips the instructions that save, set up, and restore frame pointers, and frees up an extra register in leaf functions ๐. Heads up though: it removes the frame pointer for leaf functions, which might make debugging harder ๐ฌ-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ Controls whether TLS variables can be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer has to be added. Whether that's valid depends on your operating system, and on whether it maps the segment to cover the entire TLS area ๐ง. For systems that use the GNU C Library, the default is on ๐ซถ-msse2avx,-mno-sse2avxโ Tells the assembler to encode SSE instructions with a VEX prefix. The-mavxoption turns this on by default โจ-mfentry,-mno-fentryโ If profiling is active (-pg), this puts the profiling counter call before the prologue. Note: On x86 architectures, the attribute"ms_hook_prologue"isn't possible at the moment for-mfentryand-pg๐ซ-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), this generates a section containing pointers to each profiling call, which is super handy for patching those calls automatically ๐ฉน. You can use themfentry-section=option to set the name of that section. It defaults to__mcount_loc๐-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), this generates the calls to the profiling functions as NOPs. That's useful when they should get patched in later on, dynamically. This is likely only useful together with-mrecord-mcount๐ฆ-minstrument-return=typeโ With-pg -mfentry, this instruments function exits according to type, which can be one of:none(don't instrument),call(generate a call to"__return__"), ornop5(generate a 5-byte nop sequence) ๐ธ. This only instruments true returns that end with a"ret", not sibling calls made via a jump ๐ โโ๏ธ-mrecord-return,-mno-record-returnโ Generates a"__return_loc"section that points to all the return instrumentation code ๐บ๏ธ-mfentry-name=nameโ Sets the name of the"__fentry__"symbol that gets called at function entry for-pg -mfentryfunctions ๐-mfentry-section=nameโ Sets the name of the section where-mrecord-mcountcalls get recorded. The default is__mcount_loc๐งพ-mskip-rax-setup,-mno-skip-rax-setupโ When generating code for the x86-64 architecture with SSE extensions disabled,-mskip-rax-setupcan skip setting up the RAX register, but only when no variable arguments are passed in vector registers ๐ง-m8bit-idiv,-mno-8bit-idivโ On some processors, like Intel Atom, 8-bit unsigned integer divide is way faster than 32-bit/64-bit integer divide ๐๏ธ. This option generates a run-time check: if both the dividend and divisor are in the range 0 to 255, it uses 8-bit unsigned integer divide instead of 32-bit/64-bit integer divide ๐-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Splits 32-byte AVX unaligned loads and stores into smaller pieces โ๏ธ-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset,-mstack-protector-guard-symbol=symbolโ Generates stack protection code using a canary at guard. The supported locations areglobal(for a global canary) ortls(for a per-thread canary in the TLS block, which is the default) ๐ก๏ธ. These only do something if-fstack-protectoror-fstack-protector-allis specified ๐
With the latter choice (tls), -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to specify which segment register (%fs or %gs) to use as the base register for reading the canary, and what offset from that base register to use. The defaults for those are whatever the relevant ABI says ๐
-mstack-protector-guard-symbol=symbol overrides the offset with a symbol reference to a canary in the TLS block ๐
-mgeneral-regs-onlyโ Generates code that only uses the general-purpose registers. This stops the compiler from using floating-point, vector, mask, and bound registers ๐ซ๐-mrelax-cmpxchg-loopโ When emitting a compare-and-swap loop for__syncbuiltins and__atomicbuiltins that don't have a native instruction, this optimizes for the super contended case. It issues an atomic load before theCMPXCHGinstruction, and uses thePAUSEinstruction to save CPU power when restarting the loop โก-mindirect-branch=choiceโ Converts indirect calls and jumps according to choice. The default iskeep, which leaves indirect calls and jumps unmodified ๐.thunkconverts them to a call and return thunk.thunk-inlineconverts them to an inlined call and return thunk.thunk-externconverts them to an external call and return thunk, provided in a separate object file ๐ฆ. You can control this behavior for a specific function using the function attribute"indirect_branch"๐ฏ
Heads up:-mcmodel=largeis incompatible with-mindirect-branch=thunkand-mindirect-branch=thunk-extern, since the thunk function may not be reachable in the large code model ๐ง
Note: -mindirect-branch=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐ซถ
-mfunction-return=choiceโ Converts function returns according to choice. The default iskeep, which leaves function returns unmodified ๐.thunkconverts function returns to a call and return thunk.thunk-inlineconverts them to an inlined call and return thunk.thunk-externconverts them to an external call and return thunk, provided in a separate object file ๐ฆ. You can control this behavior for a specific function using the function attribute"function_return"๐ฏ
Note: -mindirect-return=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐ซถ
Heads up:-mcmodel=largeis incompatible with-mfunction-return=thunkand-mfunction-return=thunk-extern, since the thunk function may not be reachable in the large code model ๐ง
-mindirect-branch-registerโ Forces indirect calls and jumps to go via a register ๐ง-mharden-sls=choiceโ okay bestie, this one's a whole security glow-up ๐ก๏ธ It makes GCC generate code that guards against straight line speculation (SLS), with the level set by choice. The default isnone, which turns off all SLS hardening.returncovers function returns,indirect-jmpcovers indirect jumps, andallturns on every SLS hardening option ๐ฅ-mindirect-branch-cs-prefixโ this one is giving very specific main character energy โจ It adds a CS prefix tocallandjmpinstructions that go to an indirect thunk, where the branch target is in ther8-r15registers. That makes each call or jmp instruction 6 bytes long, so at run time they can potentially be swapped out forlfence; call *%r8-r15orlfence; jmp *%r8-r15๐ฆ-mapx-inline-asm-use-gpr32โ so by default, EGPR usage is turned off in inline asm constraints ๐ The reason is that GCC has no way of knowing whether the asm instructions can handle GP32 or not. If your inline asm can handle EGPR, you add-mapx-inline-asm-use-gpr32and you're good to go ๐-mgather,-mscatterโ these two are a matching set ๐ They enable vectorization for gather and scatter instructions, respectively.
These -m switches are supported on top of everything above for x86-64 processors in 64-bit environments ๐ธ
-m32,-m64,-mx32,-m16โ okay this is the environment squad ๐ They generate code for a 16-bit, 32-bit or 64-bit environment.-m32setsint,long, and pointer types to 32 bits, and generates code that runs in 32-bit mode.-m64setsintto 32 bits, setslongand pointer types to 64 bits, and generates code for the x86-64 architecture. For Darwin, only-m64also turns off the-fno-picand-mdynamic-no-picoptions ๐-mx32setsint,long, and pointer types to 32 bits, and generates code for the x86-64 architecture โจ-m16is basically-m32, except it also outputs the.code16gccassembly directive at the very start of the assembly output, so the binary can run in 16-bit mode ๐ง
-miamcuโ this one generates code that conforms to the Intel MCU psABI. It requires-m32to be turned on ๐-mno-red-zoneโ okay so the x86-64 ABI says there's a so-called "red zone" ๐ง It's a 128-byte area beyond the stack pointer that signal or interrupt handlers don't touch, so you can stash temporary data there without adjusting the stack pointer.-mno-red-zoneturns that red zone off ๐ โโ๏ธ-mcmodel=smallโ the default, and it's the chill one ๐ธ It generates code for the small code model, where the program and its symbols must be linked in the lower 2 GB of the address space. Pointers are 64 bits, and programs can be statically or dynamically linked.-mcmodel=kernelโ this one lives in the negative 2 GB of the address space, and it has to be used for Linux kernel code ๐-mcmodel=mediumโ the program gets linked in the lower 2 GB, and small symbols go there too. Symbols bigger than-mlarge-data-thresholdget put into large data or BSS sections, and those can sit above 2GB. Programs can be statically or dynamically linked ๐ฆ-mcmodel=largeโ this model makes no assumptions at all about addresses and sizes of sections ๐-maddress-mode=longโ generates code for long address mode. It's only supported for 64-bit and x32 environments, and it's the default address mode for 64-bit environments ๐-maddress-mode=shortโ generates code for short address mode. It's only supported for 32-bit and x32 environments, and it's the default address mode for 32-bit and x32 environments ๐ซถ-mneeded,-mno-neededโ these emit theGNU_PROPERTY_X86_ISA_1_NEEDEDGNU property for the Linux target, which tells you the micro-architecture ISA level needed to run the binary โญ-mno-direct-extern-accessโ okay so without-fpicor-fPIC, this one always uses the GOT pointer to reach external symbols. With-fpicor-fPIC, it treats access to protected symbols as local symbols. The default is-mdirect-extern-access๐
โ ๏ธ Warning: shared libraries compiled with-mno-direct-extern-accessand executables compiled with-mdirect-extern-accessmay not be binary compatible if protected symbols are used in both the shared libraries and the executable. Be careful, bestie ๐ญ
-munroll-only-small-loops,-mno-unroll-only-small-loopsโ this is conservative small loop unrolling ๐ธ It's enabled by default with-O2, and it unrolls loops with fewer than 4 instructions by 1 time. That gives better utilization of the instruction decoding pipeline on modern processors. You can turn it off with-mno-unroll-only-small-loops, and it's also disabled if the more general options-funroll-loopsor-funroll-all-loopsare either enabled or explicitly disabled ๐-mdispatch-schedulerโ enables instruction scheduling โจ It's only supported onbdver1,bdver2,bdver3,bdver4, andznver1processors, and it additionally requires-fschedule-insns -fsched-pressure๐ฅ-mlam=choiceโ LAM (linear-address masking) lets special bits in the pointer be used for metadata ๐ง The default isnone. Withu48, pointer bits in positions 62:48 can be used for metadata. Withu57, pointer bits in positions 62:57 can be used for metadata ๐
๐ธ x86 Windows Options ๐ธ
๐ต Xstormy16 Options ๐ต
These options are defined for Xstormy16 ๐ฆ
-msimโ chooses startup files and a linker script that are suitable for the simulator ๐ง
๐ Xtensa Options ๐
These options are supported for Xtensa targets ๐
-mconst16,-mno-const16โ enables or disables the use of"CONST16"instructions for loading constant values ๐ When enabled,"CONST16"instructions are always used in place of the standard"L32R"instructions. The use of"CONST16"is enabled by default only if the"L32R"instruction is not available ๐-mserialize-volatile,-mno-serialize-volatileโ when this one is enabled, GCC inserts"MEMW"instructions before"volatile"memory references to guarantee sequential consistency ๐ซถ The default is-mserialize-volatile. Use-mno-serialize-volatileto leave out the"MEMW"instructions ๐-mforce-no-pic,-mno-force-no-picโ for targets like GNU/Linux, where all user-mode Xtensa code has to be position-independent code (PIC), this option turns PIC off when compiling kernel code ๐-mtext-section-literals,-mno-text-section-literalsโ these control the treatment of literal pools ๐ The default is-mno-text-section-literals, which puts literals in a separate section in the output file. That lets the literal pool sit in data RAM/ROM, and it also lets the linker combine literal pools from separate object files to remove redundant literals and improve code size. With-mtext-section-literals, the literals are interspersed in the text section so they stay as close as possible to their references. This may be necessary for large assembly files. Literals for each function are placed right before that function ๐ธ-mauto-litpools,-mno-auto-litpoolsโ these also control the treatment of literal pools ๐ฆ The default is-mno-auto-litpools, which puts literals in a separate section in the output file unless-mtext-section-literalsis used. With-mauto-litpools, the assembler interspersses the literals in the text section. The compiler doesn't produce explicit".literal"directives, and it loads literals into registers with"MOVI"instructions instead of"L32R", so the assembler can do relaxation and place literals as necessary. This option lets the assembler create several literal pools per function and assemble very big functions, which may not be possible with-mtext-section-literals๐ง-mtarget-align,-mno-target-alignโ when enabled, GCC tells the assembler to automatically align instructions to reduce branch penalties, at the cost of some code density ๐ The assembler tries to widen density instructions to align branch targets and the instructions following call instructions. If there aren't enough preceding safe density instructions to align a target, no widening happens. The default is-mtarget-align. These options don't affect auto-aligned instructions like"LOOP", which the assembler always aligns, either by widening density instructions or by inserting NOP instructions ๐-mlongcalls,-mno-longcallsโ when enabled, GCC tells the assembler to translate direct calls into indirect calls, unless it can tell that the target of a direct call is in the range the call instruction allows ๐ญ This usually happens for calls to functions in other source files. Specifically, the assembler turns a direct"CALL"instruction into an"L32R"followed by a"CALLX"instruction. The default is-mno-longcalls. Use this option in programs where the call target might be out of range ๐ซถ It's implemented in the assembler, not the compiler, so the assembly code GCC generates still shows direct call instructions. Look at the disassembled object code to see the actual instructions ๐ The assembler uses an indirect call for every cross-file call, not just the ones that really are out of range ๐-mabi=nameโ generates code for the specified ABI ๐ Permissible values arecall0andwindowed. The default ABI is chosen by the Xtensa core configuration.-mabi=call0โ function parameters are passed in registers"a2"through"a7", registers"a12"through"a15"are caller-saved, and register"a15"may be used as a frame pointer ๐ธ When this ABI version is enabled, the C preprocessor symbol"__XTENSA_CALL0_ABI__"is defined โจ-mabi=windowedโ function parameters are passed in registers"a10"through"a15", and the called function rotates the register window by 8 registers on entry, so its arguments are found in registers"a2"through"a7"๐ง Register"a7"may be used as a frame pointer. The register window is rotated 8 registers back upon return. When this ABI version is enabled, the C preprocessor symbol"__XTENSA_WINDOWED_ABI__"is defined ๐
-mextra-l32r-costs=nโ okay so this one lets you dial in an extra cost for instruction RAM/ROM access on"L32R"instructions, measured in clock cycles โฑ๏ธ ๐ธ When you're optimizing for speed, it decides whether a constant gets loaded from the literal pool with"L32R"or built from a small one using a couple of arithmetic instructions ๐งฎ The default is0.-mstrict-align,-mno-strict-alignโ these control whether GCC avoids (-mstrict-align) or allows (-mno-strict-align) memory accesses that might not line up on a natural object boundary, as the architecture spec describes ๐ The default is-mno-strict-alignfor cores that handle both unaligned loads and stores in hardware, and-mstrict-alignfor every other core ๐
โจ zSeries Options โจ
These are listed under
โจ ENVIRONMENT โจ
okay so this section is all about environment variables that change how GCC behaves ๐ Some of them point GCC at directories or prefixes to search when it's hunting for files, and others set up other aspects of the compilation environment ๐
Also, you can name search spots directly with options like -B, -I and -L ๐บ๏ธ Those take precedence over environment variables, and environment variables take precedence over whatever the GCC configuration says. Main character rules ๐
โจ LANG โจ
โจ LC_CTYPE โจ
โจ LC_MESSAGES โจ
โจ LC_ALL โจ
These variables control how GCC uses localization info so it can work with different national conventions ๐ GCC looks at the LC_CTYPE and LC_MESSAGES locale categories if it's been configured to do so. You can set these categories to any value your installation supports. A typical value is en_GB.UTF-8, which is English for the United Kingdom encoded in UTF-8 ๐ฌ๐ง
LC_CTYPEโ this one handles character classification ๐ค GCC uses it to figure out where character boundaries fall in a string. That matters for some multibyte encodings that have quote and escape characters which would otherwise be read as the end of a string or as an escape ๐ญLC_MESSAGESโ this one picks the language used in diagnostic messages ๐ฌLC_ALLโ if this is set, it overridesLC_CTYPEandLC_MESSAGES. If it isn't, thenLC_CTYPEandLC_MESSAGESdefault to the value ofLANGโจ If none of these variables are set, GCC defaults to traditional C English behavior ๐
โจ TMPDIR โจ
If TMPDIR is set, it names the directory GCC uses for temporary files ๐ GCC makes temp files to hold the output of one stage of compilation that gets fed into the next stage. For example, the preprocessor's output is the input to the compiler proper ๐ง
โจ GCC_DIAGNOSTICS_LOG โจ
If GCC_DIAGNOSTICS_LOG is set, extra info about the diagnostics subsystem gets emitted ๐ If it's set to an empty value, that info goes to stderr. Otherwise, GCC tries to open the file you named and writes the info there ๐
The exact content and format of this info can change at any time. It's meant for GCC developers rather than end-users, so don't be surprised if it looks like it's for the insiders ๐
โจ GCC_COMPARE_DEBUG โจ
Setting GCC_COMPARE_DEBUG is nearly the same as passing -fcompare-debug to the compiler driver ๐ช Check that option's documentation for more details ๐
โจ GCC_EXEC_PREFIX โจ
If GCC_EXEC_PREFIX is set, it names a prefix to use in the names of the subprograms GCC runs ๐งฉ No slash gets added when the prefix is combined with a subprogram name, but you can end your prefix with a slash if you want one ๐ฆ
If GCC_EXEC_PREFIX isn't set, GCC tries to figure out a good prefix based on the pathname it was invoked with ๐ต๏ธโโ๏ธ
If GCC can't find the subprogram using your prefix, it checks the usual places for it ๐
The default value of GCC_EXEC_PREFIX is prefix/lib/gcc/, where prefix is the prefix of the installed compiler. In lots of cases, prefix is the value of "prefix" you used when you ran the configure script โ๏ธ
Prefixes you give with -B take precedence over this one ๐
This prefix is also used for finding files like crt0.o that get used for linking ๐
It also gets used in a kind of unusual way when GCC hunts for header directories ๐ฏ For each standard directory whose name normally starts with /usr/local/lib/gcc (or, more precisely, with the value of GCC_INCLUDE_DIR), GCC tries swapping that beginning out for your prefix to make an alternate directory name. So with -Bfoo/, GCC searches foo/bar just before it searches the standard directory /usr/local/lib/bar. If a standard directory starts with the configured prefix, then the value of prefix gets replaced by GCC_EXEC_PREFIX when GCC looks for header files ๐
โจ COMPILER_PATH โจ
The value of COMPILER_PATH is a colon-separated list of directories, very much like PATH ๐ค๏ธ GCC tries these directories when searching for subprograms, but only if it can't find them using GCC_EXEC_PREFIX first ๐ซถ
โจ LIBRARY_PATH โจ
The value of LIBRARY_PATH is also a colon-separated list of directories, just like PATH ๐ When GCC is configured as a native compiler, it tries these directories when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX ๐ง Linking with GCC also uses these directories when searching for ordinary libraries for the -l option. Just remember that directories given with -L come first ๐ฅ
โจ LANG โจ
This variable passes locale info to the compiler ๐ One thing it's used for is deciding which character set to use when character literals, string literals and comments get parsed in C and C++. When the compiler is configured to allow multibyte characters, these values for LANG are recognized:
C-JISโ recognizes JIS characters ๐ฏ๐ตC-SJISโ recognizes SJIS characters ๐ฃC-EUCJPโ recognizes EUCJP characters ๐
If LANG isn't defined, or it has some other value, then the compiler uses "mblen" and "mbtowc" as defined by the default locale to recognize and translate multibyte characters ๐
โจ GCC_EXTRA_DIAGNOSTIC_OUTPUT โจ
If GCC_EXTRA_DIAGNOSTIC_OUTPUT is set to one of the following values, extra text gets emitted to stderr whenever fix-it hints are emitted ๐ฉน -fdiagnostics-parseable-fixits and -fno-diagnostics-parseable-fixits take precedence over this environment variable ๐
fixits-v1โ emits parseable fix-it hints, equivalent to-fdiagnostics-parseable-fixits๐งพ In particular, columns are expressed as a count of bytes, starting at byte 1 for the initial column ๐ขfixits-v2โ same asfixits-v1, except columns are expressed as display columns, per-fdiagnostics-column-unit=display๐
โจ EXPERIMENTAL_SARIF_SOCKET โจ
If EXPERIMENTAL_SARIF_SOCKET is set in the environment, the compiler will try to connect to a UNIX domain stream socket with that name ๐ It then sends an "OnSarifResult" JSON-RPC 2.0 notification to it for each diagnostic that occurs, where the value of the notification is a SARIF "result" object ๐จ
The compiler will fail immediately if EXPERIMENTAL_SARIF_SOCKET is set and it can't connect to it ๐
This feature is experimental and subject to change or removal without notice. Don't build your whole life on it yet ๐
Some additional environment variables affect the behavior of the preprocessor ๐งผ
โจ CPATH โจ
โจ C_INCLUDE_PATH โจ
โจ CPLUS_INCLUDE_PATH โจ
โจ OBJC_INCLUDE_PATH โจ
Each of these variables holds a list of directories, separated by a special character much like PATH, to look in for header files ๐ The special character, "PATH_SEPARATOR", depends on the target and is determined when GCC is built. For Microsoft Windows-based targets it's a semicolon, and for almost all other targets it's a colon โก
CPATH specifies a list of directories to be searched as if you'd given them with -I, but after any paths given with -I options on the command line ๐๏ธ This environment variable is used no matter which language is being preprocessed ๐
The remaining environment variables only apply when preprocessing the particular language they're named for. Each one specifies a list of directories to be searched as if you'd used -isystem, but after any paths given with -isystem options on the command line ๐งธ
In all of these variables, an empty element tells the compiler to search its current working directory ๐ Empty elements can show up at the beginning or the end of a path. For instance, if the value of CPATH is ":/special/include", that has the same effect as -I. -I/special/include ๐ซง
โจ DEPENDENCIES_OUTPUT โจ
If this variable is set, its value specifies how to output dependencies for Make, based on the non-system header files the compiler processes ๐ ๏ธ System header files get ignored in the dependency output ๐ซ
The value of DEPENDENCIES_OUTPUT can be just a file name. In that case, the Make rules are written to that file, and the target name is guessed from the source file name ๐ฏ Or the value can take the form file target, in which case the rules are written to file using target as the target name ๐
In other words, this environment variable is equivalent to combining the options -MM and -MF, with an optional -MT switch too ๐ง
โจ SUNPRO_DEPENDENCIES โจ
This variable is the same as DEPENDENCIES_OUTPUT (see above), except system header files are not ignored, so it implies -M rather than -MM ๐ However, the dependence on the main input file is omitted ๐ซฅ
โจ SOURCE_DATE_EPOCH โจ
If this variable is set, its value specifies a UNIX timestamp to use in place of the current date and time in the "__DATE__" and "__TIME__" macros ๐ฐ๏ธ That way the embedded timestamps become reproducible โป๏ธ
The value of SOURCE_DATE_EPOCH must be a UNIX timestamp, defined as the number of seconds (excluding leap seconds) since 01 Jan 1970 00:00:00, represented in ASCII. It's identical to the output of date +%s on GNU/Linux and other systems that support the %s extension in the "date" command ๐ง
The value should be a known timestamp, such as the last modification time of the source or package, and it should be set by the build process ๐๏ธ
โจ BUGS โจ
For instructions on reporting bugs, see <file:///usr/share/doc/gcc-16/README.Bugs> ๐๐ซถ
โจ FOOTNOTES โจ
- okay bestie, this one's a lil spicy ๐ถ๏ธ On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work ๐ง On multi-libbed systems,gcc -sharedhas to select the correct support libraries to link against. Skip the correct flags and you can get subtle defects ๐ but supplying them when they aren't needed is totally innocuous ๐ซถ Also,-sharedsuppresses the addition of startup code that alters the floating-point environment, which happens with-ffast-math,-Ofastor-funsafe-math-optimizationson some targets โจ
โจ SEE ALSO โจ
Go check these out, they're giving everything ๐
gpl(7),gfdl(7),fsf-funding(7),cpp(1),gcov(1),as(1),ld(1),gdb(1)- the Info entries for
gcc,cpp,as,ld,binutilsandgdb๐ฆ
โจ AUTHOR โจ
the contributors are the real MVPs ๐ Check the Info entry for gcc, or peep <https://gcc.gnu.org/onlinedocs/gcc/Contributors.html> to see everyone who helped build GCC ๐
โจ COPYRIGHT โจ
Copyright (c) 1988-2026 Free Software Foundation, Inc. ๐
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with the Invariant Sections being "GNU General Public License" and "Funding Free Software", the Front-Cover texts being (a) (see below), and with the Back-Cover Texts being (b) (see below). A copy of the license is included in the gfdl(7) man page ๐
- (a) The FSF's Front-Cover Text is:
A GNU Manual๐ - (b) The FSF's Back-Cover Text is:
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development. ๐
And that's a wrap, bestie ๐ซถ This page is from gcc-16, dated 2026-03-22. Now go be a compiler girlie ๐ โจ
๐ฆ where this page comes from
- ubuntu resolute: gcc-16-riscv64-linux-gnu 16-20260322-1ubuntu1cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms