GCC(1)
๐ gcc(1) ๐
Manual page for gcc, section 1, from the GNU project โจ
๐ NAME ๐
gcc - the GNU project C and C++ compiler ๐
โจ SYNOPSIS โจ
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
okay so the synopsis only shows the highlights ๐ for everything else, scroll on down. and g++ takes pretty much the same options as gcc, so you're not learning two whole languages here, bestie ๐ซถ
๐ DESCRIPTION ๐
okay so when you invoke GCC, it normally does preprocessing, compilation, assembly and linking, all in one go ๐ฅ the "overall options" let you stop the process at an intermediate stage. for example, -c says not to run the linker, so the output is just the object files that the assembler spat out ๐ง
other options get passed along to one or more of those stages. 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 them, and honestly that's a mercy ๐ญ
most of the command-line options you can use with GCC are for C programs. when an option is only useful with another language (usually C++), the explanation will say so explicitly. if the description doesn't mention a source language, you can use that option with all supported languages โจ
the usual way to run GCC is to run the executable called gcc, or machine-gcc when you're cross-compiling, or machine-gcc-version if you want one specific version of GCC ๐ and when you compile C++ programs, you should invoke GCC as g++ instead, no cap.
the gcc program takes options and file names as operands. a lot of options have multi-letter names, so multiple single-letter options can't be grouped together. -dv is very different from -d -v, so don't try to be clever ๐
you can mix options and other arguments. 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 gave them. also, where you put the -l option is significant ๐
a bunch of options have long names starting with -f or with -W---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 those two forms, whichever one is not the default. main character energy for the default ๐
some options take one or more arguments, usually separated from the option name by either a space or an equals sign (=). unless it's documented otherwise, an argument can be either numeric or a string. numeric arguments should typically be small unsigned decimal or hexadecimal integers, and hexadecimal arguments must begin with the 0x prefix ๐ธ
arguments to options that set a size threshold of some sort can be arbitrarily large decimal or hexadecimal integers followed by a byte size suffix. that suffix designates a multiple of bytes, like 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 arguments get called byte-size in the rest of the text. if you want 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 โจ
okay here's the big list of every option, grouped by type ๐ซถ the explanations live in the following sections, so this is just your cheat sheet to vibe-check first.
๐ฅ 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 -specs=file
-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
๐ 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
๐ง C++ Language Options ๐ง
-fabi-version=n -fno-access-control -faligned-new=n
-fno-assume-sane-operators-new-delete -fchar8_t -fcheck-new
-fconcepts -fconstexpr-depth=n -fconstexpr-cache-depth=n
-fconstexpr-loop-limit=n -fconstexpr-ops-limit=n
-fno-elide-constructors -fno-enforce-eh-specs -fno-gnu-keywords
-fno-immediate-escalation -fno-implicit-templates
-fno-implicit-inline-templates -fno-implement-inlines
-fmodule-header[=kind] -fmodule-only -fmodules
-fmodule-implicit-inline -fno-module-lazy
-fmodule-mapper=specification -fmodule-version-ignore
-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
-fno-rtti -fsized-deallocation -fstrong-eval-order[=kind]
-ftemplate-backtrace-limit=n -ftemplate-depth=n
-fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++
-fvisibility-inlines-hidden -fvisibility-ms-compat
-fext-numeric-literals -flang-info-include-translate[=header]
-flang-info-include-translate-not -flang-info-module-cmi[=module]
-stdlib=libstdc++,libc++ -Wabi-tag -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 -Weffc++
-Wno-elaborated-enum-base -Wno-exceptions -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
-Wstrict-null-sentinel -Wno-subobject-linkage -Wtemplates
-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|json|json-
stderr|json-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
-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]
๐ธ Warning Options ๐ธ
okay so this is the big warnings lineup bestie ๐ญ๐ซถ every single one of these is a flag you can toss at GCC to make it speak up about sketchy code. slay.
-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 -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 -Wno-c++11-extensions
-Wno-c++14-extensions -Wno-c++17-extensions -Wno-c++20-extensions
-Wno-c++23-extensions -Wcalloc-transposed-args -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
-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-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 -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-variable
-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
๐ฆ Static Analyzer Options ๐ฆ
the analyzer crew, bestie ๐โจ these are the flags for the static analyzer. it's giving detective energy, and every checker has its own little -Wno-analyzer-... switch if you wanna mute one. no cap, it's a lot ๐
-fanalyzer -fanalyzer-call-summaries -fanalyzer-checker=name
-fno-analyzer-feasibility -fanalyzer-fine-grained
-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 -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 only for C and Objective-C, so if you're in C++ land they just aren't it ๐ lowkey a super specific crew, but iconic for the people who need them ๐
-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
-Wnested-externs -Wold-style-declaration -Wold-style-definition
-Wstrict-prototypes -Wtraditional -Wtraditional-conversion
-Wdeclaration-after-statement -Wpointer-sign
๐ Debugging Options ๐
okay debugging era, bestie ๐ชฒ๐ these flags are all about getting GCC to tuck extra debug info into your build so your debugger can actually help you. the -g family is the main squad, and there are a ton of little knobs for DWARF, CodeView, BTF, CTF and friends. let's gooo โจ
-g -glevel -gdwarf -gdwarf-version -gbtf -gctf -gctflevel
-gprune-btf -gno-prune-btf -ggdb -grecord-gcc-switches
-gno-record-gcc-switches -gstrict-dwarf -gno-strict-dwarf
-gas-loc-support -gno-as-loc-support -gas-locview-support
-gno-as-locview-support -gcodeview -gcolumn-info -gno-column-info
-gdwarf32 -gdwarf64 -gstatement-frontiers -gno-statement-frontiers
-gvariable-location-views -gno-variable-location-views
-ginternal-reset-location-views -gno-internal-reset-location-views
-ginline-points -gno-inline-points -gvms -gz[=type] -gsplit-dwarf
-gdescribe-dies -gno-describe-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
โจ Optimization Options โจ
okay bestie, this is the big one ๐ so many flags that make your code go zoom ๐ฅ here's the whole lineup, 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-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-fdata-sections-fdce-fdelayed-branch-fdelete-null-pointer-checks-fdevirtualize-fdevirtualize-speculatively-fdevirtualize-at-ltrans-fdse-fearly-inlining-fipa-sra-fexpensive-optimizations-ffat-lto-objects-ffast-math-ffinite-math-only-ffloat-store-fexcess-precision=style-ffinite-loops-fforward-propagate-ffp-contract=style-ffunction-sections-fgcse-fgcse-after-reload-fgcse-las-fgcse-lm-fgraphite-identity-fgcse-sm-fhoist-adjacent-loads-fif-conversion-fif-conversion2-findirect-inlining-finline-stringops[=fn]-finline-functions-finline-functions-called-once-finline-limit=n-finline-small-functions-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-stack-alignment-fipa-icf-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-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-fp-int-builtin-inexact-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-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--param name=value-O-O0-O1-O2-O3-Os-Ofast-Og-Oz
โจ Program Instrumentation Options โจ
ooh, this bundle is all about watching your program's every move ๐๐
-p-pg-fprofile-arcs--coverage-ftest-coverage-fcondition-coverage-fpath-coverage-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-fbounds-check-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]
โจ Preprocessor Options โจ
the preprocessor is basically the prep team before the main event ๐ง
-Aquestion=answer-A-question[=answer]-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
โจ Assembler Options โจ
just two, but they slay ๐ซถ
-Wa,option-Xassembler option
โจ Linker Options โจ
the linker is where everything comes together, bestie ๐๐
object-file-name-fuse-ld=linker-llibrary-nostartfiles-nodefaultlibs-nolibc-nostdlib-nostdlib++-e entry--entry=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-z keyword
โจ Directory Options โจ
where the compiler goes looking for stuff ๐บ๏ธ๐ฆ
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir--embed-dir=dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--sysroot=dir
โจ Code Generation Options โจ
this is where the actual machine code gets shaped ๐ฅ๐
-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-fvisibility=[default|internal|hidden|protected]-fstrict-volatile-bitfields-fsync-libcalls-fzero-init-padding-bits=value
โจ Developer Options โจ
for the power users ๐ค๐ these are the debugging and dumping flags, so handle with care (and snacks) ๐
-dletters-dumpspecs-dumpmachine-dumpversion-dumpfullversion-fcallgraph-info[=su,da]-fchecking-fchecking=n-fdbg-cnt-list-fdbg-cnt=counter-value-list-fdisable-ipa-pass_name-fdisable-rtl-pass_name-fdisable-rtl-pass-name=range-list-fdisable-tree-pass_name-fdisable-tree-pass-name=range-list-fdump-debug-fdump-earlydebug-fdump-noaddr-fdump-unnumbered-fdump-unnumbered-links-fdump-final-insns[=file]-fdump-ipa-all-fdump-ipa-cgraph-fdump-ipa-inline-fdump-lang-all-fdump-lang-switch-fdump-lang-switch-options-fdump-lang-switch-options=filename-fdump-passes-fdump-rtl-pass-fdump-rtl-pass=filename-fdump-statistics-fdump-tree-all-fdump-tree-switch-fdump-tree-switch-options-fdump-tree-switch-options=filename-fcompare-debug[=opts]-fcompare-debug-second-fenable-kind-pass-fenable-kind-pass=range-list-fira-verbose=n-flto-report-flto-report-wpa-fmem-report-wpa-fmem-report-fpre-ipa-mem-report-fpost-ipa-mem-report-fopt-info-fopt-info-options[=file]-fmultiflags-fprofile-report-frandom-seed=string-fsched-verbose=n-fsel-sched-verbose-fsel-sched-dump-cfg-fsel-sched-pipelining-verbose-fstats-fstack-usage-ftime-report-ftime-report-details-fvar-tracking-assignments-toggle-gtoggle-print-file-name=library-print-libgcc-file-name-print-multi-directory-print-multi-lib-print-multi-os-directory-print-prog-name=program-print-search-dirs-Q-print-sysroot-print-sysroot-headers-suffix-save-temps-save-temps=cwd-save-temps=obj-time[=file]
๐ฆ Machine-Dependent Options ๐ฆ
okay so this part is the machine-specific squad ๐ every architecture gets its own little group of flags, and they only matter for their own chip family ๐ง let's go bestie ๐
โจ AArch64 Options (AArch64 Options) โจ
-mabi=nameโ slay flag ๐-mbig-endianโ big-endian drip ๐ธ-mlittle-endianโ little-endian drip ๐ธ-mgeneral-regs-onlyโ general registers only ๐-mcmodel=tinyโ tiny code model ๐ง-mcmodel=smallโ small code model ๐ง-mcmodel=largeโ large code model ๐ง-mstrict-alignโ strict alignment ๐-mno-strict-alignโ strict alignment, turned off ๐-momit-leaf-frame-pointerโ leaf frame pointer goes bye ๐-mtls-dialect=descโ desc TLS dialect ๐ฆ-mtls-dialect=traditionalโ traditional TLS dialect ๐ฆ-mtls-size=sizeโ TLS size ๐-mfix-cortex-a53-835769โ Cortex-A53 erratum fix ๐ง-mfix-cortex-a53-843419โ another Cortex-A53 fix ๐ง-mlow-precision-recip-sqrtโ low-precision reciprocal sqrt ๐งฎ-mlow-precision-sqrtโ low-precision sqrt ๐งฎ-mlow-precision-divโ low-precision division ๐งฎ-mpc-relative-literal-loadsโ PC-relative literal loads ๐-msign-return-address=scopeโ return address signing โ๏ธ-mbranch-protection=none|standard|pac-ret[+leaf +b-key]|bti|gcsโ branch protection, pick your vibe ๐ก๏ธ-mharden-sls=optsโ straight-line speculation hardening ๐ก๏ธ-march=nameโ architecture of choice ๐๏ธ-mcpu=nameโ CPU of choice ๐ง-mtune=nameโ tuning target ๐๏ธ-moverride=stringโ override string ๐-mverbose-cost-dumpโ verbose cost dump ๐-mstack-protector-guard=guardโ stack protector guard ๐ก๏ธ-mstack-protector-guard-reg=sysregโ guard system register ๐ก๏ธ-mstack-protector-guard-offset=offsetโ guard offset ๐ก๏ธ-mtrack-speculationโ speculation tracking ๐-moutline-atomicsโ outline atomics ๐ฅ-mearly-ldp-fusionโ early LDP fusion ๐-mlate-ldp-fusionโ late LDP fusion ๐-Wexperimental-fmv-targetโ experimental FMV target warning โ ๏ธ
๐ Adapteva Epiphany Options (Adapteva Epiphany Options) ๐
-mhalf-reg-fileโ half register file ๐-mprefer-short-insn-regsโ prefer short instruction registers ๐-mbranch-cost=numโ branch cost ๐ธ-mcmoveโ conditional move ๐-mnops=numโ number of nops ๐ซง-msoft-cmpsfโ soft compare for floats ๐ง-msplit-lohiโ split low and high ๐-mpost-incโ post-increment ๐-mpost-modifyโ post-modify ๐-mstack-offset=numโ stack offset ๐-mround-nearestโ round to nearest ๐ฏ-mlong-callsโ long calls ๐-mshort-callsโ short calls ๐ฑ-msmall16โ small16 ๐งธ-mfp-mode=modeโ FP mode ๐-mvect-doubleโ vector double ๐ฏ-max-vect-align=numโ max vector alignment ๐-msplit-vecmove-earlyโ split vector moves early โฉ-m1reg-regโ one reg-reg ๐ซถ
๐ AMD GCN Options (AMD GCN Options) ๐
-march=gpuโ GPU architecture ๐ฎ-mtune=gpuโ GPU tuning ๐ฎ-mstack-size=bytesโ stack size in bytes ๐
๐บ ARC Options (ARC Options) ๐บ
-mbarrel-shifterโ barrel shifter ๐-mjli-alwaysโ JLI always ๐-mcpu=cpuโ CPU pick ๐ง-mA6โ A6 ๐งฉ-mARC600โ ARC600 ๐งฉ-mA7โ A7 ๐งฉ-mARC700โ ARC700 ๐งฉ-mdpfpโ double-precision FP ๐ข-mdpfp-compactโ compact double-precision FP ๐ข-mdpfp-fastโ fast double-precision FP ๐ข-mno-dpfp-lrsrโ no DPFP LR/SR โ-meaโ extension access ๐-mno-mpyโ no multiply โ-mmul32x16โ 32x16 multiply โ๏ธ-mmul64โ 64-bit multiply โ๏ธ-matomicโ atomics โ๏ธ-mnormโ norm instruction ๐งญ-mspfpโ single-precision FP ๐ข-mspfp-compactโ compact single-precision FP ๐ข-mspfp-fastโ fast single-precision FP ๐ข-msimdโ SIMD ๐ถ-msoft-floatโ soft float ๐ง-mswapโ swap ๐-mcrcโ CRC ๐งฎ-mdsp-packaโ DSP pack-A ๐ฆ-mdvbfโ DVBF ๐งฉ-mlockโ lock ๐-mmac-d16โ MAC D16 ๐งฎ-mmac-24โ MAC 24 ๐งฎ-mrtscโ RTSC โฑ๏ธ-mswapeโ swape ๐-mtelephonyโ telephony ๐-mxyโ XY memory ๐ง-misizeโ instruction size ๐-mannotate-alignโ annotate alignment ๐-marclinuxโ ARC Linux ๐ง-marclinux_profโ ARC Linux with profiling ๐ง-mlong-callsโ long calls ๐-mmedium-callsโ medium calls ๐-msdataโ small data ๐ฆ-mirq-ctrl-savedโ IRQ control saved ๐-mrgf-banked-regsโ banked register file ๐ฆ-mlpc-width=widthโ LPC width ๐-G numโ small-data threshold ๐ฆ-mvolatile-cacheโ volatile cache ๐๏ธ-mtp-regno=regnoโ TP register number ๐ข-malign-callโ align calls ๐-mauto-modify-regโ auto-modify register ๐ง-mbbit-peepholeโ BBIT peephole ๐-mno-brccโ no BRcc โ-mcase-vector-pcrelโ PC-relative case vectors ๐งญ-mcompact-casesiโ compact casesi ๐ฆ-mno-cond-execโ no conditional execution โ-mearly-cbranchsiโ early cbranchsi โฉ-mexpand-adddiโ expand adddi โ-mindexed-loadsโ indexed loads ๐-mlraโ LRA ๐ง-mlra-priority-noneโ LRA priority none ๐ง-mlra-priority-compactโ LRA priority compact ๐ง-mlra-priority-noncompactโ LRA priority noncompact ๐ง-mmillicodeโ millicode ๐ง-mmixed-codeโ mixed code ๐จ-mq-classโ Q class ๐ท๏ธ-mRcqโ Rcq ๐ท๏ธ-mRcwโ Rcw ๐ท๏ธ-msize-level=levelโ size level ๐-mtune=cpuโ tuning CPU ๐๏ธ-mmultcost=numโ multiply cost ๐ธ-mcode-density-frameโ code density frame ๐งฑ-munalign-prob-threshold=probabilityโ unaligned probability threshold ๐ฒ-mmpy-option=multoโ multiply option ๐งฎ-mdiv-remโ divide and remainder โ-mcode-densityโ code density ๐งฑ-mll64โ LL64 ๐งฉ-mfpu=fpuโ FPU pick ๐ข-mrf16โ RF16 ๐งฉ-mbranch-indexโ branch index ๐งญ
๐จ ARM Options (ARM Options) ๐จ
-mapcs-frameโ APCS frame ๐ผ๏ธ-mno-apcs-frameโ no APCS frame โ-mabi=nameโ ABI pick ๐งพ-mapcs-stack-checkโ APCS stack check ๐-mno-apcs-stack-checkโ no APCS stack check โ-mapcs-reentrantโ APCS reentrant ๐-mno-apcs-reentrantโ no APCS reentrant โ-mgeneral-regs-onlyโ general registers only ๐-msched-prologโ scheduled prologue ๐๏ธ-mno-sched-prologโ no scheduled prologue โ-mlittle-endianโ little-endian ๐ธ-mbig-endianโ big-endian ๐ธ-mbe8โ BE-8 ๐ธ-mbe32โ BE-32 ๐ธ-mfloat-abi=nameโ float ABI ๐ง-mfp16-format=nameโ FP16 format ๐ข-mthumb-interworkโ Thumb interworking ๐-mno-thumb-interworkโ no Thumb interworking โ-mcpu=nameโ CPU pick ๐ง-march=nameโ architecture pick ๐๏ธ-mfpu=nameโ FPU pick ๐ข-mtune=nameโ tuning pick ๐๏ธ-mprint-tune-infoโ print tuning info ๐จ๏ธ-mstructure-size-boundary=nโ structure size boundary ๐-mabort-on-noreturnโ abort on noreturn ๐-mlong-callsโ long calls ๐-mno-long-callsโ no long calls โ-msingle-pic-baseโ single PIC base ๐งญ-mno-single-pic-baseโ no single PIC base โ-mpic-register=regโ PIC register ๐งญ-mnop-fun-dllimportโ nop for dllimport ๐ซง-mpoke-function-nameโ poke function name ๐-mthumbโ Thumb ๐งต-marmโ ARM mode ๐จ-mflip-thumbโ flip Thumb ๐-mtpcs-frameโ TPCS frame ๐ผ๏ธ-mtpcs-leaf-frameโ TPCS leaf frame ๐ผ๏ธ-mcaller-super-interworkingโ caller super interworking ๐-mcallee-super-interworkingโ callee super interworking ๐-mtp=nameโ TP pick ๐งต-mtls-dialect=dialectโ TLS dialect ๐ฆ-mword-relocationsโ word relocations ๐งฉ-mfix-cortex-m3-ldrdโ Cortex-M3 LDRD fix ๐ง-mfix-cortex-a57-aes-1742098โ Cortex-A57 AES fix ๐ง-mfix-cortex-a72-aes-1655431โ Cortex-A72 AES fix ๐ง-munaligned-accessโ unaligned access ๐ซธ-mneon-for-64bitsโ NEON for 64-bit ๐ถ-mslow-flash-dataโ slow flash data ๐ข-masm-syntax-unifiedโ unified assembler syntax ๐-mrestrict-itโ restrict IT ๐-mverbose-cost-dumpโ verbose cost dump ๐-mpure-codeโ pure code ๐งผ-mcmseโ CMSE ๐ก๏ธ-mfix-cmse-cve-2021-35465โ CMSE CVE fix ๐ก๏ธ-mstack-protector-guard=guardโ stack protector guard ๐ก๏ธ-mstack-protector-guard-offset=offsetโ guard offset ๐ก๏ธ-mfdpicโ FDPIC ๐งญ-mbranch-protection=none|standard|pac-ret[+leaf]โ branch protection, pick your vibe ๐ก๏ธ[+bti]|bti[+pac-ret[+leaf]]โ the rest of the branch protection combos ๐ก๏ธ
โก AVR Options (AVR Options) โก
-mmcu=mcuโ MCU pick ๐ง-mabsdataโ absolute data ๐ฆ-maccumulate-argsโ accumulate args ๐-mcvtโ CVT ๐-mbranch-cost=costโ branch cost ๐ธ-mfuse-add=levelโ fuse add level โ-mfuse-move=levelโ fuse move level โก๏ธ-mfuse-move2โ fuse move 2 โก๏ธ-mcall-prologuesโ call prologues ๐๏ธ-mgas-isr-prologuesโ GAS ISR prologues ๐๏ธ-mint8โ int8 ๐ข-mflmapโ flmap ๐บ๏ธ-mdouble=bitsโ double width ๐ข-mlong-double=bitsโ long double width ๐ข-mno-call-mainโ no call to main โ-mn_flash=sizeโ flash size ๐๏ธ-mfract-convert-truncateโ fract convert truncate โ๏ธ-mno-interruptsโ no interrupts โ-mmain-is-OS_taskโ main is an OS task ๐งต-mrelaxโ relax ๐ง-mrmwโ read-modify-write โ๏ธ-mstrict-Xโ strict X ๐งญ-mtiny-stackโ tiny stack ๐งธ-mrodata-in-ramโ rodata in RAM ๐ง-msplit-bit-shiftโ split bit shift โ๏ธ-msplit-ldstโ split load/store ๐ฆ-mshort-callsโ short calls ๐ฑ-mskip-bugโ skip bug ๐-muse-nonzero-bitsโ use nonzero bits ๐ฏ-nodevicelibโ no device library ๐ซ-nodevicespecsโ no device specs ๐ซ-Waddr-space-convertโ address space convert warning โ ๏ธ-Wmisspelled-isrโ misspelled ISR warning โ ๏ธ
๐ต Blackfin Options (Blackfin Options) ๐ต
-mcpu=cpu[-sirevision]โ CPU and silicon revision ๐ง-msimโ simulator ๐ฎ-momit-leaf-frame-pointerโ leaf frame pointer goes bye ๐-mno-omit-leaf-frame-pointerโ leaf frame pointer stays ๐ซถ-mspecld-anomalyโ speculative load anomaly ๐-mno-specld-anomalyโ no speculative load anomaly โ-mcsync-anomalyโ CSYNC anomaly ๐-mno-csync-anomalyโ no CSYNC anomaly โ-mlow-64kโ low 64k ๐ง-mno-low64kโ no low 64k โ-mstack-check-l1โ stack check L1 ๐-mid-shared-libraryโ ID shared library ๐-mno-id-shared-libraryโ no ID shared library โ-mshared-library-id=nโ shared library ID ๐ข-mleaf-id-shared-libraryโ leaf ID shared library ๐-mno-leaf-id-shared-libraryโ no leaf ID shared library โ-msep-dataโ separate data ๐งฉ-mno-sep-dataโ no separate data โ-mlong-callsโ long calls ๐-mno-long-callsโ no long calls โ-mfast-fpโ fast FP ๐-minline-pltโ inline PLT ๐งต-mmulticoreโ multicore ๐ง-mcoreaโ core A ๐ ฐ๏ธ-mcorebโ core B ๐ ฑ๏ธ-msdramโ SDRAM ๐๏ธ-micplbโ ICPLB ๐งฑ
๐งฉ C6X Options (C6X Options) ๐งฉ
-mbig-endianโ big-endian ๐ธ-mlittle-endianโ little-endian ๐ธ-march=cpuโ architecture pick ๐๏ธ-msimโ simulator ๐ฎ-msdata=sdata-typeโ small data type ๐ฆ
๐ฆ CRIS Options (CRIS Options) ๐ฆ
-mcpu=cpuโ CPU pick ๐ง-march=cpuโ architecture pick ๐๏ธ-mtune=cpuโ tuning pick ๐๏ธ-mmax-stack-frame=nโ max stack frame size ๐-metrax4โ ETRAX 4 ๐งฉ-metrax100โ ETRAX 100 ๐งฉ-mpdebugโ P-debug ๐-mcc-initโ CC init ๐งญ-mno-side-effectsโ no side effects โ-mstack-alignโ stack alignment ๐-mdata-alignโ data alignment ๐-mconst-alignโ constant alignment ๐-m32-bitโ 32-bit ๐ข-m16-bitโ 16-bit ๐ข-m8-bitโ 8-bit ๐ข-mno-prologue-epilogueโ no prologue or epilogue โ-melfโ ELF ๐งพ-maoutโ a.out ๐งพ-simโ simulator ๐ฎ-sim2โ simulator 2 ๐ฎ-mmul-bug-workaroundโ multiply bug workaround ๐-mno-mul-bug-workaroundโ no multiply bug workaround โ
๐ C-SKY Options (C-SKY Options) ๐
-march=archโ architecture pick ๐๏ธ-mcpu=cpuโ CPU pick ๐ง-mbig-endianโ big-endian ๐ธ-EBโ big-endian, the short way ๐ธ-mlittle-endianโ little-endian ๐ธ-ELโ little-endian, the short way ๐ธ-mhard-floatโ hard float ๐ง-msoft-floatโ soft float ๐ง-mfpu=fpuโ FPU pick ๐ข-mdouble-floatโ double float ๐ข-mfdivduโ FDIVDU โ-mfloat-abi=nameโ float ABI ๐ง-melrwโ ELRW ๐งฉ-mistackโ interrupt stack ๐-mmpโ MP ๐งต-mcpโ CP ๐งฉ-mcacheโ cache ๐๏ธ-msecurityโ security ๐ก๏ธ-mtrustโ trust ๐ก๏ธ-mdspโ DSP ๐ถ-medspโ enhanced DSP ๐ถ-mvdspโ vector DSP ๐ถ-mdivโ divide โ-msmartโ smart mode ๐ง-mhigh-registersโ high registers ๐๏ธ-manchorโ anchor ๐งญ-mpushpopโ push and pop ๐-mmultiple-stldโ multiple load/store ๐ฆ-mconstpoolโ constant pool ๐งบ-mstack-sizeโ stack size ๐-mccrtโ CCRT ๐งฉ-mbranch-cost=nโ branch cost ๐ธ-mcse-ccโ CSE CC ๐-msched-prologโ scheduled prologue ๐๏ธ-msimโ simulator ๐ฎ
๐ช Cygwin and MinGW Options (Cygwin and MinGW Options) ๐ช
-mconsoleโ console ๐ฅ๏ธ-mcrtdll=libraryโ CRT DLL library ๐-mdllโ DLL ๐งฉ-mnop-fun-dllimportโ nop for dllimport ๐ซง-mthreadโ thread ๐งต-municodeโ Unicode ๐ค-mwin32โ Win32 ๐ช-mwindowsโ Windows ๐ช-fno-set-stack-executableโ no executable stack setting ๐ซ
๐ Darwin Options (Darwin Options) ๐
-all_loadโ all load ๐ฅ-allowable_clientโ allowable client ๐งโ๐คโ๐ง-archโ arch ๐๏ธ-arch_errors_fatalโ arch errors fatal ๐-arch_onlyโ arch only ๐๏ธ-bind_at_loadโ bind at load ๐-bundleโ bundle ๐ฆ-bundle_loaderโ bundle loader ๐ฆ-client_nameโ client name ๐ท๏ธ-compatibility_versionโ compatibility version ๐ข-current_versionโ current version ๐ข-dead_stripโ dead strip โ๏ธ-dependency-fileโ dependency file ๐-dylib_fileโ dylib file ๐-dylinker_install_nameโ dylinker install name ๐ท๏ธ-dynamicโ dynamic ๐-dynamiclibโ dynamic library ๐-exported_symbols_listโ exported symbols list ๐-filelistโ file list ๐-flat_namespaceโ flat namespace ๐๏ธ-force_cpusubtype_ALLโ force CPU subtype ALL ๐ง-force_flat_namespaceโ force flat namespace ๐๏ธ-headerpad_max_install_namesโ header pad for install names ๐-iframeworkโ include framework ๐-image_baseโ image base ๐ผ๏ธ-initโ init ๐ฑ-install_nameโ install name ๐ท๏ธ-keep_private_externsโ keep private externs ๐-multi_moduleโ multi-module ๐งฉ-multiply_definedโ multiply defined ๐-multiply_defined_unusedโ multiply defined unused ๐-noall_loadโ no all load โ-no_dead_strip_inits_and_termsโ no dead stripping of inits and terms ๐ซ-nodefaultrpathsโ no default rpaths ๐ซ-nofixprebindingโ no fix prebinding ๐ซ-nomultidefsโ no multidefs ๐ซ-noprebindโ no prebind ๐ซ-noseglinkeditโ no segment link edit ๐ซ-pagezero_sizeโ page zero size ๐-prebindโ prebind ๐-prebind_all_twolevel_modulesโ prebind all two-level modules ๐-private_bundleโ private bundle ๐-read_only_relocsโ read-only relocs ๐-sectalignโ section align ๐-sectobjectsymbolsโ section object symbols ๐งพ-whyloadโ why load โ-seg1addrโ segment 1 address ๐-sectcreateโ section create ๐งฑ-sectobjectsymbolsโ section object symbols ๐งพ-sectorderโ section order ๐-segaddrโ segment address ๐-segs_read_only_addrโ segments read-only address ๐-segs_read_write_addrโ segments read-write address ๐-seg_addr_tableโ segment address table ๐๏ธ-seg_addr_table_filenameโ segment address table filename ๐-seglinkeditโ segment link edit ๐-segprotโ segment protection ๐ก๏ธ-segs_read_only_addrโ segments read-only address ๐-segs_read_write_addrโ segments read-write address ๐-single_moduleโ single module ๐งฉ-staticโ static ๐งฑ-sub_libraryโ sub library ๐-sub_umbrellaโ sub umbrella โ๏ธ-twolevel_namespaceโ two-level namespace ๐๏ธ-umbrellaโ umbrella โ๏ธ-undefinedโ undefined โ-unexported_symbols_listโ unexported symbols list ๐-weak_reference_mismatchesโ weak reference mismatches โ ๏ธ-whatsloadedโ what's loaded ๐-Fโ framework path ๐-gusedโ gused ๐งพ-gfullโ gfull ๐งพ-mmacosx-version-min=versionโ minimum macOS version ๐-mkernelโ kernel ๐ง-mone-byte-boolโ one-byte bool ๐ข
๐งญ DEC Alpha Options (DEC Alpha Options) ๐งญ
-mno-fp-regsโ no FP registers โ-msoft-floatโ soft float ๐ง-mieeeโ IEEE ๐ข-mieee-with-inexactโ IEEE with inexact ๐ข-mieee-conformantโ IEEE conformant ๐ข-mfp-trap-mode=modeโ FP trap mode ๐ชค-mfp-rounding-mode=modeโ FP rounding mode ๐ฏ-mtrap-precision=modeโ trap precision ๐ฏ-mbuild-constantsโ build constants ๐งฑ-mcpu=cpu-typeโ CPU type pick ๐ง-mtune=cpu-typeโ tuning CPU type ๐๏ธ-mbwxโ BWX ๐งฉ-mmaxโ MAX ๐งฉ-mfixโ FIX ๐งฉ-mcixโ CIX ๐งฉ-msafe-bwaโ safe BWA ๐ก๏ธ-msafe-partialโ safe partial ๐ก๏ธ-mfloat-vaxโ VAX float ๐ง-mfloat-ieeeโ IEEE float ๐ง-mexplicit-relocsโ explicit relocs ๐งฉ-msmall-dataโ small data ๐ฆ-mlarge-dataโ large data ๐ฆ-msmall-textโ small text ๐ฆ-mlarge-textโ large text ๐ฆ-mmemory-latency=timeโ memory latency ๐ฐ๏ธ
๐ eBPF Options (eBPF Options) ๐
-mbig-endianโ big-endian ๐ธ-mlittle-endianโ little-endian ๐ธ-mframe-limit=bytesโ frame limit in bytes ๐-mxbpfโ XBPF ๐งฉ-mco-reโ CO-RE ๐งฉ-mno-co-reโ no CO-RE โ-mjmpextโ jump extension โฉ-mjmp32โ 32-bit jumps โฉ-malu32โ ALU32 โ-mv3-atomicsโ v3 atomics โ๏ธ-mbswapโ byte swap ๐-msdivโ signed divide โ-msmovโ signed move โก๏ธ-mcpu=versionโ CPU version ๐ง-masm=dialectโ assembler dialect ๐-minline-memops-threshold=bytesโ inline memops threshold ๐
๐ฆ FR30 Options (FR30 Options) ๐ฆ
-msmall-modelโ small model ๐งธ-mno-lsimโ no LSIM โ
๐ท FT32 Options (FT32 Options) ๐ท
-msimโ simulator ๐ฎ-mlraโ LRA ๐ง-mnodivโ no divide โ-mft32bโ FT32B ๐งฉ-mcompressโ compress ๐๏ธ-mnopmโ no PM โ
๐ FRV Options (FRV Options) ๐
-mgpr-32โ 32 GPRs ๐ข-mgpr-64โ 64 GPRs ๐ข-mfpr-32โ 32 FPRs ๐ข-mfpr-64โ 64 FPRs ๐ข-mhard-floatโ hard float ๐ง-msoft-floatโ soft float ๐ง-malloc-ccโ alloc CC ๐งญ-mfixed-ccโ fixed CC ๐งญ-mdwordโ doubleword ๐ข-mno-dwordโ no doubleword โ-mdoubleโ double ๐ข-mno-doubleโ no double โ-mmediaโ media ๐ถ-mno-mediaโ no media โ-mmuladdโ multiply-add โ๏ธ-mno-muladdโ no multiply-add โ-mfdpicโ FDPIC ๐งญ-minline-pltโ inline PLT ๐งต-mgprel-roโ GP-relative read-only ๐-multilib-library-picโ multilib library PIC ๐-mlinked-fpโ linked frame pointer ๐-mlong-callsโ long calls ๐-malign-labelsโ align labels ๐-mlibrary-picโ library PIC ๐-macc-4โ ACC 4 ๐งฉ-macc-8โ ACC 8 ๐งฉ-mpackโ pack ๐ฆ-mno-packโ no pack โ-mno-eflagsโ no eflags โ-mcond-moveโ conditional move ๐-mno-cond-moveโ no conditional move โ-moptimize-membarโ optimize membar ๐งน-mno-optimize-membarโ no membar optimization โ-msccโ SCC ๐งฉ-mno-sccโ no SCC โ-mcond-execโ conditional execution ๐๏ธ-mno-cond-execโ no conditional execution โ-mvliw-branchโ VLIW branch ๐ง-mno-vliw-branchโ no VLIW branch โ-mmulti-cond-execโ multi conditional execution ๐๏ธ-mno-multi-cond-execโ no multi conditional execution โ-mnested-cond-execโ nested conditional execution ๐ช-mno-nested-cond-execโ no nested conditional execution โ-mtomcat-statsโ Tomcat stats ๐-mTLSโ TLS ๐ฆ-mtlsโ TLS ๐ฆ-mcpu=cpuโ CPU pick ๐ง
๐ง GNU/Linux Options (GNU/Linux Options) ๐ง
-mglibcโ glibc ๐ง-muclibcโ uClibc ๐ง-mmuslโ musl ๐ง-mbionicโ Bionic ๐ค-mandroidโ Android ๐ค-tno-android-ccโ no Android CC โ-tno-android-ldโ no Android LD โ
๐น๏ธ H8/300 Options (H8/300 Options) ๐น๏ธ
-mrelaxโ relax ๐ง-mhโ H ๐ค-msโ S ๐ค-mnโ N ๐ค-mexrโ EXR ๐งฉ-mno-exrโ no EXR โ-mint32โ int32 ๐ข-malign-300โ align 300 ๐
๐งฑ HPPA Options (HPPA Options) ๐งฑ
-march=architecture-typeโ architecture type ๐๏ธ-matomic-libcallsโ atomic libcalls โ๏ธ-mbig-switchโ big switch ๐-mcaller-copiesโ caller copies ๐-mdisable-fpregsโ disable FP registers ๐ซ-mdisable-indexingโ disable indexing ๐ซ-morderedโ ordered ๐-mfast-indirect-callsโ fast indirect calls ๐-mgasโ GAS ๐งฉ-mgnu-ldโ GNU ld ๐งฉ-mhp-ldโ HP ld ๐งฉ-mfixed-range=register-rangeโ fixed register range ๐-mcoherent-ldcwโ coherent LDCW ๐งฒ-mjump-in-delayโ jump in delay slot โฉ-mlinker-optโ linker optimization ๐งน-mlong-callsโ long calls ๐-mlong-load-storeโ long load/store ๐ฆ-mno-atomic-libcallsโ no atomic libcalls โ-mno-disable-fpregsโ no disabling FP registers โ-mno-disable-indexingโ no disabling indexing โ-mno-fast-indirect-callsโ no fast indirect calls โ-mno-gasโ no GAS โ-mno-jump-in-delayโ no jump in delay slot โ-mno-long-load-storeโ no long load/store โ-mno-portable-runtimeโ no portable runtime โ-mno-soft-floatโ no soft float โ-mno-space-regsโ no space registers โ-msoft-floatโ soft float ๐ง-mpa-risc-1-0โ PA-RISC 1.0 ๐งฑ-mpa-risc-1-1โ PA-RISC 1.1 ๐งฑ-mpa-risc-2-0โ PA-RISC 2.0 ๐งฑ-mportable-runtimeโ portable runtime ๐ฑ-mschedule=cpu-typeโ schedule CPU type ๐๏ธ-mspace-regsโ space registers ๐-msoft-multโ soft multiply โ๏ธ-msioโ SIO ๐งฉ-mwsioโ WSIO ๐งฉ-munix=unix-stdโ UNIX standard ๐งพ-nolibdldโ no libdld ๐ซ-staticโ static ๐งฑ-threadsโ threads ๐งต
๐๏ธ IA-64 Options (IA-64 Options) ๐๏ธ
-mbig-endianโ big-endian ๐ธ-mlittle-endianโ little-endian ๐ธ-mgnu-asโ GNU as ๐งฉ-mgnu-ldโ GNU ld ๐งฉ-mno-picโ no PIC โ-mvolatile-asm-stopโ volatile asm stop ๐-mregister-namesโ register names ๐ท๏ธ-msdataโ small data ๐ฆ-mno-sdataโ no small data โ-mconstant-gpโ constant GP ๐งญ-mauto-picโ auto PIC ๐งญ-mfused-maddโ fused multiply-add โ๏ธ-minline-float-divide-min-latencyโ inline float divide, min latency โ-minline-float-divide-max-throughputโ inline float divide, max throughput โ-mno-inline-float-divideโ no inline float divide โ-minline-int-divide-min-latencyโ inline int divide, min latency โ-minline-int-divide-max-throughputโ inline int divide, max throughput โ-mno-inline-int-divideโ no inline int divide โ-minline-sqrt-min-latencyโ inline sqrt, min latency ๐งฎ-minline-sqrt-max-throughputโ inline sqrt, max throughput ๐งฎ-mno-inline-sqrtโ no inline sqrt โ-mdwarf2-asmโ DWARF2 asm ๐งพ-mearly-stop-bitsโ early stop bits ๐-mfixed-range=register-rangeโ fixed register range ๐-mtls-size=tls-sizeโ TLS size ๐-mtune=cpu-typeโ tuning CPU type ๐๏ธ-milp32โ ILP32 ๐ข-mlp64โ LP64 ๐ข-msched-br-data-specโ branch data speculation ๐ฎ-msched-ar-data-specโ AR data speculation ๐ฎ-msched-control-specโ control speculation ๐ฎ-msched-br-in-data-specโ branch in data speculation ๐ฎ-msched-ar-in-data-specโ AR in data speculation ๐ฎ-msched-in-control-specโ in-control speculation ๐ฎ-msched-spec-ldcโ speculative LDC ๐ฎ-msched-spec-control-ldcโ speculative control LDC ๐ฎ-msched-prefer-non-data-spec-insnsโ prefer non-data-speculative insns ๐ฏ-msched-prefer-non-control-spec-insnsโ prefer non-control-speculative insns ๐ฏ-msched-stop-bits-after-every-cycleโ stop bits after every cycle ๐-msched-count-spec-in-critical-pathโ count speculation in critical path ๐งฎ-msel-sched-dont-check-control-specโ selective scheduler, skip control spec check ๐-msched-fp-mem-deps-zero-costโ FP memory deps at zero cost ๐ธ-msched-max-memory-insns-hard-limitโ max memory insns hard limit ๐-msched-max-memory-insns=max-insnsโ max memory insns ๐ข
๐ง LM32 Options (LM32 Options) ๐ง
-mbarrel-shift-enabledโ barrel shift enabled ๐-mdivide-enabledโ divide enabled โ-mmultiply-enabledโ multiply enabled โ๏ธ-msign-extend-enabledโ sign extend enabled โ-muser-enabledโ user enabled ๐ซถ
Okay bestie, this is the machine-specific flag pile, so grab a snack ๐ Each target gets its own little drawer, and the page just lists the flags with no fine print, so I'm keeping it exactly as-is ๐
๐ฆ LoongArch Options ๐ฆ
-march=arch-type -mtune=tune-type -mabi=base-abi-type -mfpu=fpu-type
-msimd=simd-type -msoft-float -msingle-float -mdouble-float -mlsx -mno-lsx
-mlasx -mno-lasx -mbranch-cost=n -maddr-reg-reg-cost=n
-mcheck-zero-division -mno-check-zero-division -mcond-move-int
-mno-cond-move-int -mcond-move-float -mno-cond-move-float -memcpy
-mno-memcpy -mstrict-align -mno-strict-align -G num
-mmax-inline-memcpy-size=n -mexplicit-relocs=style -mexplicit-relocs
-mno-explicit-relocs -mdirect-extern-access -mno-direct-extern-access
-mcmodel=code-model -mrelax -mpass-mrelax-to-as -mrecip -mrecip=opt
-mfrecipe -mno-frecipe -mdiv32 -mno-div32 -mlam-bh -mno-lam-bh -mlamcas
-mno-lamcas -mld-seq-sa -mno-ld-seq-sa -mtls-dialect=opt
-mannotate-tablejump -mno-annotate-tablejump
๐ธ M32C Options ๐ธ
-mcpu=cpu -msim -memregs=number
๐ง M32R/D Options ๐ง
-m32r2 -m32rx -m32r -mdebug -malign-loops -mno-align-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 ๐
-march=arch -mcpu=cpu -mtune=tune -m68000 -m68020 -m68020-40 -m68020-60
-m68030 -m68040 -m68060 -mcpu32 -m5200 -m5206e -m528x -m5307 -m5407
-mcfv4e -mbitfield -mno-bitfield -mc68000 -mc68020 -mnobitfield -mrtd
-mno-rtd -mdiv -mno-div -mshort -mno-short -mhard-float -m68881
-msoft-float -mpcrel -malign-int -mstrict-align -msep-data -mno-sep-data
-mshared-library-id=n -mid-shared-library -mno-id-shared-library -mxgot
-mno-xgot -mlong-jump-table-offsets
๐ MCore Options ๐
-mhardlit -mno-hardlit -mdiv -mno-div -mrelax-immediates
-mno-relax-immediates -mwide-bitfields -mno-wide-bitfields
-m4byte-functions -mno-4byte-functions -mcallgraph-data
-mno-callgraph-data -mslow-bytes -mno-slow-bytes -mno-lsim -mlittle-endian
-mbig-endian -m210 -m340 -mstack-increment
๐ฅ MicroBlaze Options ๐ฅ
-msoft-float -mhard-float -msmall-divides -mcpu=cpu -mmemcpy
-mxl-soft-mul -mxl-soft-div -mxl-barrel-shift -mxl-pattern-compare
-mxl-stack-check -mxl-gp-opt -mno-clearbss -mxl-multiply-high
-mxl-float-convert -mxl-float-sqrt -mbig-endian -mlittle-endian
-mxl-reorder -mxl-mode-app-model -mpic-data-is-text-relative
๐ MIPS Options ๐
Lowkey the biggest drawer in the whole closet, so let's gooo โจ
-EL -EB -march=arch -mtune=arch -mips1 -mips2 -mips3 -mips4 -mips32
-mips32r2 -mips32r3 -mips32r5 -mips32r6 -mips64 -mips64r2 -mips64r3
-mips64r5 -mips64r6 -mips16 -mno-mips16 -mflip-mips16
-minterlink-compressed -mno-interlink-compressed -minterlink-mips16
-mno-interlink-mips16 -mabi=abi -mabicalls -mno-abicalls -mshared
-mno-shared -mplt -mno-plt -mxgot -mno-xgot -mgp32 -mgp64 -mfp32 -mfpxx
-mfp64 -mhard-float -msoft-float -mno-float -msingle-float
-mdouble-float -modd-spreg -mno-odd-spreg -mabs=mode -mnan=encoding -mdsp
-mno-dsp -mdspr2 -mno-dspr2 -mmcu -mmno-mcu -meva -mno-eva -mvirt
-mno-virt -mxpa -mno-xpa -mcrc -mno-crc -mginv -mno-ginv -mmicromips
-mno-micromips -mmsa -mno-msa -mloongson-mmi -mno-loongson-mmi
-mloongson-ext -mno-loongson-ext -mloongson-ext2 -mno-loongson-ext2
-mfpu=fpu-type -msmartmips -mno-smartmips -mpaired-single
-mno-paired-single -mdmx -mno-mdmx -mips3d -mno-mips3d -mmt -mno-mt
-mllsc -mno-llsc -mlong64 -mlong32 -msym32 -mno-sym32 -Gnum -mlocal-sdata
-mno-local-sdata -mextern-sdata -mno-extern-sdata -mgpopt -mno-gopt
-membedded-data -mno-embedded-data -muninit-const-in-rodata
-mno-uninit-const-in-rodata -mcode-readable=setting -msplit-addresses
-mno-split-addresses -mexplicit-relocs -mno-explicit-relocs
-mexplicit-relocs=release -mcheck-zero-division -mno-check-zero-division
-mdivide-traps -mdivide-breaks -mload-store-pairs -mno-load-store-pairs
-mstrict-align -mno-strict-align -mno-unaligned-access -munaligned-access
-mmemcpy -mno-memcpy -mlong-calls -mno-long-calls -mmad -mno-mad -mimadd
-mno-imadd -mfused-madd -mno-fused-madd -nocpp -mfix-24k -mno-fix-24k
-mfix-r4000 -mno-fix-r4000 -mfix-r4400 -mno-fix-r4400 -mfix-r5900
-mno-fix-r5900 -mfix-r10000 -mno-fix-r10000 -mfix-rm7000 -mno-fix-rm7000
-mfix-vr4120 -mno-fix-vr4120 -mfix-vr4130 -mno-fix-vr4130 -mfix-sb1
-mno-fix-sb1 -mflush-func=func -mno-flush-func -mbranch-cost=num
-mbranch-likely -mno-branch-likely -mcompact-branches=policy
-mfp-exceptions -mno-fp-exceptions -mvr4130-align -mno-vr4130-align
-msynci -mno-synci -mlxc1-sxc1 -mno-lxc1-sxc1 -mmadd4 -mno-madd4
-mrelax-pic-calls -mno-relax-pic-calls -mmcount-ra-address
-mframe-header-opt -mno-frame-header-opt
๐ MMIX Options ๐
-mlibfuncs -mno-libfuncs -mepsilon -mno-epsilon -mabi=gnu -mabi=mmixware
-mzero-extend -mknuthdiv -mtoplevel-symbols -melf -mbranch-predict
-mno-branch-predict -mbase-addresses -mno-base-addresses -msingle-exit
-mno-single-exit
๐ซถ MN10300 Options ๐ซถ
-mmult-bug -mno-mult-bug -mno-am33 -mam33 -mam33-2 -mam34 -mtune=cpu-type
-mreturn-pointer-on-d0 -mno-crt0 -mrelax -mliw -msetlb
๐ Moxie Options ๐
-meb -mel -mmul.x -mno-crt0
โญ MSP430 Options โญ
-msim -masm-hex -mmcu= -mcpu= -mlarge -msmall -mrelax -mwarn-mcu
-mcode-region= -mdata-region= -msilicon-errata= -msilicon-errata-warn=
-mhwmult= -minrt -mtiny-printf -mmax-inline-shift=
๐ฆ NDS32 Options ๐ฆ
-mbig-endian -mlittle-endian -mreduced-regs -mfull-regs -mcmov -mno-cmov
-mext-perf -mno-ext-perf -mext-perf2 -mno-ext-perf2 -mext-string
-mno-ext-string -mv3push -mno-v3push -m16bit -mno-16bit
-misr-vector-size=num -mcache-block-size=num -march=arch
-mcmodel=code-model -mctor-dtor -mrelax
๐ Nvidia PTX Options ๐
-m64 -mmainkernel -moptimize
๐ธ OpenRISC Options ๐ธ
-mboard=name -mnewlib -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 ๐ง
-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 -mint32 -mno-int16
-mint16 -mno-int32 -msplit -munix-asm -mdec-asm -mgnu-asm -mlra
๐ PowerPC Options ๐
See RS/6000 and PowerPC Options.
๐ PRU Options ๐
-mmcu=mcu -minrt -mno-relax -mloop -mabi=variant
๐ฅ RISC-V Options ๐ฅ
-mbranch-cost=N-instruction -mplt -mno-plt -mabi=ABI-string -mfdiv
-mno-fdiv -mfence-tso -mno-fence-tso -mdiv -mno-div -misa-spec=ISA-spec-string
-march=ISA-string -mtune=processor-string -mpreferred-stack-boundary=num
-msmall-data-limit=N-bytes -msave-restore -mno-save-restore
-mshorten-memrefs -mno-shorten-memrefs -mstrict-align -mno-strict-align
-mcmodel=medlow -mcmodel=medany -mcmodel=large -mexplicit-relocs
-mno-explicit-relocs -mrelax -mno-relax -mriscv-attribute
-mno-riscv-attribute -malign-data=type -mbig-endian -mlittle-endian
-mstack-protector-guard=guard -mstack-protector-guard-reg=reg
-mstack-protector-guard-offset=offset -mcsr-check -mno-csr-check
-mmovcc -mno-movcc -minline-atomics -mno-inline-atomics -minline-strlen
-mno-inline-strlen -minline-strcmp -mno-inline-strcmp -minline-strncmp
-mno-inline-strncmp -mtls-dialect=desc -mtls-dialect=trad
๐ RL78 Options ๐
-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs -mcpu=g10 -mcpu=g13
-mcpu=g14 -mg10 -mg13 -mg14 -m64bit-doubles -m32bit-doubles
-msave-mduc-in-interrupts
โจ RS/6000 and PowerPC Options โจ
Last drawer in this part, and it's a whole vibe ๐
-mcpu=cpu-type -mtune=cpu-type -mcmodel=code-model -mpowerpc64 -maltivec
-mno-altivec -mpowerpc-gpopt -mno-powerpc-gpopt -mpowerpc-gfxopt
-mno-powerpc-gfxopt -mmfcrf -mno-mfcrf -mpopcntb -mno-popcntb -mpopcntd
-mno-popcntd -mfprnd -mno-fprnd -mcmpb -mno-cmpb -mhard-dfp -mno-hard-dfp
-mfull-toc -mminimal-toc -mno-fp-in-toc -mno-sum-in-toc -m64 -m32
-mxl-compat -mno-xl-compat -mpe -malign-power -malign-natural
-msoft-float -mhard-float -mmultiple -mno-multiple -mupdate -mno-update
-mavoid-indexed-addresses -mno-avoid-indexed-addresses -mfused-madd
-mno-fused-madd -mbit-align -mno-bit-align -mstrict-align -mno-strict-align
-mrelocatable -mno-relocatable -mrelocatable-lib -mno-relocatable-lib
-mtoc -mno-toc -mlittle -mlittle-endian -mbig -mbig-endian
-mdynamic-no-pic -mswdiv -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 -mlongcall
-mno-longcall -mpltseq -mno-pltseq -mblock-move-inline-limit=num
-mblock-compare-inline-limit=num -mblock-compare-inline-loop-limit=num
-mno-block-ops-unaligned-vsx -mstring-compare-inline-limit=num -misel
-mno-isel -mvrsave -mno-vrsave -mmulhw -mno-mulhw -mdlmzb -mno-dlmzb
-mprototype -mno-prototype -msim -mmvme -mads -myellowknife -memb -msdata
-msdata=opt -mreadonly-in-sdata -mvxworks -G num -mrecip -mrecip=opt
-mno-recip -mrecip-precision -mno-recip-precision -mveclibabi=type -mfriz
-mno-friz -mpointers-to-nested-functions -mno-pointers-to-nested-functions
-msave-toc-indirect -mno-save-toc-indirect -mpower8-fusion
-mno-mpower8-fusion -mcrypto -mno-crypto -mhtm -mno-htm -mquad-memory
-mno-quad-memory -mquad-memory-atomic -mno-quad-memory-atomic
-mcompat-align-parm -mno-compat-align-parm -mfloat128 -mno-float128
-mfloat128-hardware -mno-float128-hardware -mgnu-attribute
-mno-gnu-attribute -mstack-protector-guard=guard
-mstack-protector-guard-reg=reg -mstack-protector-guard-offset=offset
-mprefixed -mno-prefixed -mpcrel -mno-pcrel -mmma -mno-mmma -mrop-protect
-mno-rop-protect -mprivileged -mno-privileged
๐ RX Options ๐
okay so RX has its own little squad of options, bestie ๐ -m64bit-doubles -m32bit-doubles -fpu -nofpu -mcpu= -mbig-endian-data -mlittle-endian-data -msmall-data -msim -mno-sim -mas100-syntax -mno-as100-syntax -mrelax -mmax-constant-size= -mint-register= -mpid -mallow-string-insns -mno-allow-string-insns -mjsr -mno-warn-multiple-fast-interrupts -msave-acc-in-interrupts ๐ง
โจ S/390 and zSeries Options โจ
this one is giving big mainframe energy ๐
-mtune=cpu-type -march=cpu-type -mhard-float -msoft-float -mhard-dfp -mno-hard-dfp -mlong-double-64 -mlong-double-128 -mbackchain -mno-backchain -mpacked-stack -mno-packed-stack -msmall-exec -mno-small-exec -mmvcle -mno-mvcle -m64 -m31 -mdebug -mno-debug -mesa -mzarch -mhtm -mvx -mzvector -mtpf-trace -mno-tpf-trace -mtpf-trace-skip -mno-tpf-trace-skip -mfused-madd -mno-fused-madd -mwarn-framesize -mwarn-dynamicstack -mstack-size -mstack-guard -mhotpatch=halfwords,halfwords ๐ฅ
๐ฆ SH Options ๐ฆ
SH has a whole lineup, no cap ๐ญ -m1 -m2 -m2e -m2a-nofpu -m2a-single-only -m2a-single -m2a -m3 -m3e -m4-nofpu -m4-single-only -m4-single -m4 -m4a-nofpu -m4a-single-only -m4a-single -m4a -m4al -mb -ml -mdalign -mrelax -mbigtable -mfmovd -mrenesas -mno-renesas -mnomacsave -mieee -mno-ieee -mbitops -misize -minline-ic_invalidate -mpadstruct -mprefergot -musermode -multcost=number -mdiv=strategy -mdivsi3_libfunc=name -mfixed-range=register-range -maccumulate-outgoing-args -matomic-model=atomic-model -mbranch-cost=num -mzdcbranch -mno-zdcbranch -mcbranch-force-delay-slot -mfused-madd -mno-fused-madd -mfsca -mno-fsca -mfsrra -mno-fsrra -mpretend-cmove -mtas ๐ธ
๐ซถ Solaris 2 Options ๐ซถ
the Solaris crew is small but mighty โจ -mclear-hwcap -mno-clear-hwcap -mimpure-text -mno-impure-text -pthreads ๐
๐ SPARC Options ๐
SPARC has so many toggles it's unreal ๐ญ -mcpu=cpu-type -mtune=cpu-type -mcmodel=code-model -mmemory-model=mem-model -m32 -m64 -mapp-regs -mno-app-regs -mfaster-structs -mno-faster-structs -mflat -mno-flat -mfpu -mno-fpu -mhard-float -msoft-float -mhard-quad-float -msoft-quad-float -mstack-bias -mno-stack-bias -mstd-struct-return -mno-std-struct-return -munaligned-doubles -mno-unaligned-doubles -muser-mode -mno-user-mode -mv8plus -mno-v8plus -mvis -mno-vis -mvis2 -mno-vis2 -mvis3 -mno-vis3 -mvis3b -mno-vis3b -mvis4 -mno-vis4 -mvis4b -mno-vis4b -mcbcond -mno-cbcond -mfmaf -mno-fmaf -mfsmuld -mno-fsmuld -mpopc -mno-popc -msubxc -mno-subxc -mfix-at697f -mfix-ut699 -mfix-ut700 -mfix-gr712rc ๐
๐ System V Options ๐
only a few here, but they're iconic ๐ -Qy -Qn -YP,paths -Ym,dir ๐
๐ V850 Options ๐
the V850 lineup is serving so many variants ๐ญ -mlong-calls -mno-long-calls -mep -mno-ep -mprolog-function -mno-prolog-function -mspace -mtda=n -msda=n -mzda=n -mapp-regs -mno-app-regs -mdisable-callt -mno-disable-callt -mv850e2v3 -mv850e2 -mv850e1 -mv850es -mv850e -mv850 -mv850e3v5 -mloop -mrelax -mlong-jumps -msoft-float -mhard-float -mgcc-abi -mrh850-abi -mbig-switch โญ
๐ง VAX Options ๐ง
VAX keeps it classic ๐ -munix -mgnu -md -md-float -mg -mg-float -mlra ๐ฆ
๐ธ Visium Options ๐ธ
Visium is lowkey underrated ๐ -mdebug -msim -mfpu -mno-fpu -mhard-float -msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode โจ
๐ฅ VMS Options ๐ฅ
VMS has its own vibe, okay ๐ -mvms-return-codes -mdebug-main=prefix -mmalloc64 -mpointer-size=size ๐ซถ
๐ VxWorks Options ๐
the VxWorks options are a whole mood ๐ธ -mrtp -msmp -non-static -Bstatic -Bdynamic -Xbind-lazy -Xbind-now ๐
๐ x86 Options ๐
okay x86 is the main character of this whole page, bestie ๐ญโจ it has so many options it's actually unhinged in the best way. here they all are: -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 -mno-wide-multiply -mrtd -malign-double -mpreferred-stack-boundary=num -mincoming-stack-boundary=num -mcld -mcx16 -msahf -mmovbe -mcrc32 -mmwait -mrecip -mrecip=opt -mvzeroupper -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 -mthreads -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.1-256 -mavx10.1-512 -mevex512 -mavx10.2 -mamx-avx512 -mamx-tf32 -mamx-transpose -mmovrs -mamx-movrs -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 -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 -mfentry-name=name -mfentry-section=name -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 -mrelax-cmpxchg-loop -mindirect-branch=choice -mfunction-return=choice -mindirect-branch-register -mharden-sls=choice -mindirect-branch-cs-prefix -mneeded -mno-direct-extern-access -munroll-only-small-loops -mlam=choice ๐
๐ x86 Windows Options ๐
for the x86 Windows stuff, just peek at Cygwin and MinGW Options, it's got you ๐
โญ Xstormy16 Options โญ
just -msim for this one, short and sweet ๐ง
๐ฆ Xtensa Options ๐ฆ
Xtensa has a glow-up list too โจ -mconst16 -mno-const16 -mfused-madd -mno-fused-madd -mforce-no-pic -mserialize-volatile -mno-serialize-volatile -mtext-section-literals -mno-text-section-literals -mauto-litpools -mno-auto-litpools -mtarget-align -mno-target-align -mlongcalls -mno-longcalls -mabi=abi-type -mextra-l32r-costs=cycles -mstrict-align -mno-strict-align ๐
๐ท zSeries Options ๐ท
zSeries is the same as S/390 and zSeries Options, so check that one out ๐
๐ Options Controlling the Kind of Output ๐
okay so compiling is basically a four-step glow-up: preprocessing, compilation proper, assembly, and linking, always in that order ๐ GCC can preprocess and compile several files into several assembler input files, or squish them into one assembler input file. then each assembler input file makes an object file, and linking combines all the object files (the ones freshly compiled plus any you handed it) into an executable file โจ
for any given input file, the file name suffix decides what kind of compilation happens, so the ending really matters bestie ๐ซถ
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. heads up, 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. again, you must link with thelibobjclibrary to make an Objective-C++ program work. and.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) ๐file.cc,file.cp,file.cxx,file.cpp,file.CPP,file.c++,file.Cโ C++ source code that must be preprocessed. quick note: in.cxx, the last two letters must both be literallyx, and.Crefers to a literal capital C ๐งfile.mm,file.Mโ Objective-C++ source code that must be preprocessed.file.miiโ Objective-C++ source code that should not be preprocessed.file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ header file to be turned into a precompiled header or Ada spec. ๐ฆfile.f,file.for,file.ftn,file.fiโ Fixed form Fortran source code that should not be preprocessed.file.F,file.FOR,file.fpp,file.FPP,file.FTNโ Fixed form Fortran source code that must be preprocessed (with the traditional preprocessor). ๐ธfile.f90,file.f95,file.f03,file.f08,file.fiiโ Free form Fortran source code that should not be preprocessed.file.F90,file.F95,file.F03,file.F08โ Free form Fortran source code that must be preprocessed (with the traditional preprocessor). ๐file.cob,file.COB,file.cbl,file.CBLโ COBOL source code. โจfile.goโ Go source code. ๐ซถfile.dโ D source code.file.diโ D interface file.file.ddโ D documentation code (Ddoc). ๐file.adsโ Ada source code file that contains a library unit declaration (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 are also called specs ๐file.adbโ Ada source code file containing a library unit body (a subprogram or package body). these are also called bodies. ๐file.sโ Assembler code. ๐งfile.S,file.sxโ Assembler code that must be preprocessed. ๐otherโ an object file to be fed straight into linking. any file name with no recognized suffix gets treated this way, so it's giving "skip the line" energy ๐
You can pick the input language yourself with the -x option, bestie ๐
-x languageโ okay so this one lets you declare the language for the input files that come after it, instead of letting the compiler guess from the file name suffix ๐ฎ It stays active for every following input file until the next-xshows up. The valid values are:
c c-header cpp-output
c++ c++-header c++-system-header c++-user-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
ada
cobol
d
f77 f77-cpp-input f95 f95-cpp-input
go
Note that -x does not imply a particular language standard, bestie ๐ For example, -x f77 may also need -std=legacy for some older source codes. Don't skip it!
-x noneโ the main character reset ๐งน This turns off any language specification, so the files after it get handled by their file name suffixes again, as if-xhad never been used at all โจ
If you only want some stages of compilation, you can use -x (or filename suffixes) to tell gcc where to start, and one of the options -c, -S, or -E to say where gcc should stop ๐ฆ Heads up: some combinations, like -x cpp-output -E, instruct gcc to do absolutely nothing at all ๐
-cโ compile or assemble the source files, but do NOT link ๐ธ The linking stage simply 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 are ignored, so they just get left alone ๐ซถ
-Sโ stop right after the compilation proper and skip assembling ๐ The output is an assembler code file for each non-assembler input file you gave it.
By default, the assembler file name for a source file is made by swapping the suffix .c, .i, etc. for .s.
Input files that don't need compilation are ignored.
-Eโ stop after the preprocessing stage and don't run the compiler proper ๐ง The output is preprocessed source code, which gets sent to the standard output.
Input files that don't need preprocessing are ignored.
-o fileโ place the primary output infile๐ This applies to whatever kind of output you're making, whether that's an executable, an object file, an assembler file, or preprocessed C code.
If you don't use -o, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its assembler file in source.s, a precompiled header file in source.suffix.gch, and all preprocessed C source on standard output ๐
Okay, so -o only names the primary output, but it also affects how the auxiliary and dump outputs get named ๐ Unless overridden, both auxiliary outputs and dump outputs get placed 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 file type. For dump outputs, the dump file's suffix gets appended to the input file's suffix. In compilation commands, the base name of both auxiliary and dump outputs is the base name of the primary output. 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 of the combination is that base name. Otherwise they get concatenated, separated by a dash ๐
Here's the vibe with -c:
gcc -c foo.c ...
This will use foo.o as the primary output, and place aux outputs and dumps next to it, e.g., aux file foo.dwo for -gsplit-dwarf, and dump file foo.c.???r.final for -fdump-rtl-final.
If a non-linker output file is explicitly specified, aux and dump files take the same base name by default:
gcc -c foo.c -o dir/foobar.o ...
This will name aux outputs dir/foobar.* and dump outputs dir/foobar.c.*.
A linker output will prefix aux and dump outputs instead ๐ญ
gcc foo.c bar.c -o dir/foobar ...
This will generally name aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and 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, aux outputs are named dir/foo.* and dump outputs are named dir/foo.c.* โจ
The location and names of auxiliary and dump outputs can be adjusted with the options -dumpbase, -dumpbase-ext, -dumpdir, -save-temps=cwd, and -save-temps=obj ๐ฆ
-dumpbase dumpbaseโ this sets the base name for auxiliary and dump output files ๐ซถ It does NOT affect the name of the primary output file. Intermediate outputs, when preserved, aren't treated as primary outputs. They're treated as auxiliary outputs instead.
Like, this one:
gcc -save-temps -S foo.c
saves the (no longer) temporary preprocessed file in foo.i, and then compiles to the (implied) output file foo.s. Whereas this one:
gcc -save-temps -dumpbase save-foo -c foo.c
preprocesses to save-foo.i, compiles to save-foo.s (now an intermediate, and therefore 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 (for example, those requested by -fdump-* options) keep the input name suffix. Aux output files (those requested by other non-dump options, e.g. -save-temps, -gsplit-dwarf, -fcallgraph-info) drop it.
Similar suffix differentiation of dump and aux outputs can be achieved 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 (e.g. -dumpdir or -save-temps=*) is 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.*, disregarding dir/ in -o, the ./ prefix implied by -save-temps=cwd, and pfx- in -dumpdir ๐ธ
When -dumpbase is specified in a command that compiles multiple inputs, or that compiles and then links, it may be combined with dumppfx, as described under -dumpdir. Then each input file is compiled using the combined dumppfx, and default values for dumpbase and auxdropsuf are computed for each input file:
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs. It avoids overwriting the auxiliary and dump outputs by using the dumpbase as a prefix, creating auxiliary and dump outputs named main-foo.* and main-bar.* ๐ง
An empty string given as dumpbase avoids the influence of the output basename on the naming of auxiliary and dump outputs during compilation, and computes default values instead:
gcc -c foo.c -o dir/foobar.o -dumpbase " ...
This will name aux outputs dir/foo.* and dump outputs dir/foo.c.*. Notice how their basenames come from the input name, but the directory still defaults to that of the output ๐
The 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 auxiliary outputs dir/foo.* and dir/bar.*, and dump outputs dir/foo.c.* and dir/bar.c.*. LTO recompilation during linking will use dir/foobar. as the prefix for dumps and auxiliary files โจ
-dumpbase-ext auxdropsufโ when forming the name of an auxiliary (but NOT a dump) output file, this drops the trailingauxdropsuffromdumpbasebefore any suffixes get appended ๐ If you don't specify it, this option defaults to the suffix of a defaultdumpbase. That's the suffix of the input file when-dumpbaseisn't on the command line, or whendumpbaseis combined withdumppfx.
gcc foo.c -c -o dir/foo.o -dumpbase x-foo.c -dumpbase-ext .c ...
This creates dir/foo.o as the main output, and generates auxiliary outputs in dir/x-foo.*. It takes the location of the primary output and drops the .c suffix from the dumpbase. Dump outputs keep the suffix: dir/x-foo.c.* ๐ฆ
This option is disregarded if it doesn't match the suffix of a specified dumpbase, except as an alternative to the executable suffix when appending the linker output base name to dumppfx, as described below:
gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
This creates main.out as the primary output, and avoids overwriting the auxiliary and dump outputs by using the executable name minus auxdropsuf as a prefix. It creates auxiliary outputs named main-foo.* and main-bar.*, and dump outputs named main-foo.c.* and main-bar.c.* ๐
-dumpdir dumppfxโ when forming the name of an auxiliary or dump output file, usedumppfxas a prefix ๐
gcc -dumpdir pfx- -c foo.c ...
This creates foo.o as the primary output, and auxiliary outputs named pfx-foo.*. It combines the given dumppfx with the default dumpbase, which is derived from the default primary output, which is in turn derived from the input name. Dump outputs also take the input name suffix: pfx-foo.c.* ๐
If dumppfx is going to be used as a directory name, it must end with a directory separator:
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.*, combining the given dumppfx with the default dumpbase derived from the primary output name. Dump outputs also take the input name suffix: dir/bar.c.* ๐ฅ
It defaults to 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 multiple such options are given, the last one prevails:
gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
So it still spits out foo.o, but the auxiliary outputs get named foo.* ๐ because -save-temps=* overrides the dumppfx you gave with the earlier -dumpdir option. ๐
It's not a big deal 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 pass -dumpbase, the dumpbase minus an auxdropsuf suffix, plus a dash, gets tacked onto (or overrides, if it has any directory components) an explicit or defaulted dumppfx. That way each of the compilations gets its own differently-named aux and dump outputs โจ
gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
This outputs 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 compare that with the single-input version:
gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
Applying -dumpbase to a single source does not compute and append a separate dumpbase per input file, so 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 gets the dumpbase- treatment from above (think the foo.c and bar.c compilation, but without -c). If neither -dumpdir nor -dumpbase is given, the linker output base name, minus auxdropsuf if specified (or the executable suffix otherwise), plus a dash gets appended to the default dumppfx instead. ๐ฆ Heads up though, this is different from the earlier cases of linking:
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
This does not append the output name main to dumppfx, because -dumpdir was explicitly specified. The vibe here is that an explicitly-specified dumppfx can include the output name as part of the prefix, if you want that. Only an explicitly-specified -dumpbase gets combined with it, so a meaningful option never just gets thrown away ๐ซถ
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 above, but not with an explicit -dumpdir that stops the combination, even if -save-temps=* overrides it:
gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
Auxiliary outputs are named foo.*, and dump outputs foo.c.*, in the current working directory, as ultimately requested by -save-temps=cwd ๐ธ
Okay, so here's the big-picture data flow. It's a little imprecise, but it's intuitive ๐ง The primary output name gets split into a directory part and a basename part. dumppfx is set to the directory part, unless -dumpdir or -save-temps=* overrides it, and dumpbase is set to the basename part, unless -dumpbase overrides it. With multiple inputs or linking, this dumpbase may get combined with dumppfx and 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 in that the suffix from dumpbase is kept ๐
When it comes to auxiliary and dump outputs created during LTO recompilation ๐, a combination of dumppfx and dumpbase gets passed down to lto-wrapper as a -dumpdir option. This happens whether it's given explicitly or derived from the linker output name (but not from inputs), and even in cases where this combination wouldn't otherwise get used as such. The trailing period replaces the compiler-added dash, if there is one. Since linking is involved, this program doesn't normally get any -dumpbase and -dumpbase-ext, and it ignores them ๐
When lto-wrapper runs sub-compilers, it appends the LTO stage names to the dumppfx it received, makes sure it contains a directory component so it overrides any -dumpdir, and passes that along as -dumpbase to the sub-compilers โจ
โจ OPTIONS โจ
-vโ Prints the commands the compiler runs for each stage of compilation (on standard error output). It also prints the version number of the compiler driver program, plus the preprocessor and the compiler proper ๐ฃ-###โ Basically-v, except the commands are not actually executed. Arguments get quoted unless they only contain alphanumeric characters or"./-_". This is super handy for shell scripts that want to capture the driver-generated command lines ๐ค--helpโ Prints (on the standard output) a description of the command-line optionsgccunderstands. If-vis also specified, then--helpgets passed on to the various processesgccinvokes, so they can show the command-line options they accept. If-Wextrahas also been specified (before the--helpoption), then command-line options with no documentation attached are displayed too ๐--target-helpโ Prints (on the standard output) a description of the target-specific command-line options for each tool. For some targets, extra target-specific info may also get printed ๐ฏ--help={class|[^]qualifier}[,...]โ 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โ Displays all of the optimization options the compiler supports.warningsโ Displays all of the options that control warning messages the compiler produces.targetโ Displays target-specific options. Unlike--target-help, target-specific options of the linker and assembler are not displayed, because those tools don't currently support the extended--help=syntax ๐paramsโ Displays the values recognized by the--paramoption.languageโ Displays 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 select thecommonclass.commonโ Displays the options that are common to all languages.
And here are the supported qualifiers:
undocumentedโ Displays only the options that are undocumented.joinedโ Displays options that take an argument appearing after an equal sign in the same continuous piece of text, such as:--help=target.separateโ Displays options that take an argument appearing as a separate word following the original option, such as:-o output-file.
Want all the undocumented target-specific switches the compiler supports? Use:
--help=target,undocumented
You can invert a qualifier by putting the ^ character in front of it. So if you want every binary warning option (the ones that are either on or off and don't take an argument) that has a description, use:
--help=warnings,^joined,^undocumented
The argument to --help= should not consist solely of inverted qualifiers.
Combining several classes is possible, but it usually narrows the output so much that there's nothing to show. One case where it does work is 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 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 ๐
If the -Q option appears on the command line before --help=, the descriptive text that --help= shows changes. Instead of describing the options, it indicates whether each option is enabled, disabled, or set to a specific value (assuming the compiler knows this at the point where --help= is used) ๐
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 is sensitive to the effects of previous command-line options, so for example you can find out which optimizations are enabled at -O2 by using:
-Q -O2 --help=optimizers
Or, if you want to see which binary optimizations are enabled by -O3, do this:
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โ Displays the version number and copyrights of the invoked GCC ๐-pass-exit-codesโ Normally, thegccprogram exits with the code of1if any phase of the compiler returns a non-success return code. If you specify-pass-exit-codes, thengccinstead returns with the numerically highest error produced by any phase that returned an error indication. The C, C++, and Fortran front ends return4if they hit an internal compiler error ๐ญ-pipeโ Uses pipes rather than temporary files for communication between the various stages of compilation. This fails to work on some systems where the assembler can't read from a pipe, but the GNU assembler has no trouble with it ๐ฆ-specs=fileโ Processes file after the compiler reads in the standard specs file, in order to override the defaults that thegccdriver program uses when deciding which switches to pass tocc1,cc1plus,as,ld, etc. You can specify more than one-specs=fileon the command line, and they're processed in order, from left to right ๐ง-wrapperโ Invokes all subcommands under a wrapper program. The name of the wrapper program and its parameters are passed as a comma-separated list:
gcc -c t.c -wrapper gdb,--args
This invokes all subprograms of gcc under gdb --args, so the invocation of cc1 becomes gdb --args cc1 .... ๐
โจ -ffile-prefix-map=old=new ๐บ๏ธ๐
When you're compiling files that live in the directory old, GCC will record any references to them in the compilation result as if those files lived in new instead. Writing this option is the same as writing out every individual -f*-prefix-map option, so it's basically the one-stop shop ๐๏ธ. It's a lowkey perfect tool for reproducible builds that don't care where they're built ๐ธ. Directories referenced by directives are not affected by these options. See also -fmacro-prefix-map, -fdebug-prefix-map, -fprofile-prefix-map and -fcanon-prefix-map ๐ฆ.
-fcanon-prefix-mapโ okay so, when you use the-f*-prefix-mapoptions, GCC normally compares the old prefix against the filename it would reference by doing a plain textual comparison of the prefixes. On case-insensitive filesystems it ignores character case, and on DOS-based filesystems it treats slashes and backslashes as the same thing ๐ .-fcanon-prefix-mapswitches this so the comparisons happen on canonicalized paths for botholdand the referenced filename. Main character energy ๐.-fplugin=name.soโ loads the plugin code from the filename.so, which is assumed to be a shared object that the compiler willdlopen. The base name of the shared object file is what identifies 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, this generates the matching Ada specs ๐.-fada-spec-parent=unitโ used together with-fdump-ada-spec[-slim]above, this makes the generated Ada specs child units of the parentunit๐.-fdump-go-spec=fileโ for input files in any language, this generates matching Go declarations infile. You get Goconst,type,var, andfuncdeclarations, which is a really useful way to start writing a Go interface to code written in some other language ๐น๐ซถ.@fileโ reads command-line options fromfile. The options it reads get slotted in right where the original@fileoption was ๐. Iffiledoesn't exist or can't be read, then the option gets treated literally and isn't removed ๐.
Options inside file are separated by whitespace. If you need a whitespace character inside an option, wrap the entire option in single or double quotes. Any character (including a backslash) can be included by putting a backslash in front of it ๐. The file can also contain more @file options of its own, and those get processed recursively, so yes, it can go deep ๐.
โจ 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 do for C programs (usually with the name gcc) ๐
.
Heads up though: using gcc does not add the C++ library ๐ญ. g++ is a program that calls GCC and automatically specifies linking against the C++ library, so it's the one you want for C++ vibes ๐. It treats .c, .h and .i files as C++ source files instead of C source files, unless you use -x ๐. 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 use many of the same command-line options you'd use for programs in any language ๐. You can also use command-line options meaningful for C and related languages, or options that only mean something for C++ programs ๐.
โจ Options Controlling C Dialect โจ
The following options control the dialect of C (or languages derived from C, like C++, Objective-C and Objective-C++) that the compiler accepts ๐.
-ansiโ in C mode, this is equivalent to-std=c90. In C++ mode, it's equivalent to-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, and 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 doesn't turn off other GNU extensions that have no meaning in ISO C90, like omitting the middle term of a "?:" expression ๐ฆ.
On the flip side, 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 ๐ญ. Because of that, some strictly conforming programs may get rejected ๐. The particular standard is also what -Wpedantic uses 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 ๐ง.
You must provide a value for this option. The 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). Check out<https://gcc.gnu.org/c99status.html>for more info ๐. The namesc9xandiso9899:199xare deprecated ๐ซ.c11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard โจ. This one 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 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 ๐งช. 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 ๐งช. 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 ๐ซ.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. This is the default for C++ code ๐. The namegnu++1zis deprecated ๐ซ.c++20,c++2aโ the 2020 ISO C++ standard plus amendments ๐งช. Support is experimental and could change in incompatible ways in future releases ๐ฌ. The namec++2ais deprecated ๐ซ.gnu++20,gnu++2aโ GNU dialect of-std=c++20๐งช. Support is experimental and could change in incompatible ways in future releases ๐ฌ. 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โ outputs prototyped declarations to the givenfilenamefor all functions declared and/or defined in a translation unit, including the ones in header files ๐. This option is silently ignored in any language other than C ๐คซ.
Okay so bestie, the aux-info file is lowkey iconic ๐ Besides the declarations, it leaves little comments showing where each one came from (source file and line) ๐. It also tags each declaration as I (implicit), N (new, prototyped) or O (old, unprototyped), right after the line number and colon โจ. The next character says whether it came from a declaration (C) or a definition (F) ๐. And for function definitions, it also drops a K&R-style list of arguments and their declarations in comments right after the declaration ๐ฆ
-fno-asmโ Stopsasm,inlineandtypeoffrom being treated as keywords, so you can use them as regular identifiers ๐
Your code can use __asm__, __inline__ and __typeof__ instead, which is giving full keyword energy โจ In C, -ansi already implies -fno-asm, so no need to add it twice ๐
In C++, inline is a standard keyword, so this switch doesn't touch it at all ๐
โโ๏ธ If you only want typeof gone and want to keep asm and inline, use -fno-gnu-keywords instead ๐ In C99 mode (-std=c99 or -std=gnu99), this switch only affects asm and typeof, because inline is already a standard keyword in ISO C99 ๐ธ In C23 mode (-std=c23 or -std=gnu23), it only affects asm, since typeof is standard in ISO C23 ๐ง
-fno-builtin,-fno-builtin-functionโ Don't recognize built-in functions whose names don't start with__builtin_๐ โโ๏ธ
GCC usually generates special code for certain built-in functions so they run faster ๐๏ธ For example, calls to alloca might turn into a single instruction that adjusts the stack directly, and calls to memcpy might become inline copy loops ๐ The result is often smaller and faster, but the calls don't show up as calls anymore. That means you can't set a breakpoint on them, and you can't change what they do by linking against a different library ๐ญ Also, once GCC recognizes a built-in function, it can use what it knows about that function to warn you about bad calls, or to generate more efficient code, even when the code still contains calls to it ๐ For example, warnings are given with -Wformat for bad calls to printf when printf is built in and strlen is known not to modify global memory ๐
With the -fno-builtin-function option, only that one built-in function gets disabled ๐ฏ function must not begin with __builtin_. If you name a function that isn't built-in in this version of GCC, the option is simply ignored ๐คทโโ๏ธ There's no matching -fbuiltin-function option. If you want to turn built-in functions back on selectively while 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โ Lets conditional expressions have mismatched types in their second and third arguments ๐ The value of that kind of expression isvoid. This option is not supported for C++ ๐ โโ๏ธ-ffreestandingโ Tells GCC that compilation targets a freestanding environment โจ This implies-fno-builtin. A freestanding environment is one where the standard library might not exist, and program startup might not necessarily start atmain๐ง The most obvious example is an OS kernel ๐ This is equivalent to-fno-hosted.-fgimpleโ Turns on parsing of function definitions marked with__GIMPLE. It's an experimental feature that lets you unit test GIMPLE passes ๐งช-fgnu-tmโ When you specify-fgnu-tm, 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 experimental, and its interface may change in future versions of GCC as the official specification changes ๐ฌ Not every architecture supports this feature, so heads up ๐ซถ
For more information on GCC's support for transactional memory,
Transactional memory is not supported together with non-call exceptions (-fnon-call-exceptions). Don't mix them, bestie ๐
-fgnu89-inlineโ Tells GCC to use the traditional GNU semantics forinlinefunctions when in C99 mode ๐ธ
Using this option is roughly the same as adding the gnu_inline function attribute to every inline function ๐
The option -fno-gnu89-inline explicitly tells GCC to use the C99 semantics for inline when in C99 or gnu99 mode. In other words, it sets 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โ Tells GCC that compilation targets a hosted environment โจ This implies-fbuiltin. A hosted environment is one where the entire standard library is available andmainhas a return type ofint๐ Basically everything except a kernel fits this description ๐ง This is equivalent to-fno-freestanding.-flax-vector-conversionsโ Allows implicit conversions between vectors with different numbers of elements and/or incompatible element types ๐ฌ Please don't use this in new code, it's giving "old and messy" ๐-fms-extensionsโ Accepts some non-standard constructs found in Microsoft header files ๐ช
In C++ code, this lets member names in structures match earlier type declarations, which is so chaotic but also kind of fun ๐
typedef int UOW;
struct ABC {
UOW UOW;
};
Some cases of unnamed fields in structures and unions are only accepted with this option ๐ซฃ
This option is off for all targets except x86 targets using ms-abi, so don't expect it to just work everywhere ๐ โโ๏ธ
-fpermitted-flt-eval-methods=styleโ Controls which values ofFLT_EVAL_METHODthe compiler is allowed to use ๐ฆ
ISO/IEC TS 18661-3 defines new permissible values for FLT_EVAL_METHOD. These say that operations and constants whose semantic type is an interchange or extended format should be evaluated to the precision and range of that type ๐ค The new values are a superset of what C99/C11 allows, and C99/C11 doesn't specify what other positive values of FLT_EVAL_METHOD mean. So code that's C11-conformant might never have expected these new values to show up ๐ญ
-fpermitted-flt-eval-methods decides whether the compiler only allows the FLT_EVAL_METHOD values from C99/C11, or the extended set from ISO/IEC TS 18661-3 โจ
style is either c11 or ts-18661-3, depending on what you need ๐
In a standards-compliant mode (-std=c11 or similar), the default is -fpermitted-flt-eval-methods=c11. In a GNU dialect (-std=gnu11 or similar), the default is -fpermitted-flt-eval-methods=ts-18661-3 ๐
The -fdeps-* options extract structured dependency information for a source file ๐ง This means figuring out which resources from other source files the source needs in order to compile, and which resources the source itself provides. That info can add required dependencies between compilation rules of dependent sources based on their actual contents, so the build tools don't have to reflect that information themselves ๐ซถ
-fdeps-file=fileโ Where to write the structured dependency information ๐-fdeps-format=formatโ The format to use for structured dependency information.p1689r5is the only supported format right now ๐ When this argument is specified, the output of-MFgets stripped of some information (namely C++ modules), so it doesn't use extended makefile syntax that most tools won't understand ๐-fdeps-target=fileโ This is the-MTequivalent for structured dependency information ๐ฏ It names the target that will ultimately need any required resources, and that will provide any resources extracted from the source that other sources might need ๐ง-fplan9-extensionsโ Accepts some non-standard constructs used in Plan 9 code ๐น
This turns on -fms-extensions, lets you pass pointers to structures with anonymous fields to functions that expect pointers to elements of the field's type, and lets you refer 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โ Control whether a bit-field is signed or unsigned when the declaration doesn't use eithersignedorunsigned๐ข By default, such a bit-field is signed, which is consistent, since basic integer types likeintare signed too ๐-fsigned-charโ Makes the typecharsigned, just likesigned charโจ
This is equivalent to -fno-unsigned-char, which is the negative form of -funsigned-char. Likewise, -fno-signed-char is equivalent to -funsigned-char ๐
-funsigned-charโ Makes the typecharunsigned, just likeunsigned char๐
Every kind of machine has a default for what char should be. It's either like unsigned char by default, or like signed char by default ๐ฅ๏ธ
Ideally, a portable program always uses signed char or unsigned char when it depends on the signedness of an object ๐งผ But lots of programs were written to use plain char and expect it to be signed, or expect it to be unsigned, depending on the machines they were written for ๐ฉ This option, and its inverse, let you make those programs work with the opposite default ๐ซถ
The type char is always a distinct type from both signed char and unsigned char, even though it behaves exactly like one of those two ๐ค
-fstrict-flex-arrays(C and C++ only),-fstrict-flex-arrays=level(C and C++ only) โ Controls when the trailing array of a structure gets treated as a flexible array member when you're accessing its elements ๐ฆ The value oflevelsets how strict that is ๐
-fstrict-flex-arrays is equivalent to -fstrict-flex-arrays=3, which is the strictest option. A trailing array only counts as a flexible array member when it's declared as one, per the C99 standard onwards ๐
The negative form, -fno-strict-flex-arrays, is equivalent to -fstrict-flex-arrays=0, which is the least strict. In that case, every trailing array of a structure is treated as a flexible array member ๐ท
okay so there are two more levels hiding between 0 and 3 โจ they exist for older code that uses the GCC zero-length array extension ([0]) or one-element arrays as flexible array members ([1]) ๐ง when level is 1, the trailing array gets treated as a flexible array member when it's declared as [], [0], or [1]. when level is 2, it only counts when it's declared as [] or [0] ๐
you can control this for one specific trailing array field in a struct by using the variable attribute "strict_flex_array" attribute ๐
and yes, the -fstrict_flex_arrays option interacts with the -Wstrict-flex-arrays option ๐ซถ
-fsso-struct=endiannessโ okay this one sets the default scalar storage order of structures and unions to whatever endianness you pick ๐ the accepted values arebig-endian,little-endian, andnative(the native endianness of the target, which is the default). this option is not supported for C++ ๐
โ ๏ธ warning, bestie: -fsso-struct makes GCC generate code that is not binary compatible with code generated without it if the endianness you specify isn't the native endianness of the target ๐ญ handle with care
โจ Options Controlling C++ Dialect โจ
this section is all about the command-line options that only mean something for C++ programs ๐ you can still use most of the GNU compiler options no matter what language your program is in, though. for example, you might 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 too ๐ฆ
here's the list of options that are only for compiling C++ programs ๐
-fabi-version=nโ use versionnof the C++ ABI ๐ the default is version0.- version
0refers to the version that conforms most closely to the C++ ABI specification. so the ABI you get with version0will change between versions of G++ as ABI bugs get fixed ๐ - version
1is the version of the C++ ABI that first showed up in G++ 3.2. - version
2is the version that first showed up in G++ 3.4, and it was the default through G++ 4.9. - version
3fixes an error in mangling a constant address as a template argument. - version
4, which first showed up in G++ 4.5, implements a standard mangling for vector types. - version
5, which first showed up in G++ 4.6, fixes the mangling of attribute const/volatile on function pointer types,decltypeof a plain decl, and use of a function parameter in the declaration of another parameter. - version
6, which first showed up 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, which first showed up in G++ 4.8, treatsnullptr_tas a builtin type and fixes the mangling of lambdas in default argument scope. - version
8, which first showed up in G++ 4.9, fixes the substitution behavior of function types with function-cv-qualifiers. - version
9, which first showed up in G++ 5.2, fixes the alignment of "nullptr_t". - version
10, which first showed up in G++ 6.1, adds mangling of attributes that affect type identity, such as ia32 calling convention attributes (e.g. stdcall). - version
11, which first showed up in G++ 7, fixes the mangling ofsizeof...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, which first showed up 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, which first showed up in G++ 8.2, fixes the accidental change in version 12 ๐ซถ - version
14, which first showed up in G++ 10, fixes the mangling of the nullptr expression. - version
15, which first showed up in G++ 10.3, fixes the G++ 10 ABI tag regression. - version
16, which first showed up in G++ 11, changes the mangling of "__alignof__" so it's distinct from that of "alignof", plus dependent operator names. - version
17, which first showed up in G++ 12, fixes the layout of classes that inherit from aggregate classes with default member initializers in C++14 and up. - version
18, which first showed up in G++ 13, fixes manglings of lambdas that have additional context. - version
19, which first showed up in G++ 14, fixes manglings of structured bindings to include ABI tags. - version
20, which first showed up in G++ 15, fixes manglings of lambdas in static data member initializers. - see also
-Wabi.
- version
-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 to13(GCC 8.2 compatibility). if another ABI version is explicitly selected, it defaults to0. 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 gets 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โ enables support for C++17 "new" of types that need more alignment than "void* ::operator new(std::size_t)" provides ๐ a numeric argument like "-faligned-new=32" can say how much alignment (in bytes) that function provides, but 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
-fno-assume-sane-operators-newโ the C++ standard lets you replace the global "new", "new[]", "delete" and "delete[]" operators, though a lot of C++ programs don't replace them and just use the implementation-provided version ๐ง the standard also lets you omit those calls when they're made from new or delete expressions (and by extension the same is assumed if "__builtin_operator_new" or "__builtin_operator_delete" functions are used). this option controls 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_new" or "__builtin_operator_delete" calls, don't read or modify any global variables, or variables whose address could escape to the operators (global state; except for "errno" for the "new" and "new[]" operators). this allows most optimizations across those calls. the implementation-provided operators satisfy this unless "malloc" implementation details are observable in the code or "malloc" hooks are used, but it might not hold 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โ enables support for "char8_t" as adopted for C++20 ๐ that includes a new "char8_t" fundamental type, changes to the types of UTF-8 string and character literals, new signatures for user-defined literals, associated standard library updates, and new "__cpp_char8_t" and "__cpp_lib_char8_t" feature test macros.
this option lets functions be overloaded for ordinary 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
and it 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;
๐จ heads up: the change to the types of UTF-8 string and character literals introduces incompatibilities with ISO C++11 and later standards. for example, the following code 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โ okay so this one makes G++ check that the pointeroperator newhands back isn't null before it starts messing with the memory ๐. Honestly it's usually unnecessary, because the C++ standard saysoperator newonly returns 0 if it's declaredthrow(), and in that case the compiler checks the return value anyway, even without this flag. In every other case, whereoperator newhas a non-empty exception specification, running out of memory gets signalled by throwingstd::bad_alloc๐. See alsonew (nothrow).-fconceptsโ the bestie of template arguments ๐ฆ. This turns on support for the C++ Concepts feature, which lets you constrain template arguments. With-std=c++20and above, Concepts are part of the language standard, so-fconceptsis on by default โจ.
Some constructs from the earlier C++ Extensions for Concepts Technical Specification, ISO 19217 (2015), didn't make it into the standard, but they can still be enabled with -fconcepts-ts ๐ธ. Real talk though, -fconcepts-ts was deprecated in GCC 14 and removed in GCC 15, so users are expected to convert their code to C++20 concepts ๐ญ.
-fconstexpr-depth=nโ sets the maximum nested evaluation depth for C++11constexprfunctions to n ๐ง. You need a limit like this so endless recursion gets caught during constant expression evaluation. The standard's minimum is 512.-fconstexpr-cache-depth=nโ sets the maximum level of nested evaluation depth for C++11constexprfunctions that gets cached, to n ๐. This is a heuristic, so it's a trade-off: caching can speed up compilation when it avoids repeated calculations, but it eats memory when highly recursive evaluations make the cache grow huge. The default is 8. Very few people need to touch it, but if your code does heavyconstexprmaths, feel free to experiment and find what works best for you โจ.-fconstexpr-fp-exceptโ okay this one is spicy ๐ฅ. Annex F of the C standard says IEC559 floating point exceptions hit at compile time shouldn't stop compilation. C++ compilers have historically ignored that and treated 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 that say an operation is undefined:
constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
-fconstexpr-loop-limit=nโ sets the maximum number of iterations for a loop in C++14constexprfunctions to n ๐. Endless loops need a cap so they get caught during constant expression evaluation. The default is 262144 (1<<18).-fconstexpr-ops-limit=nโ sets the maximum number of operations during a singleconstexprevaluation ๐. Even if each loop is under the iteration limit above, several nested loops with lots of iterations, or a ton of expressions inside a loop or outside of one, can make the evaluation take forever. The default is 33554432 (1<<25).-fcontractsโ enables experimental support for the C++ Contracts feature ๐งช. It was briefly added to and then removed from the C++20 working paper (N4820), and the implementation also includes proposed enhancements from papers P1290, P1332, and P1429. This is mostly for people who want to experiment and help shape the feature for a future C++ standard ๐ซถ.
When a checked contract is violated, the violation handler gets called. You can swap in your own handler by defining:
void
handle_contract_violation (const std::experimental::contract_violation&);
There are different sets of extra flags for N4820, P1332, or P1429 contracts, and you can't mix these sets together ๐. Here they are:
-fcontract-mode=[on|off]โ controls whether contracts have any semantics at all. Defaults to on.-fcontract-assumption-mode=[on|off]โ [N4820] controls whether contracts with level axiom should have the assume semantic. Defaults to on.-fcontract-build-level=[off|default|audit]โ [N4820] picks which level of contracts gets checks generated for it. Defaults to default.-fcontract-continuation-mode=[on|off]โ [N4820] controls whether the program is allowed to keep running after a contract violation. In other words, do checked contracts get the maybe semantic instead of the never semantic. Defaults to off.-fcontract-role=<name>:<default>,<audit>,<axiom>โ [P1332] sets the concrete semantics for each contract level of a particular contract role ๐.-fcontract-semantic=[default|audit|axiom]:<semantic>โ [P1429] sets the concrete semantic for a particular contract level โจ.-fcontract-strict-declarations=[on|off]โ controls whether adding contracts to a function after its first declaration gets rejected. Defaults to off.
The concrete semantics you can pick with -fcontract-role or -fcontract-semantic are:
ignoreโ this contract has no effect ๐.assumeโ this contract is treated like C++23[[assume]].check_never_continue,never,abortโ this contract is checked. If it fails, the violation handler gets called. If the handler returns,std::terminateis called ๐.check_maybe_continue,maybeโ this contract is checked. If it fails, the violation handler gets called. If the handler returns, execution keeps going normally ๐ฆ.
-fcoroutinesโ enables support for the C++ coroutines extension. It's experimental, so handle with a little care ๐ง.-fdiagnostics-all-candidatesโ lets the C++ front end note all the candidates during an overload resolution failure ๐. That includes the case where a deleted function gets selected.-fno-elide-constructorsโ the C++ standard lets an implementation skip creating a temporary that's only used to initialize another object of the same type ๐. This flag turns that optimization off and forces G++ to call the copy constructor in all cases. It also makes G++ call trivial member functions that would otherwise be expanded inline.
In C++17, the compiler is required to omit these temporaries, but this option still affects trivial member functions ๐ซ .
-fno-enforce-eh-specsโ don't generate code that checks for violations of exception specifications at run time ๐ง. This breaks the C++ standard, but it can be handy for shrinking code size in production builds, kind of like definingNDEBUG. It does not give your code permission to throw exceptions that break the exception specifications. The compiler still optimizes based on those specs, so throwing an unexpected exception gives you undefined behavior at run time ๐ฌ.-fextern-tls-init,-fno-extern-tls-initโ the C++11 and OpenMP standards letthread_localandthreadprivatevariables have dynamic (runtime) initialization ๐งต. To make that work, any use of such a variable goes through a wrapper function that does the necessary initialization. When the use and the definition are 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 can be sure that no use in a non-defining TU needs to trigger dynamic initialization, either because the variable is statically initialized or because a use in the defining TU runs before any use in another TU, you can skip that 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++ frontend fold calls tostd::move,std::forward,std::addressof, andstd::as_const๐ท. Unlike inlining, this means no debug information gets generated for those calls. Since these functions are rarely interesting to debug, this flag is enabled by default unless-fno-inlineis active.-fno-gnu-keywordsโtypeofstops being a keyword, so your code can use that word as an identifier ๐. You can use the keyword__typeof__instead. This option is implied by the strict ISO C++ dialects:-ansi,-std=c++98,-std=c++11, etc.-fno-immediate-escalationโ stops immediate function escalation, where certain functions can get promoted toconsteval, as specified in P2564R3 ๐. Here's an 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);
}
That 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. As a result, 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 ๐ง. However, with -fno-immediate-escalation, f doesn't get promoted to consteval, and 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 โจ. This option can be used in C++14 mode or later. It can change initialization from dynamic to static, plus some other optimizations come along for the ride ๐.
โจ OPTIONS (continued) โจ
-fno-implicit-templatesโ okay so this one is a lot. The compiler will never emit code for non-inline templates that get instantiated implicitly (aka just by using them) ๐. It only emits code for explicit instantiations. If you turn this on, you have to structure your code so you include every explicit instantiation you need, or you'll get undefined symbols at link time ๐.
โ ๏ธ bestie, if you skip the explicit instantiations with this flag on, the linker will throw undefined symbol errors at you. Plan ahead!
-fno-implicit-inline-templatesโ don't emit code for implicit instantiations of inline templates either ๐ . By default the compiler handles inlines differently, so that compiles with and without optimization need the same set of explicit instantiations. Iconic consistency ๐ซถ.-fno-implement-inlinesโ to save space, don't emit 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're called ๐ญ.-fmodules,-fno-modulesโ enable support for C++20 modules ๐ง. The-fno-modulesflag is usually not needed, since that's already the default. Even though modules are a C++20 feature, selecting that standard version does not currently turn them on implicitly, so you have to ask for-fmodulesyourself ๐.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ compile a header file so it becomes an importable header unit ๐ฆ.-fmodule-implicit-inlineโ okay so in modular code, member functions defined inside their class definition are not implicitly inline. That's different from traditional C++ behavior, and it's for good reasons ๐ค. It can cause a bit of a headache when porting code though. This option makes those function definitions implicitly inline. Be warned: it creates an ABI incompatibility, so you must use it everywhere or nowhere ๐ซ. (Definitions outside of a named module stay implicitly inline no matter what ๐ธ.)-fno-module-lazyโ disable 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 the oracle that answers "which filename belongs to this module name?" ๐ฎ. If you don't specify one, theCXX_MODULE_MAPPERenvironment variable gets used, and if that's unset too, an in-process default is provided โจ.-fmodule-onlyโ only emit the Compiled Module Interface, and skip the object file entirely ๐ฆ.-fms-extensionsโ disable-Wpedanticwarnings about constructs used in MFC ๐ช. Examples are implicitint, and getting a pointer to a member function using non-standard syntax ๐.-fnew-inheriting-ctorsโ enable the P0136 adjustment 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 enabled by default unless-fabi-version=10or lower is specified ๐.-fnew-ttp-matchingโ enable the P0522 resolution to Core issue 150, which covers template template parameters and default arguments ๐. It allows a template with default template arguments to be passed as an argument for a template template parameter that has fewer template parameters. This flag is enabled by default for-std=c++17โญ.-fno-nonansi-builtinsโ disable built-in declarations of functions that aren't mandated by ANSI/ISO C ๐งน. That includes"ffs","alloca","_exit","index","bzero","conjf", and other related functions ๐.-fnothrow-optโ treat athrow()exception specification as if it were a"noexcept"specification ๐ธ. This reduces or eliminates the text size overhead compared to a function with no exception specification. If the function has local variables with non-trivial destructors, the exception specification 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 exception specification results in a call to"terminate"instead of"unexpected"๐.-fno-operator-namesโ do not treat the operator name keywords"and","bitand","bitor","compl","not","or", and"xor"as synonyms for the operators ๐ .-fno-optional-diagsโ disable 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 having multiple meanings within a class ๐ญ.-fno-pretty-templatesโ okay so when an error message refers to a specialization of a function template, the compiler normally prints the template's signature, followed by the template arguments and any typedefs or typenames in that signature. So you get something like"void f(T) [with T = int]"instead of"void f(int)", so you can tell which template is involved ๐. When an error refers to a specialization of a class template, it leaves out any template arguments that match the default template arguments for that template โ๏ธ. If either of those behaviors makes errors harder to read instead of easier, use-fno-pretty-templatesto turn them off ๐ .-frange-for-ext-tempsโ enable lifetime extension of C++ range-basedfortemporaries ๐. With-std=c++23and above this is part of the language standard, so the temporaries get extended until the end of the loop by default. This option lets you turn that behavior on in earlier versions of the standard too โณ.-fno-rttiโ disable generation of run-time type information for every class with virtual functions ๐งฌ. That info is what the"dynamic_cast"and"typeid"features use. If you don't use those parts of the language, you can save some space with this flag ๐. Exception handling uses the same information, but G++ generates it only when needed ๐ท. The"dynamic_cast"operator can still be used for casts that don't need run-time type information, like casts to"void *"or to unambiguous base classes โจ.
โ ๏ธ Mixing code compiled with-frttiand code compiled with-fno-rttimay not work ๐ฌ. For example, programs may fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti.
-fsized-deallocationโ enable 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 useful for user-defined replacement deallocation functions that, for example, use the size of the object to make deallocation faster ๐. It's enabled by default under -std=c++14 and above. The flag -Wsized-deallocation warns about places that might want to add a definition ๐.
-fstrict-enumsโ lets the compiler optimize using the assumption that a value of an enumerated type can only be one of the values of the enumeration ๐ข. (As defined in the C++ standard: basically, a value that can be represented in the minimum number of bits needed to represent all the enumerators.) This assumption may not hold if the program uses a cast to convert an arbitrary integer value to the enumerated type ๐. This option has no effect for an enumeration type with a fixed underlying type ๐ซฅ.-fstrong-eval-order,-fstrong-eval-order=kindโ evaluate member access, array subscripting, and shift expressions in left-to-right order, and evaluate assignment in right-to-left order, as adopted for C++17 ๐น.-fstrong-eval-orderis equivalent to-fstrong-eval-order=all, and it's enabled by default with-std=c++17or later ๐.-fstrong-eval-order=someenables just the ordering of member access and shift expressions, and it's the default for C++ dialects prior to C++17 ๐.-fstrong-eval-order=noneis equivalent to-fno-strong-eval-order๐ซง.
-ftemplate-backtrace-limit=nโ set the maximum number of template instantiation notes for a single warning or error ton๐. The default value is10๐.-ftemplate-depth=nโ set the maximum instantiation depth for template classes ton๐. A limit on template instantiation depth is needed to detect endless recursions during template class instantiation ๐. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than17(changed to1024in C++11) ๐. The default value is900, since the compiler can run out of stack space before hitting1024in some situations ๐ต.-fno-threadsafe-staticsโ don't emit the extra code that uses the routines from the C++ ABI for thread-safe initialization of local statics ๐งต. You can use this to shave a bit off code size in code that doesn't need to be thread-safe ๐.-fuse-cxa-atexitโ register destructors for objects with static storage duration with the"__cxa_atexit"function, instead of the"atexit"function ๐ช. This option 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โ don't use the"__cxa_get_exception_ptr"runtime routine ๐ โโ๏ธ. This causes"std::uncaught_exception"to be incorrect, but it's necessary if the runtime routine isn't available ๐ ๏ธ.-fvisibility-inlines-hiddenโ this switch declares that the user doesn't try to compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects ๐ซฃ.
The effect is that 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 used inside the DSO ๐ฆ. Turning this on can have a dramatic effect on the load and link times of a DSO, because it massively shrinks the dynamic export table when the library makes heavy use of templates ๐.
The behavior isn't quite the same as marking the methods as hidden directly, because it doesn't affect static variables local to the function, and it doesn't make the compiler deduce that the function is defined in only one shared object ๐ง.
You can give a method an explicit visibility to cancel out the effect of the switch for that method ๐ซ. For example, if you do want to compare pointers to a particular inline method, you might mark it as having default visibility ๐. Marking the enclosing class with explicit visibility has no effect ๐.
Explicitly instantiated inline methods are unaffected by this option, since their linkage might otherwise cross a shared library boundary ๐.
-fvisibility-ms-compatโ okay so this one is a whole mood ๐ It tries to use visibility settings to make GCC's C++ linkage model act like Microsoft Visual Studio's, bestie ๐
It makes these changes to GCC's linkage model:
- It sets the default visibility to "hidden", same as
-fvisibility=hidden๐ - Types are not hidden by default, but their members are ๐
- The One Definition Rule gets relaxed for types with no explicit visibility specification that are defined in more than one shared object. Those declarations are allowed if they'd be allowed without this option โจ
Honestly, in new code you should use -fvisibility=hidden and export only the classes you actually want visible outside. Unfortunately, code might be relying on the Visual Studio behavior, perhaps by accident ๐ญ
Some of the fallout: static data members of the same type, with the same name, defined in different shared objects are different, so changing one won't change the other ๐ Also, pointers to function members defined in different shared objects may not compare equal. And when this flag is given, defining types with the same name in different ways is a violation of the ODR ๐จ
-fno-weakโ no weak symbol support, even if your linker provides it ๐ โโ๏ธ By default, G++ uses weak symbols when they're available. This one only exists for testing and should not be used by end-users. It gives you inferior code and has no benefits, so don't. 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 turned off, those suffixes are treated as C++11 user-defined literal numeric suffixes instead. It's on by default for all pre-C++11 dialects and all GNU dialects:-std=c++98,-std=gnu++98,-std=gnu++11,-std=gnu++14. It's off by default for ISO C++11 onwards (-std=c++11, ...) ๐ธ-nostdinc++โ skips the standard directories that are specific to C++ when searching for header files, but still searches the other standard directories ๐ง (This one is used when building the C++ library, so it's giving behind-the-scenes energy ๐)-flang-info-include-translate,-flang-info-include-translate-not,-flang-info-include-translate=headerโ these tell you about include translation events ๐ The first notes accepted include translations, the second notes declined ones. Theheaderform informs you about include translations for 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โ informs you about Compiled Module Interface pathnames ๐ฆ The first one notes all read CMI pathnames. The module form does not read a specific module's CMI, which is the vibe to remember here ๐ module may be a named module or a header-unit. A header-unit is indicated by either a pathname containing directory separators, or by 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 options:libstdc++(the default, native C++ runtime for G++) andlibc++, which is the C++ runtime installed on some operating systems (for example, Darwin versions from Darwin11 onwards). This switches G++ to use the headers from the library you pick, and emits "-lstdc++" or "-lc++" respectively when a C++ runtime is needed for linking ๐ฅ
In addition, these warning options only have meanings for C++ programs, so here's the C++-only tea โ
-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 on ABI tags โจ-Wcomma-subscript(C++ and Objective-C++ only) โ warns about uses of a comma expression inside a subscripting expression ๐ This was deprecated in C++20 and is going to be removed in C++23. A comma expression wrapped in "( )" is not deprecated, though, so you're safe there ๐ Example:
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 is found and supports the right number and types of arguments ๐ฆ G++ will accept the formerly valid syntax for code that's not valid in C++23, but used to be valid (though deprecated) in C++20, with a pedantic warning. You can disable that with -Wno-comma-subscript ๐
It's enabled by default with -std=c++20 unless you use -Wno-deprecated, and after -std=c++23 regardless of -Wno-deprecated. Before -std=c++20, it's enabled with an 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 with no explicitly written deduction guides ๐ This points out cases where CTAD only succeeded because the compiler synthesized the implicit deduction guides, which might not be what the programmer meant. Some style guides only allow CTAD on types that specifically "opt-in", meaning types designed to support CTAD ๐ง You can suppress this warning 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 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 is bound to a temporary whose lifetime has already ended ๐ For example:
int n = 1;
const int& r = std::max(n - 1, n + 1); // r is dangling
In that example, two temporaries are created, one for each argument, and a reference to one of them is returned. Both temporaries are 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 safe in this respect. For example, "std::use_facet" takes and returns a reference, but it doesn't return one of its 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. In that case, the warning is disabled for all the member functions โจ
-Wdangling-reference also warns about code like this:
auto p = std::minmax(1, 2);
where "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" ๐ฅ
The warning doesn't fire 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. That means the class is a non-union class that has a pointer data member and a trivial destructor.
You can disable the warning by using the "gnu::no_dangling" attribute ๐ โโ๏ธ
This warning is enabled by -Wextra ๐ฅ
-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ warns when "delete" is used to destroy an instance of a class that has virtual functions and a non-virtual destructor ๐จ It's unsafe to delete an instance of a derived class through a pointer to a base class 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. With-Wdeprecated-copy-dtor, it also deprecates the implicit declaration if the class has a user-provided destructor ๐ซถ-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only) โ disables the warning about when the usual arithmetic conversions are applied to operands where one is an enumeration type and the other is a different enumeration type ๐ This conversion was deprecated in C++20. For 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, you can enable this warning with -Wenum-conversion or -Wdeprecated ๐
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only) โ disables the warning about when the usual arithmetic conversions are applied to operands where one is an enumeration type and the other is a floating-point type ๐ซง This conversion was deprecated in C++20. For 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, you can enable this warning with -Wenum-conversion or -Wdeprecated โจ
-Wdeprecated-literal-operator(C++ and Objective-C++ only) โ okay so this one warns you that declaring a user-defined literal operator with a space before the suffix is deprecated ๐ โโ๏ธ. It's on by default in C++23, or whenever you explicitly turn on-Wdeprecated. ๐
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) โ leaving out the comma before the varargs...at the end of a parameter list is deprecated, and this warning tells you so ๐. It's enabled by default in C++26, or with an explicit-Wdeprecated. โจ
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 up, this warns if an (invalid) extra enum-base shows up in an elaborated-type-specifier ๐. Basically that's an enum with a given underlying type and no enumerator list, used somewhere other than a standalone declaration of the enum. It's enabled by default, and-pedantic-errorsupgrades it into a full error. ๐ญ-Wno-init-list-lifetime(C++ and Objective-C++ only) โ this turns off warnings forstd::initializer_listuses that are likely to leave you with dangling pointers ๐. The underlying array of aninitializer_listgets treated like a normal C++ temporary, so it's super easy to accidentally keep a pointer to that array after its lifetime is over. Some classic ways that happens:- 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 returned value 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 made for the right side of the assignment only lives until the end of the full-expression. So by the next statement, that variable 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 is 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โ this warns when a function never produces a constant expression ๐ง. In C++20 and earlier, everyconstexprfunction and function template needs at least one set of arguments in at least one instantiation where calling it could be an evaluated subexpression of a core constant expression. C++23 dropped that rule, so you can now have aconstexprfunction or function template where no call ever meets the requirements of a core constant expression.
This warning is enabled as a pedantic warning by default in C++20 and earlier. In C++23, you can turn -Winvalid-constexpr on, and then it becomes an ordinary warning. For example:
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โ this checks that all imported macro definitions are valid at the end of compilation ๐ฆ. It's not on by default, because it needs extra processing to figure out. It can be really handy when you're preparing sets of header-units and want your macros to stay consistent. ๐ซถ-Wno-literal-suffix(C++ and Objective-C++ only) โ this stops the warning when a string or character literal is 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 using formatting macros from<inttypes.h>working. For 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 start with an underscore. Those suffixes are reserved for future standardization, so GCC warns you about them ๐. These warnings are enabled by default.
-Wno-narrowing(C++ and Objective-C++ only) โ for C++11 and later, narrowing conversions get diagnosed by default, just like the standard requires ๐ซ. A narrowing conversion from a constant is an error, and a narrowing conversion from a non-constant is a warning.-Wno-narrowingsilences that diagnostic. Heads up: this doesn't change what well-formed code means, since narrowing conversions are still ill-formed in SFINAE contexts. ๐ โโ๏ธ
With -Wnarrowing in C++98, you get a warning when a narrowing conversion that C++11 prohibits happens inside { }, like this:
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) โ warns when anoexcept-expression evaluates to false because of a call to a function that doesn't have a non-throwing exception specification (so nothrow()ornoexcept), even though the compiler knows it never actually throws an exception ๐ค.-Wnoexcept-type(C++ and Objective-C++ only) โ this warns if the C++17 feature that makesnoexceptpart of a function type changes the mangled name of a symbol compared to C++14 ๐. It's enabled by-Wabiand-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) โ this warns when the destination of a call to a raw memory function, likememsetormemcpy, is an object of class type ๐. It also warns when writing into that object might sidestep a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers. Messing with the representation of those objects can break invariants that the class's member functions rely on. For example, thememsetcall below is undefined because it modifies a non-trivial class object, so it gets flagged:
std::string str = "abc";
memset (&str, 0, sizeof str);
The safe move is to initialize or clear those objects with the appropriate constructor or assignment operator, if one exists โจ. -Wclass-memaccess is enabled by -Wall. Explicitly casting the pointer to the class object to void *, or to a type that the raw memory function can safely access, suppresses the warning.
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ this warns when a class has virtual functions and an accessible non-virtual destructor, either on itself or on an accessible polymorphic base class ๐ฌ. That combo makes it possible (but unsafe) to delete a derived-class instance through a pointer to the class or base class. This warning gets turned on automatically when you specify-Weffc++. Honestly,-Wdelete-non-virtual-dtor(enabled by-Wall) is the better pick, because it warns about the unsafe cases without false positives. ๐-Wregister(C++ and Objective-C++ only) โ warns on uses of theregisterstorage class specifier, unless it's part of the GNU Explicit Register Variables extension ๐๏ธ.registerwas deprecated in C++11 and removed in C++17. It's enabled by default with-std=c++17.-Wreorder(C++ and Objective-C++ only) โ warns when the order of member initializers in your code doesn't match the order they actually have to run 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. -Wreorder is enabled by -Wall.
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this warns when a call tostd::movestops copy elision from happening ๐ โโ๏ธ. A typical case where copy elision can kick in is when you return from a function with a class return type, the expression being returned is the name of a non-volatile automatic object (and not a function parameter), and it has the same type as the function's return type. Check this one out:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
In this example, the std::move call prevents copy elision, so you get the warning. This warning is enabled by -Wall. ๐
-Wno-redundant-move(C++ and Objective-C++ only) โ this warns about redundant calls tostd::move, meaning a move operation would have happened even without thestd::movecall ๐ซ . 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);
}
okay so here the std::move call is redundant ๐ and bestie, G++ implements Core Issue 1579, so there's another example that's lowkey sneaky:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
in this one, copy elision isn't applicable because the type of the expression being returned and the function return type differ ๐ but G++ still treats the return value as if it were designated by an rvalue. it's giving confusing, fr fr ๐ธ
This warning is enabled by -Wextra โจ
-Wrange-loop-construct(C++ and Objective-C++ only) โ the main character of this warning is an unnecessary copy inside a C++ range-based for-loop ๐ฆ it happens when the range declaration isn't a reference, but it probably should be. for example:
struct S { char arr[128]; };
void fn () {
S arr[5];
for (const auto x : arr) { ... }
}
it does not warn when the type being copied is a trivially-copyable type whose size is less than 64 bytes, so no need to panic over tiny stuff ๐ซถ
this warning also catches a loop variable in a range-based for-loop that gets initialized with a value of a different type, which results in a copy. like:
void fn() {
int arr[10];
for (const double &x : arr) { ... }
}
in the example above, every single iteration makes a temporary value of type double that gets created and destroyed, and the reference const double & is bound to it. not it ๐ญ
This warning is enabled by -Wall ๐
-Wredundant-tags(C++ and Objective-C++ only) โ 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 an ambiguity โจ for example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
but on the other hand, in this example there is no warning, because the keyword is actually necessary:
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) โ turns off the warning for when a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐ if a type A depends on a type B with no or internal linkage, defining it in multiple translation units would be an ODR violation, because the meaning of B is different in each translation unit. 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 as well. the compiler doesn't give this warning for types defined in the main .C file, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default ๐ง-Weffc++(C++ and Objective-C++ only) โ warns about violations of the following style guidelines from Scott Meyers' Effective C++ series of books ๐- 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 enables -Wnon-virtual-dtor, which is also one of the effective C++ recommendations. however, the check is extended to warn about the lack of virtual destructor in accessible non-polymorphic bases classes too ๐
heads up: when you pick this option, the standard library headers don't obey all of these guidelines, so use grep -v to filter out those warnings ๐
-Wno-exceptions(C++ and Objective-C++ only) โ disables the warning for when an exception handler is shadowed by another handler, which can point out a wrong ordering of exception handlers ๐-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about the use of an uncasted "NULL" as sentinel. when compiling only with GCC this is a valid sentinel, since "NULL" is 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. BUT this use is not portable across different compilers, so be careful bestie โญ-Wno-non-template-friend(C++ and Objective-C++ only) โ disables warnings when non-template friend functions are declared within a template. in very old versions of GCC that predate the implementation of the ISO standard, declarations such asfriend int foo(int), where the name of the friend is an unqualified-id, could be interpreted as a particular specialization of a template function. the warning exists to diagnose compatibility problems, and it's enabled by default ๐-Wold-style-cast(C++ and Objective-C++ only) โ warns if an old-style (C-style) cast to a non-void type is used within a C++ program ๐ the new-style casts ("dynamic_cast", "static_cast", "reinterpret_cast", and "const_cast") are less vulnerable to unintended effects and way easier to search for, so ngl, use those instead ๐-Woverloaded-virtual(C++ and Objective-C++ only)-Woverloaded-virtual=nโ warns when a function declaration hides virtual functions from a base class ๐ฆ for example, in:
struct A {
virtual void f();
};
struct B: public A {
void f(int); // does not override
};
the "A" class version of "f" is hidden in "B", and code like this:
B* b;
b->f();
fails to compile ๐
in cases where the different signatures are not an accident, the simplest solution is to add a using-declaration to the derived class to un-hide the base function, e.g. add "using A::f;" to "B" ๐ซถ
the optional level suffix controls the behavior when all the declarations in the derived class override virtual functions in the base class, even if not all of the base functions are overridden. for example:
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 used virtually, the user might have decided that the base class semantics for some of the overloads are fine.
at level 1, this case does not warn; at level 2, it does. -Woverloaded-virtual by itself selects level 2. 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 to a plain pointer ๐ธ-Wsign-promo(C++ and Objective-C++ only) โ warns when overload resolution chooses a promotion from an unsigned or enumerated type to a signed type, over a conversion to an unsigned type of the same size. previous versions of G++ tried to preserve unsignedness, but the standard mandates the current behavior ๐-Wtemplates(C++ and Objective-C++ only) โ warns when a primary template declaration is encountered. some coding rules disallow templates, and this can be used to enforce that rule. the warning is inactive inside a system header file, such as the STL, so you can still use the STL ๐ง one may also instantiate or specialize templates, no warning there ๐-Wmismatched-new-delete(C++ and Objective-C++ only) โ warns for mismatches between calls to "operator new" or "operator delete" and the corresponding call to the allocation or deallocation function ๐ญ this includes invocations of C++ "operator delete" with pointers returned from either mismatched forms of "operator new", or from other functions that allocate objects for which the "operator delete" isn't a suitable deallocator, as well as calls to other deallocation functions with pointers returned from "operator new" for which the deallocation function isn't suitable.
for example, the "delete" expression in the function below gets diagnosed, because it doesn't match the array form of the "new" expression the pointer argument was returned from. similarly, the call to "free" is also diagnosed:
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 diagnoses mismatches involving allocation and deallocation functions other than "operator new" and "operator delete" ๐
-Wmismatched-new-delete is included in -Wall ๐ฅ
-Wmismatched-tags(C++ and Objective-C++ only) โ warns for declarations of structs, classes, and class templates and their specializations with a class-key that doesn't match either the definition or the first declaration if no definition is provided ๐
for example, the declaration of "struct Object" in the argument list of "draw" triggers the warning. to avoid it, either remove the redundant class-key "struct" or replace it with "class" to match its definition:
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
it's not wrong to declare a class with the class-key "struct" as the example above shows ๐ the -Wmismatched-tags option is intended to help achieve a consistent style of class declarations. in code that's meant to be portable to Windows-based compilers, the warning helps prevent unresolved references due to the difference in the mangling of symbols declared with different class-keys ๐ the option can be used either on its own or in conjunction with -Wredundant-tags ๐ซถ
-Wmultiple-inheritance(C++ and Objective-C++ only) โ okay so this one warns you when a class is defined with multiple direct base classes ๐ Some coding rules ban multiple inheritance, so this is how you enforce that rule ๐ It goes quiet inside system header files like the STL, so you can still use the STL freely ๐ You're also still allowed to define classes that indirectly use multiple inheritance โจ-Wvirtual-inheritanceโ this warns when a class is defined with a virtual direct base class ๐ฆ Same deal as above: some coding rules disallow multiple inheritance, and this helps enforce that ๐ It's also silent inside system headers like the STL, and you can still define classes that indirectly use virtual inheritance ๐ธ-Wno-virtual-move-assignโ this one suppresses warnings about inheriting from a virtual base that has a non-trivial C++11 move assignment operator ๐ Heads up, this is a bit of a danger zone ๐ 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 so it never moves from a moved-from object, you're safe to turn this warning off ๐ซถ-Wnamespacesโ warns when a namespace definition is opened ๐ง Some coding rules say no namespaces, and this is the enforcer ๐ Like the others, it's inactive inside system header files such as the STL, so the STL is still yours ๐ You can also still use using directives and qualified names ๐-Wno-template-body(C++ and Objective-C++ only) โ this disables diagnosing errors while parsing a template, and instead hits you with an error only when the template actually gets instantiated ๐ซ It can also downgrade those errors into warnings with Wno-error= or -fpermissive โจ-Wno-template-id-cdtor(C++ and Objective-C++ only) โ this turns off the warning about using a simple-template-id as the declarator-id of a constructor or destructor ๐ That stopped being valid in C++20 thanks to DR 2237, so here's what that looks like:
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 turned on by -Wc++20-compat ๐
-Wtemplate-names-tu-localโ this warns when a template body hides an exposure of a translation-unit-local entity ๐ Usually, referring to a translation-unit-local entity (like an internal linkage declaration) 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 isn't an exposure, so no error gets emitted ๐
The tricky part: variable or function templates can accidentally become unusable if they reference one of these entities, because other translation units that import the template will never be able to instantiate it ๐ญ This warning tries to catch cases where that might happen ๐ต๏ธโโ๏ธ An explicit instantiation silences the warning ๐คซ
This flag is enabled by -Wextra ๐
-Wno-terminate(C++ and Objective-C++ only) โ disables the warning about a throw-expression that will immediately result in a call to "terminate" ๐ฅ-Wno-vexing-parse(C++ and Objective-C++ only) โ this warns about the most vexing parse syntactic ambiguity ๐คฏ It flags declarations that look like variable definitions, but C++ says they have to be read as function declarations ๐ For instance:
void f(double a) {
int i(); // extern int i (void);
int n(int(a)); // extern int n (int);
}
Another example:
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, e.g. 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 kind of pointless ๐-Wvolatile(C++ and Objective-C++ only) โ warns about deprecated uses of the "volatile" qualifier ๐ That includes:- postfix and prefix "++" and "--" expressions of "volatile"-qualified types
- simple assignments where the left operand is a "volatile"-qualified non-class type, using its value
- compound assignments where the left operand is a "volatile"-qualified non-class type
- "volatile"-qualified function return types
- "volatile"-qualified parameter types
- structured bindings of a "volatile"-qualified type
This usage was deprecated in C++20 ๐ฅฒ
It's enabled by default with -std=c++20. Before -std=c++20, it's enabled with an explicit -Wdeprecated ๐
-Waligned-newโ warns about a new-expression of a type that needs greater 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-newand-Wplacement-new=nโ warns about placement new expressions with undefined behavior, like constructing an object in a buffer that's smaller than the object's type ๐ฑ For example, this placement new gets diagnosed because it tries to construct an array of 64 integers in a buffer that's only 64 bytes:
char buf [64];
new (buf) int[64];
This warning is enabled by default ๐ซถ
-Wplacement-new=1โ this is the default warning level for-Wplacement-new๐ At this level, the warning isn't issued for some strictly undefined constructs that GCC allows as extensions for compatibility with legacy code ๐ซ For example, the following "new" expression isn't diagnosed at this level, even though the C++ standard says it's undefined behavior, 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โ at this level, GCC 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 the size is less than the size of the object being constructed ๐ฅ The previous example would be diagnosed here, but the following construct uses the flexible member array extension to dodge 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-valueand-Wcatch-value=n(C++ and Objective-C++ only) โ warns about catch handlers that don't catch via reference ๐ โโ๏ธ-Wcatch-value=1(or just-Wcatch-valuefor short) warns about polymorphic class types that are caught by value ๐ง-Wcatch-value=2warns about all class types that are caught by value ๐ซ-Wcatch-value=3warns about all types that are not caught by reference ๐
-Wcatch-value is enabled by -Wall โจ
-Wconditionally-supported(C++ and Objective-C++ only) โ warns for conditionally-supported constructs (C++11 [intro.defs]) ๐งฉ-Wno-defaulted-function-deleted(C++ and Objective-C++ only) โ warns 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 have 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 behavior at runtime ๐ฌ This warning is enabled by default ๐-Wextra-semi(C++, Objective-C++ only) โ warns about redundant semicolons ๐ Extra semicolons can pop up in a few different places:- a semicolon after in-class function definitions, which is valid in all C++ dialects and is never a pedwarn:
struct S {
void foo () {};
};
- an extra semicolon at namespace scope, which has been allowed since C++11 (so it's a pedwarn in C++98):
struct S {
};
;
- an extra semicolon in class definitions, which 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) โ this controls warnings when a base class is inaccessible in a class derived from it because of ambiguity ๐ The 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 using C++11 inheriting constructors when the base class being inherited from has a C variadic constructor ๐ The warning is on by default, because the ellipsis is not inherited ๐ซ-Wno-invalid-offsetof(C++ and Objective-C++ only) โ suppresses warnings from applying the "offsetof" macro to a non-POD type ๐ According to the 2014 ISO C++ standard, applying "offsetof" to a non-standard-layout type is undefined ๐ณ In existing C++ implementations, though, "offsetof" typically gives meaningful results ๐คทโโ๏ธ This flag is for users who know they're writing nonportable code and have deliberately chosen to ignore the warning ๐
The restrictions on "offsetof" may be relaxed in a future version of the C++ standard ๐ธ
-Wsized-deallocation(C++ and Objective-C++ only) โ bestie, this one warns when you define an unsized deallocation function but there's no matching sized one (or the other way around) ๐งนโจ The unsized version looks like this:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
and the sized version looks like this:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
It's enabled by -Wextra along with -fsized-deallocation ๐
-Wsuggest-final-typesโ this one is giving code-review energy ๐ง It warns about types with virtual methods where your code would be cleaner if the type were declared with the C++11finalspecifier or, if possible, declared in an anonymous namespace. That lets GCC devirtualize the polymorphic calls more aggressively, which is lowkey iconic ๐ This warning hits harder with link-time optimization, because the class hierarchy graph is more complete then ๐ธ-Wsuggest-final-methodsโ same vibe, but at the method level ๐ฆ It warns about virtual methods that would be better off declared with the C++11finalspecifier or, if possible, with their type declared in an anonymous namespace or with thefinalspecifier. Again, this is more effective with link-time optimization, when the class hierarchy graph is more complete ๐ Pro tip from the manual (not me, the manual ๐): look at the-Wsuggest-final-typessuggestions first, then rebuild with the new annotations โจ-Wsuggest-overrideโ warns about overriding virtual functions that aren't marked with theoverridekeyword. No sneaky overrides allowed, periodt ๐-Wno-conversion-null(C++ and Objective-C++ only) โ this one turns off warnings for conversions betweenNULLand non-pointer types ๐ โโ๏ธ Heads up,-Wconversion-nullis enabled by default, so you'd have to ask for this one specifically ๐ฅบ
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
(Quick note first, okay? ๐ This manual does not describe the Objective-C and Objective-C++ languages themselves. This section is only about the command-line options that are meaningful for Objective-C and Objective-C++ programs. You can also use most of the language-independent GNU compiler options. 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. You can use the other options with any language GCC supports ๐
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's the list of options that are only for compiling Objective-C and Objective-C++ programs ๐
-fconstant-string-class=class-nameโ tells GCC which class to instantiate for each literal string written with the@"..."syntax ๐ง Use class-name as that class. The default isNXConstantStringif the GNU runtime is being used, andNSConstantStringif the NeXT runtime is being used (see below). On Darwin / macOS platforms, the-fconstant-cfstringsoption, if it's also present, overrides the-fconstant-string-classsetting and causes@"..."literals to be laid out as constant CoreFoundation strings. Also,-fconstant-cfstringsis an alias for the target-specific-mconstant-cfstringsequivalent ๐-fgnu-runtimeโ generates object code compatible with the standard GNU Objective-C runtime. This is the default on most types of systems ๐ฃ-fnext-runtimeโ generates output compatible with the NeXT runtime. This is the default on NeXT-based systems, including Darwin / macOS ๐ The macro__NEXT_RUNTIME__is predefined if, and only if, this option is used โจ-fno-nil-receiversโ assumes that all Objective-C message dispatches ([receiver message:arg]) in this translation unit make sure the receiver is notnil. That lets the runtime use more efficient entry points ๐โโ๏ธ This option is only available together with the NeXT runtime and ABI version 0 or 1.-fobjc-abi-version=nโ uses 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 you don't specify anything, the default is version 0 on 32-bit target machines, and version 2 on 64-bit target machines ๐-fobjc-call-cxx-cdtorsโ for each Objective-C class, GCC checks whether any of its instance variables is a C++ object with a non-trivial default constructor. If so, it synthesizes a special- (id) .cxx_constructinstance method, which runs those non-trivial default constructors on the instance variables, in order, and then returnsself. It also checks whether any instance variable is a C++ object with a non-trivial destructor, and if so, synthesizes a special- (void) .cxx_destructmethod, which runs all those 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, not the ones inherited from superclasses. It's the Objective-C runtime's responsibility to invoke all of these methods across an object's inheritance hierarchy. The - (id) .cxx_construct methods get invoked by the runtime right after a new object instance is allocated, and the - (void) .cxx_destruct methods get invoked right before the runtime deallocates an object instance ๐ซง
As of this writing, only the NeXT runtime on Mac OS X 10.4 and later can invoke the - (id) .cxx_construct and - (void) .cxx_destruct methods ๐
-fobjc-direct-dispatchโ allows fast jumps to the message dispatcher. On Darwin, this is done via the comm page ๐-fobjc-exceptionsโ enables 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 it's not available together with the NeXT runtime on Mac OS X 10.2 and earlier ๐-fobjc-gcโ enables garbage collection (GC) in Objective-C and Objective-C++ programs ๐๏ธ This is only available with the NeXT runtime. The GNU runtime has a different garbage collection implementation that doesn't need any special compiler flags ๐งน-fobjc-nilcheckโ for the NeXT runtime with version 2 of the ABI, checks for anilreceiver in method invocations before doing the actual method call ๐ This is the default, and you can turn it off with-fno-objc-nilcheck. Class methods and super calls are never checked fornilthis way, no matter what this flag is set to. Right now this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is used ๐-fobjc-std=objc1โ conforms 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 doesn't change conformance to C/C++ standards, which is controlled by the separate C/C++ dialect option flags. When you use this option with the Objective-C or Objective-C++ compiler, any Objective-C syntax that GCC 4.0 doesn't recognize gets rejected. It's useful if you need to make sure your Objective-C code can be compiled with older versions of GCC ๐ฐ๏ธ-freplace-objc-classesโ emits a special marker that tellsld(1)not to statically link the resulting object file, and letsdyld(1)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 together with the NeXT runtime on Mac OS X 10.3 and later โจ-fzero-linkโ when compiling for the NeXT runtime, the compiler normally replaces calls toobjc_getClass("...")(when the class name is known at compile time) with static class references that get initialized at load time, which is better for run-time performance ๐๏ธ Specifying-fzero-linksuppresses that behavior and keeps the calls toobjc_getClass("..."). This is useful in Zero-Link debugging mode, since it lets you modify individual class implementations during program execution. The GNU runtime currently always keeps 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. That can cause shadowing between instance variables and other variables declared locally inside a class method, or globally, with the same name ๐ Specifying-fno-local-ivarsdisables this behavior, which avoids those variable shadowing issues ๐ท-fivar-visibility=[public|protected|private|package]โ sets the default instance variable visibility to the option you choose, so that instance variables declared outside the scope of any access modifier directive 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) โ doesn't warn if a property for an Objective-C object has no assign semantics specified ๐คซ
Okay so bestie, we're picking up right where the Objective-C warnings get spicy ๐
-Wno-protocol(Objective-C and Objective-C++ only) โ okay so if a class says it implements a protocol, GCC yells at you for every protocol method the class doesn't implement ๐ค By default it even yells about methods the class inherits from its superclass without explicitly implementing them. But if you use-Wno-protocol, inherited methods count as implemented and GCC stays quiet about them ๐ซถ-Wobjc-root-class(Objective-C and Objective-C++ only) โ warns if a class interface has no superclass. Most classes inherit from "NSObject" (or "Object"), for example ๐ If you're making a root class on purpose, you can shut the warning up by marking its interface with "__attribute__((objc_root_class))" โจ-Wselector(Objective-C and Objective-C++ only) โ warns if you end up with multiple methods of different types for the same selector during compilation ๐ It checks the method list at the very final stage of compilation, and it also checks each selector used in a@selector(...)expression that has a matching method somewhere in the compilation. Because all of this happens only at the end, these warnings won't show up if the final stage never gets reached, like when there's an error earlier on or when you're using-fsyntax-only๐-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're sending a message to a receiver of type "id" or "Class" ๐ฅ This is off by default, and when it's off GCC skips the warning if the differences are only between types that share the same size and alignment.-Wundeclared-selector(Objective-C and Objective-C++ only) โ warns if you use a@selector(...)expression for a selector that hasn't been declared yet ๐ โโ๏ธ 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 one checks the moment it spots a@selector(...)expression, while-Wselectorwaits for the final stage. It also enforces the coding style rule that methods and selectors must be declared before you use them ๐ง-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 where you pick which OpenMP and OpenACC offload targets get code generated for them ๐ฏ The default, which is the same as-foffload=default, generates 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 name ๐
Offload targets are written in GCC's internal target-triplet format ๐ง If you want to see the list of configured offload targets, run the compiler with -v and look for "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 only want options for specific 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:
-foffload-options='-fno-math-errno -ffinite-math-only' \
-foffload-options=nvptx-none=-latomic
-foffload-options=amdgcn-amdhsa=-march=gfx906
-fopenaccโ enables 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 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 sizes separated by colons, in the order gang, worker, and vector. You can leave a size out to use a target-specific default value โจ-fopenmpโ enables handling of OpenMP directives in C/C++:#pragma omp,[[omp::directive(...)]],[[omp::decl(...)]], and[[omp::sequence(...)]]๐ In Fortran it turns on!$ompand the conditional compilation sentinel!$. In fixed source form Fortran, the sentinels can also start withcor*.
This option implies -pthread, so it's only supported on targets that support -pthread. Also, -fopenmp 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, using#pragma omp,[[omp::directive(...)]],[[omp::sequence(...)]], and[[omp::decl(...)]]in C/C++, and!$ompin Fortran ๐ธ It also turns on the conditional compilation sentinel!$in Fortran, and in fixed source form Fortran the sentinels can start with c or * too. Other OpenMP directives get ignored ๐
Unless you also specify -fopenmp, the "loop" region binds to the current task region, no matter what the "bind" clause says ๐ง
-fopenmp-target-simd-clone,-fopenmp-target-simd-clone=device-typeโ besides making SIMD clones for functions marked with "declare simd", GCC also makes clones for functions marked with the OpenMP "declare target" directive that are good candidates for vectorization while this option is active ๐ The device-type can be "none", "host", "nohost", or "any". These match the keywords for the "device_type" clause of the "declare target" directive, 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 what the output device looked like (its width, and so on) ๐ The options below let you control the formatting algorithm, like how many characters go on each line and 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 sits on a single line. This is the default for all front ends.
Note: this option also affects the display of the #error and #warning pre-processor directives, and the deprecated function/type/variable attribute. It does not affect the pragma GCC warning and pragma GCC error pragmas ๐
โโ๏ธ
-fdiagnostics-plain-outputโ requests that diagnostic output look as plain as possible ๐ค This can be 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 equivalent to all of these:-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
If GCC ever changes the default look of its diagnostics in the future, the matching option to turn off the new behavior will get 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 get repeated 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 emit the same source location info (as a prefix) for every physical line that comes out of breaking up a message that's too long for one line ๐งต-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ uses color in diagnostics ๐จ WHEN isnever,always, orauto. The default depends on how the compiler was configured. It can be any of those WHEN options, orneverif theGCC_COLORSenvironment variable isn't present, andautootherwise.automakes GCC use color only when standard error is a terminal and it's not running inside an emacs shell ๐ The forms-fdiagnostics-colorand-fno-diagnostics-colorare aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively ๐
Okay so the colors are controlled by the environment variable GCC_COLORS ๐ Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings ๐
SGR commands get interpreted by your terminal or terminal emulator, so if you want the permitted values and what they mean as character attributes, check the section in your text terminal's documentation ๐ค These substring values are integers written in decimal, and you can stack them together with semicolons โจ
Common values to stack 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 mode 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 mode background colors ๐
The default GCC_COLORS is this bad boy ๐
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
So 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 set, bestie ๐ซถ
error=โ the SGR substring for error: markers ๐warning=โ the SGR substring for warning: markers โ ๏ธnote=โ the SGR substring for note: markers ๐path=โ the SGR substring for coloring paths of control-flow events, the ones printed via-fdiagnostics-path-format=. This covers the identifiers of individual events and the lines showing interprocedural calls and returns ๐ค๏ธrange1=โ the SGR substring for the first additional range ๐range2=โ the SGR substring for the second additional range ๐locus=โ the SGR substring for location info, likefile:lineorfile:line:columnetc ๐quote=โ the SGR substring for anything printed inside quotes ๐ฌfnname=โ the SGR substring for names of C++ functions ๐งtargs=โ the SGR substring for C++ function template parameter bindings ๐ธfixit-insert=โ the SGR substring for fix-it hints that suggest text to be inserted or replaced โfixit-delete=โ the SGR substring for fix-it hints that suggest text to be deleted โdiff-filename=โ the SGR substring for filename headers inside generated patches ๐diff-hunk=โ the SGR substring for the starts of hunks inside generated patches ๐งฉdiff-delete=โ the SGR substring for deleted lines inside generated patches ๐๏ธdiff-insert=โ the SGR substring for inserted lines inside generated patches ๐ฑtype-diff=โ the SGR substring for highlighting mismatching types within template arguments in the C++ frontend ๐ โโ๏ธvalid=โ the SGR substring for highlighting valid elements within text art diagrams โinvalid=โ the SGR substring for highlighting invalid elements within text art diagrams โhighlight-a=,highlight-b=โ the SGR substrings for contrasting two different things inside diagnostics, like a pair of mismatching types. Check out-fdiagnostics-show-highlight-colorsfor more ๐
โจ -fdiagnostics-urls[=WHEN] โจ
Uses escape sequences to embed URLs in diagnostics ๐ For example, when -fdiagnostics-show-option prints the command-line option controlling a diagnostic, it can embed a URL pointing at the docs for that option ๐
WHEN can be never, always, or auto ๐ auto makes GCC use URL escape sequences only when standard error is a terminal, and only 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 ๐ ๏ธ It can be any of the above WHEN options ๐
GCC can also be configured (through the --with-diagnostics-urls=auto-if-env configure-time option) so the default depends on environment variables ๐ In that setup, GCC defaults to auto if either the GCC_URLS or TERM_URLS environment variables are present and non-empty in the compiler's environment, and to never if neither one is ๐ธ
Even with -fdiagnostics-urls=always, the behavior still depends on those environment variables, though ๐ญ If GCC_URLS is set to empty or no, URLs are not embedded in diagnostics. If it's set to st, URLs use ST escape sequences. If it's set to bel, which is the default, URLs use BEL escape sequences. Any other non-empty value enables the feature ๐ If GCC_URLS isn't set, TERM_URLS is used as a fallback ๐ Quick note: ST is an ANSI escape sequence whose string terminator is ESC \, and BEL is an ASCII character (CTRL-G) that usually sounds like a beep ๐
Right now GCC also tries to detect a few terminals that don't implement the URL feature and that have bugs, or at least had bugs in versions still in use. With those, URL escapes are likely to misbehave and print garbage on the screen ๐๏ธ That list is currently xfce4-terminal, certain known-buggy gnome-terminal versions, the linux console, and mingw ๐ You can skip this check with -fdiagnostics-urls=always ๐ซก
โจ -fno-diagnostics-show-option โจ
By default, each diagnostic includes text naming the command-line option that directly controls it (if that option is known to the diagnostic machinery) ๐ฃ Passing -fno-diagnostics-show-option 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. If -fmessage-length=n is given, the source line gets truncated to n characters โ๏ธ When the output goes to a terminal, the width is limited to whatever the COLUMNS environment variable says or, if it isn't set, to the terminal width ๐
โจ -fno-diagnostics-show-labels โจ
By default, when printing source code (via -fdiagnostics-show-caret), diagnostics can label ranges of source with pertinent info, like the types of expressions ๐ท๏ธ
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option stops those labels from printing (in the example above, that's the vertical bars and the "char *" and "long int" text) ๐
โโ๏ธ
โจ -fno-diagnostics-show-event-links โจ
By default, when printing execution paths (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 carry an associated CWE ("https://cwe.mitre.org/index.html") identifier ๐ชฒ GCC itself only provides this metadata for some of the -fanalyzer diagnostics, and GCC plugins may also provide diagnostics with it ๐ By default, if the info is present, it gets printed along with the diagnostic. This option suppresses printing of this metadata ๐ซถ
โจ -fno-diagnostics-show-rules โจ
Diagnostic messages can optionally have rules attached, like 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 printing of this 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 one:
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, and the"int"in the quoted source, are colored usinghighlight-a(bold green by default), and - the
"const char *"in the message and in the quoted source are both colored usinghighlight-b(bold blue by default).
The whole point is to draw your eyes to how the different parts of the message relate to the source ๐ Color groups related stuff together and makes mismatched things stand out ๐
This extra colorization is turned on by default whenever color printing is enabled (as per -fdiagnostics-color=), but you can turn it off separately with -fno-diagnostics-show-highlight-colors ๐ซถ
โจ -fno-diagnostics-show-line-numbers โจ
By default, when printing source code (via -fdiagnostics-show-caret), a left margin showing line numbers gets printed ๐ข This option suppresses that left margin ๐
โจ -fdiagnostics-minimum-margin-width=width โจ
This option controls the minimum width of the left margin printed by -fdiagnostics-show-line-numbers ๐ It defaults to 6 ๐
-fdiagnostics-parseable-fixitsโ okay so this one is for the IDEs ๐ปโจ It spits out fix-it hints in a format a machine can actually read. After each relevant diagnostic you get a line that starts withfix-it:, like this:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
The location is a half-open range counted in bytes, and the column count starts at byte 1. So in that example, bytes 3 through 20 of line 45 in "test.c" get swapped out for the replacement string. Picture it like this ๐
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape backslash as "\\", tab as "\t", newline as "\n", and double quotes as "\"". Anything non-printable gets written in octal, so vertical tab becomes "\013" ๐ซถ
An empty replacement string means "delete this range." An empty range, like "45:3-45:3", means "insert the string right here." ๐ธ
-fdiagnostics-generate-patchโ this one prints the fix-it hints to stderr as a unified diff, after all the diagnostics have been printed ๐ Something like this:
--- 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. It follows the same rules as diagnostics, so go check -fdiagnostics-color if you want the details ๐
-fdiagnostics-show-template-treeโ in the C++ frontend, when you get those mismatching template type errors, this flag turns on a tree view that shows which parts match and which parts don't ๐ณ Without it, you get something like:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
With it, you get a tree-like structure showing the common and differing parts, like:
map<
[...],
vector<
[double != float]>>
The parts that differ get highlighted with color, so in this case "double" and "float" pop out ๐
-fno-elide-typeโ okay so by default, when the C++ frontend shows mismatching template types, it hides the shared bits and prints them as"[...]"to keep the message short ๐ Here's the default:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
If you add -fno-elide-type, GCC stops doing that. This flag also changes what -fdiagnostics-show-template-tree shows, so they're connected ๐
-fdiagnostics-path-format=KINDโ this tells GCC how to print the control-flow paths attached to a diagnostic ๐ค๏ธKINDcan benone,separate-events, orinline-events, andinline-eventsis the default โจ
none means don't print diagnostic paths at all. Bye bye, paths ๐
separate-events prints a separate note diagnostic for each event in the path. It looks like this:
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 prints the events right inside the source code. It tries to group events that are close together into runs and shows them as labelled ranges, which is so cute ๐ฆ The same events as above would look like:
'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 (events that jump between functions) gets grouped by stack frame, and indentation shows how the 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 one adds extra info when printing control-flow paths for a diagnostic ๐ If you turn it on, the stack depth gets printed for each run of events within-fdiagnostics-path-format=inline-events. If you use it together with-fdiagnostics-path-format=separate-events, then the stack depth and function declaration get tacked onto each event instead.
This one is mainly for GCC developers and plugin developers who are debugging diagnostics that report interprocedural control flow. Not really for the rest of us, bestie ๐ง
-fno-show-columnโ do not print column numbers in diagnostics ๐ โโ๏ธ This might be necessary if the diagnostics are being scanned by a program that doesn't understand column numbers, like dejagnu.-fdiagnostics-column-unit=UNITโ this picks the units used for column numbers ๐ It affects the traditional diagnostics (as long as you haven't used-fno-show-column) and also the JSON format diagnostics, if you asked for those.
The default UNIT is display, which counts the number of display columns each character takes up. That can be bigger than the byte count, like with tab characters, or smaller, like with multibyte characters. For example, "GREEK SMALL LETTER PI (U+03C0)" takes up one display column, but its UTF-8 encoding is two bytes. "SLIGHTLY SMILING FACE (U+1F642)" takes up two display columns, and its UTF-8 encoding is four bytes ๐
If you set UNIT to byte, the column number becomes the raw byte count in every case. That's how GCC did it before version 11.1.0, so it's the old-school vibe ๐
-fdiagnostics-column-origin=ORIGINโ this chooses the origin for column numbers, meaning which number the very first column gets ๐ข The default of1matches traditional GCC behavior and the GNU style guide. Some utilities might work better with an origin of0, and any non-negative value is allowed.-fdiagnostics-escape-format=FORMATโ okay so 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 Unicode normalization issues. Those get flagged so GCC escapes any bytes that aren't printable ASCII when it prints those lines.
This option controls how those bytes get escaped.
The default FORMAT is unicode. It shows non-printable-ASCII Unicode characters in the form <U+XXXX>. Bytes that don't correspond to a Unicode character validly encoded in UTF-8 get shown as hexadecimal in the form <XX> ๐ธ
For example, say a source line has the string before, followed by the Unicode character U+03C0 ("GREEK SMALL LETTER PI", with UTF-8 encoding 0xCF 0x80), followed by the byte 0xBF (a stray UTF-8 trailing byte), followed by the string after. For that diagnostic, it gets printed as:
before<U+03C0><BF>after
If you set FORMAT to bytes, every non-printable-ASCII byte shows up as <XX>. This lets you see the underlying encoding of non-ASCII Unicode characters. For the same example, you'd get:
before<CF><80><BF>after
-fdiagnostics-text-art-charset=CHARSETโ some diagnostics include "text art" diagrams, which are pictures made out of text meant to be viewed in a monospaced font ๐จ
This option picks which characters get used to draw those diagrams, if any. CHARSET can be none, ascii, unicode, or emoji ๐
The none value turns those little diagrams off completely ๐. ascii makes sure every diagram is pure ASCII, aka "ASCII art" ๐จ. unicode lets it use a conservative amount of unicode drawing characters, like box-drawing characters ๐
. And emoji goes full glam and adds emoji to the output โจ, such as printing U+26A0 WARNING SIGN followed by U+FE0F VARIATION SELECTOR-16 to pick the emoji version of the character ๐ซถ.
The default is emoji ๐, except when the environment variable LANG is set to C. Then it's ascii instead, because that's the safe choice ๐ซถ.
-fdiagnostics-format=FORMAT
Okay so this one lets you pick a different format for printing diagnostics ๐. FORMAT can be text, sarif-stderr, sarif-file, json, json-stderr, or json-file ๐ฆ.
Using this option replaces any extra "output sinks" added by -fdiagnostics-add-output=, or the ones set by -fdiagnostics-set-output= ๐
.
The default is text ๐ธ.
The sarif-stderr and sarif-file formats both emit diagnostics in SARIF Version 2.1.0 format. sarif-stderr sends them to stderr, and sarif-file writes them to a file named source.sarif โจ.
The various json, json-stderr, and json-file values are deprecated ๐. They refer to a legacy JSON-based output format. json is just a synonym for json-stderr ๐ง. The json-stderr and json-file formats are identical, apart from where the JSON gets emitted to. With json-stderr, the JSON goes to stderr, whereas with json-file it's written to source.gcc.json ๐.
-fdiagnostics-add-output=DIAGNOSTICS-OUTPUT-SPEC
Add an additional "output sink" for emitting diagnostics ๐.
DIAGNOSTICS-OUTPUT-SPEC should specify a scheme, optionally followed by : and one or more KEY=VALUE pairs, in this form:
<SCHEME>
<SCHEME>:<KEY>=<VALUE>
<SCHEME>:<KEY>=<VALUE>,<KEY2>=<VALUE2>
etc. ๐ซ
Schemes, keys, or values with a name prefixed "experimental" may change or be removed without notice ๐. Be careful with those ones, bestie!
SCHEME can be:
text: emits diagnostics to stderr using GCC's classic text output format ๐.
Supported keys are:
color=[yes|no]: overrides the colorization settings from-fdiagnostics-colorfor this text output ๐.experimental-nesting=[yes|no]: enables an experimental mode that emphasizes hierarchical relationships within diagnostics messages, showing location information on separate lines ๐งฉ.experimental-nesting-show-locations=[yes|no]: ifexperimental-nesting=yes, then locations are shown by default. Set this key tonoto stop printing them. This exists for GCC developers writing DejaGnu test cases ๐งช.experimental-nesting-show-levels=[yes|no]: a debugging option for use withexperimental-nesting=yes. Set it toyesto print explicit nesting levels in the output. This also exists for GCC developers ๐ ๏ธ.
sarif: emits diagnostics to a file in SARIF format ๐.
Supported keys are:
file=FILENAME: the filename to write the SARIF output to, which can have a leading absolute or relative path. If not specified, it defaults tosource.sarif๐.version=[2.1|2.2-prerelease]: the SARIF version to use for the output. If not specified, it defaults to2.1."2.2-prerelease"uses an unofficial draft of the future SARIF 2.2 specification and should only be used for experimentation in this release ๐งชโ ๏ธ.
For 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
would add a pair of outputs, each writing to a different file, using versions 2.1 and 2.2 of the SARIF standard respectively ๐ฏโโ๏ธ.
In EBNF:
<diagnostics-output-specifier> = <diagnostics-output-name>
| <diagnostics-output-name>, ":", <key-value-pairs>;
<diagnostics-output-name> = "text" | "sarif";
<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 "output sink," it replaces all existing output sinks ๐งน. That includes ones from -fdiagnostics-format=, -fdiagnostics-add-output=, or a prior call to -fdiagnostics-set-output= ๐
.
-fno-diagnostics-json-formatting
By default, when JSON gets emitted for diagnostics (via -fdiagnostics-format=sarif-stderr, -fdiagnostics-format=sarif-file, -fdiagnostics-format=json, -fdiagnostics-format=json-stderr, or -fdiagnostics-format=json-file), GCC adds newlines and indentation to visually show the hierarchical structure of the JSON ๐ธ.
Use -fno-diagnostics-json-formatting to suppress that whitespace ๐ซง. It must be passed before the option it is meant to affect โ ๏ธ.
This is meant for compatibility with tools that don't expect newlines in the output, like the kind emitted by older GCC releases ๐ฆ.
๐ Options to Request or Suppress Warnings ๐
Warnings are diagnostic messages that report constructions that aren't inherently erroneous, but are risky or suggest there may have been an error ๐.
The following language-independent options don't enable specific warnings. Instead, they control the kinds of diagnostics GCC produces ๐ง .
-fsyntax-only
Checks the code for syntax errors, but doesn't do anything beyond that ๐.
-fmax-errors=n
Limits the maximum number of error messages to n. Once that number is hit, GCC bails out instead of trying to keep processing the source code ๐. If n is 0 (the default), there's no limit on the number of error messages produced ๐. If -Wfatal-errors is also specified, then -Wfatal-errors takes precedence over this option ๐.
-w: inhibits all warning messages ๐คซ.-Werror: turns all warnings into errors ๐.
-Werror=
Turns the specified warning into an error ๐จ. You append the specifier for a warning to it. For example, -Werror=switch turns the warnings controlled by -Wswitch into errors ๐. This switch also has a negative form, which negates -Werror for specific warnings. For example, -Wno-error=switch makes -Wswitch warnings not be errors, even when -Werror is 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= as described above ๐. (Printing of the option in the warning message can be disabled with the -fno-diagnostics-show-option flag ๐.)
Note that specifying -Werror=foo automatically implies -Wfoo. However, -Wno-error=foo doesn't imply anything at all ๐ซ .
-Wfatal-errors
Causes the compiler to abort compilation on the first error that occurred, instead of trying to keep going and printing further error messages ๐ญ.
You can request many specific warnings with options beginning with -W. For example, -Wunused-variable requests warnings on declarations of variables that are never used ๐. Each of these specific warning options also has a negative form beginning with -Wno- to turn warnings off. For example, -Wno-unused-variable ๐. This manual only lists one of the two forms, whichever one isn't the default ๐. For further language-specific options, also refer to C++ Dialect Options and Objective-C and Objective-C++ Dialect Options ๐. Additional warnings can be produced by enabling the static analyzer;
Some options, such as -Wall and -Wextra, turn on other options, such as -Wunused, which may turn on further options, such as -Wunused-variable ๐. The combined effect of positive and negative forms is that more specific options have priority over less specific ones, no matter their position on the command line ๐. For options of the same specificity, the last one takes effect ๐. Options enabled or disabled via pragmas take effect as if they appeared at the end of the command line ๐.
When an unrecognized warning option is requested (e.g., -Wunknown-warning), GCC gives an error saying the option isn't recognized ๐
โโ๏ธ. The -Wno- form behaves a little differently, though: no diagnostic is produced for -Wno-unknown-warning unless other diagnostics are being produced ๐คทโโ๏ธ. This lets you use new -Wno- options with old compilers. But if something goes wrong, 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 may not be issued at all unless optimization is enabled ๐ด. While optimization in general improves the efficacy of warnings about control and data-flow problems, in some cases it may also cause false positives ๐.
-Wpedantic, -pedantic
Issues all the warnings demanded by strict ISO C and ISO C++. It diagnoses all programs that use forbidden extensions, and some other programs that don't follow ISO C and ISO C++ ๐. This follows the version of the ISO C or C++ standard specified by any -std option used ๐.
Valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few require -ansi or a -std option specifying the version of the standard) โ
. Without this option, though, 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 warning messages for use of the alternate keywords whose names begin and end with __. This alternate format can also be used to 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 they can be disabled separately by their specific option, e.g. -Wpedantic -Wno-pointer-sign ๐.
Where the standard named by -std is a GNU extended dialect like gnu90 or gnu99, there's a matching base standard, which is the version of ISO C that the GNU dialect is built on, bestie ๐. Warnings from -Wpedantic show up wherever the base standard requires them. It wouldn't make sense for them to only cover features outside the GNU dialect you picked, because by definition the GNU dialects already include everything the compiler supports with that option, so there'd be nothing left to warn about ๐
-pedantic-errors
Okay so this one is giving strict ๐
. It makes an error out of anything the base standard requires a diagnostic for, including some cases with undefined behavior at compile time and some cases that don't stop a program that's valid under the standard from compiling. Don't mix this up with -Werror=pedantic, though. That one is basically useless in comparison, because it only upgrades the diagnostics controlled by -Wpedantic. -pedantic-errors also hits required diagnostics that are always on or controlled by other options ๐ญ
If you want the required diagnostics that are warnings by default to become errors, but you don't want the -Wpedantic diagnostics turned on, you can use -pedantic-errors -Wno-pedantic. Or, if you want them enabled but only as warnings, go with -pedantic-errors -Wno-error=pedantic โจ
Some required diagnostics are errors by default, but you can knock them down to warnings with -fpermissive or with their own specific warning option, like -Wno-error=narrowing. ๐ฆ
Some diagnostics for non-ISO practices are controlled by their own warning options instead of -Wpedantic, but -pedantic-errors turns those into errors too. For example:
-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
This one is the chill option ๐ธ It downgrades some required diagnostics about nonconformant code from errors to warnings, so some nonconforming code can still compile. A few C++ diagnostics are controlled only by this flag. It also downgrades some C and C++ diagnostics that have their own flag:
-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)
-fpermissive is the default for the historic C language modes: -std=c89, -std=gnu89, -std=c90, and -std=gnu90 ๐ฐ๏ธ
-Wall
This turns on all the warnings about constructions that some folks find questionable and that are easy to avoid (or tweak so the warning goes away), even when macros are involved. It also turns on some language-specific warnings described in the C++ Dialect Options and Objective-C and Objective-C++ Dialect Options sections ๐
-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
Heads up ๐ some warning flags are not implied by -Wall. Some of them flag constructions users don't usually see as questionable but that you might want to check for now and then. Others flag constructions that are necessary or hard to avoid in some cases, with no simple code change to silence them. Some of those are enabled by -Wextra, but a lot of them have to be turned on one by one ๐ง
-Wextra
This turns on some extra warning flags that -Wall doesn't. (This option used to be called -W. The older name still works, but -Wextra is more descriptive, so use that one โจ)
-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)-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-Wunused-parameter(only with-Wunusedor-Wall)-Wunused-but-set-parameter(only with-Wunusedor-Wall)
-Wextra also prints warnings for these cases too ๐ซถ
- A pointer gets compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both show up 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 isn't initialized in the copy constructor of a derived class.
-Wabi (C, Objective-C, C++ and Objective-C++ only)
This warns about code affected by ABI changes ๐ฅ That includes code that might not be compatible with the vendor-neutral C++ ABI, plus the psABI for the particular target. The psABI warnings are also controlled separately by -Wpsabi, which -Wabi implies.
Since G++ now defaults to updating the ABI with each major release, -Wabi normally only warns about C++ ABI compatibility problems when a check was added later in a release series for an ABI issue found after the initial release. -Wabi warns about more things if an older ABI version is selected with -fabi-version=n ๐
You can also give -Wabi an explicit version number to check C++ ABI compatibility against a particular -fabi-version level. For example, -Wabi=2 warns about changes relative to -fabi-version=2.
If you give an explicit version number and -fabi-compat-version isn't specified, the version number from this option is used for compatibility aliases. If you don't give a version number with this option but do specify -fabi-compat-version, that version number is used for C++ ABI warnings instead.
An effort has been made to warn about all of these cases, but there are probably some that go unwarned even though G++ is generating incompatible code. There may also be cases where warnings get emitted even though the generated code is actually compatible ๐
If you're worried that code generated by G++ might not be binary compatible with code from other compilers, 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 got 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 didn't allow overloading of functions taking vectors of different sizes.
The mangling changed in -fabi-version=4.
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration got folded away.
These mangling issues were fixed in -fabi-version=5.
Okay so the ABI saga keeps going, bestie ๐
- Scoped enumerators passed to a variadic function get promoted like unscoped ones, which makes
va_argthrow a fit ๐ On most targets this doesn't actually change the parameter passing ABI, because there's no way to pass anything smaller thanint. โจ Also, the ABI mangling changed for template argument packs,const_cast,static_cast, prefix increment/decrement, and a class scope function used as a template argument. Those got fixed in-fabi-version=6๐ - Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t๐ญ Both got fixed in-fabi-version=7๐ซถ - When mangling a function type with function-cv-qualifiers, the un-qualified function type was wrongly treated as a substitution candidate ๐ That got fixed in
-fabi-version=8, which is the default for GCC 5.1 ๐ decltype(nullptr)had an alignment of 1, so you could get unaligned accesses, yikes ๐ Tea: this didn't affect the ABI of a function with anullptr_tparameter, because parameters have a minimum alignment. It got fixed in-fabi-version=9, the default for GCC 5.2 ๐ธ- Target-specific attributes that change a type's identity, like ia32 calling conventions on a function type (
stdcall,regparm, etc.), didn't affect the mangled name ๐ญ That led to name collisions whenever function pointers were used as template arguments. It got fixed in-fabi-version=10, the default for GCC 6.1 ๐ -Wpsabi(C, Objective-C, C++ and Objective-C++ only) โ this one is all about processor-specific ABI changes, like shifts in alignment requirements or how function arguments get passed ๐ฆ On a bunch of targets, including AArch64, ARM, x86, MIPS, RS6000/PowerPC, and S/390, these details changed between GCC versions and/or C or C++ standard versions, and that can mess with binary compatibility. With-Wpsabi, GCC can sniff out potentially incompatible usages and warn you โจ It's enabled by default, and-Wabiimplies it too.-Wno-changes-meaning(C++ and Objective-C++ only) โ okay, C++ wants unqualified uses of a name inside a class to mean the same thing across the whole class scope, so declaring the name after you've already used 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 both declarations have the same type. The B2 case is an error ๐ You can turn off both diagnostics with -Wno-changes-meaning. If you want the error case downgraded to a warning instead, use -Wno-error=changes-meaning or -fpermissive. Both diagnostics also get suppressed by -fms-extensions ๐
-Wchar-subscriptsโ warns if an array subscript has typechar. This is a super common bug, because people forget thatcharis signed on some machines ๐ Enabled by-Wall.-Wno-coverage-mismatchโ warns if feedback profiles don't match when you use-fprofile-use. If the source file changes between compiling with-fprofile-generateand-fprofile-use, the profile feedback files can fail to match, and GCC can't use that feedback info ๐ญ By default this warning is on and treated as an error. You can use-Wno-coverage-mismatchto silence the warning, or-Wno-error=coverage-mismatchto silence the error. Skipping the error can leave you with poorly optimized code, so it's only really useful for very minor stuff like bug fixes in an existing codebase. Completely disabling the warning is not recommended ๐ซถ-Wno-coverage-too-many-conditionsโ warns if-fcondition-coverageis used and an expression has too many terms, so GCC gives up on coverage. Coverage gets abandoned when the conditional has more terms than there are bits in agcov_type_unsigned. This warning is enabled by default โจ-Wno-coverage-too-many-pathsโ warns if-fpath-coverageis used and a function has too many paths, so GCC gives up. Giving up is controlled by-fpath-coverage-limit. This warning is enabled by default ๐-Wno-coverage-invalid-line-numberโ warns in case a function ends earlier than it begins because of invalidlinenummacros ๐ The warning only shows up with--coverageenabled. By default it's on and treated as an error.-Wno-coverage-invalid-line-numberdisables the warning, and-Wno-error=coverage-invalid-line-numberdisables the error.-Wno-cpp(C, Objective-C, C++, Objective-C++ and Fortran only) โ suppresses the warning messages that#warningdirectives emit ๐ธ-Wdouble-promotion(C, C++, Objective-C and Objective-C++ only) โ gives a warning when afloatvalue gets implicitly promoted todouble๐ CPUs with a 32-bit single-precision floating-point unit implementfloatin hardware but emulatedoublein software. On a machine like that, doing math withdoubleis way more expensive because of the software emulation overhead ๐ญ
It's super easy to accidentally do double math, because floating-point literals are implicitly double. For example:
float area(float radius)
{
return 3.14159 * radius * radius;
}
The compiler does the entire computation in double, because the floating-point literal is a double ๐
-Wduplicate-decl-specifier(C and Objective-C only) โ warns if a declaration has a duplicateconst,volatile,restrictor_Atomicspecifier. Enabled by-Wall๐-Wformat,-Wformat=nโ this is the big format-string checker ๐ฅ It checks calls toprintf,scanf, etc., to make sure the arguments have types that match the format string, and that the conversions in the format string actually make sense โจ That covers standard functions, plus any others specified by format attributes, in theprintf,scanf,strftimeandstrfmonfamilies (strfmonis an X/Open extension, not in the C standard), or other target-specific families. Which functions get checked without format attributes depends on the standard version you picked, and those checks are turned off by-ffreestandingor-fno-builtin.
The formats get checked against the format features supported by GNU libc version 2.2. That includes all ISO C90 and C99 features, plus features from the Single Unix Specification and some BSD and GNU extensions ๐ฆ Other library implementations might not support all of these, and GCC doesn't warn about features that go beyond a particular library's limits. Still, if you use -Wpedantic with -Wformat, you'll get warnings about format features that aren't in the selected standard version (but not for strfmon formats, since those aren't in any version of the C standard).
-Wformat=1,-Wformatโ-Wformatis the same as-Wformat=1, and-Wno-formatis the same as-Wformat=0๐ Since-Wformatalso checks for null format arguments in several functions, it implies-Wnonnulltoo. A few parts of this level can be turned off with-Wno-format-contains-nul,-Wno-format-extra-args, and-Wno-format-zero-length.-Wformatis enabled by-Wall.-Wformat=2โ turns on-Wformatplus extra format checks ๐ Right now that's equivalent to-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k.
-Wno-format-contains-nulโ if-Wformatis specified, this stops GCC from warning about format strings that contain NUL bytes ๐ธ-Wno-format-extra-argsโ if-Wformatis specified, this stops GCC from warning about excess arguments to aprintforscanfformat function. The C standard says those extra args get ignored ๐ If the unused arguments sit between used arguments that use$operand number specifications, GCC still warns by default, because it can't know what type to hand tova_argto skip the unused ones. But forscanfformats, this option suppresses the warning when the unused arguments are all pointers, since the Single Unix Specification says those are allowed ๐ง-Wformat-overflow,-Wformat-overflow=levelโ warns about calls to formatted output functions likesprintfandvsprintfthat might overflow the destination buffer ๐ญ When the exact number of bytes written by a format directive can't be figured out at compile time, GCC estimates it using heuristics that depend on thelevelargument and on optimization. Turning on optimization usually makes the warning more accurate, but it can also cause false positives ๐-Wformat-overflow,-Wformat-overflow=1โ level 1 is enabled by-Wformatand takes a conservative approach, only warning about calls that 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 either by their directive's precision or by a finite set of string literals, are assumed to take the value in that range that produces the most bytes on output. 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 avoid the warning, though it might not be enough to avoid the overflow itself ๐
โจ OPTIONS โจ (continued)
-Wformat-overflow=2โ okay bestie, level 2 is where it gets spicy ๐ฅ. It also flags calls that might overflow the destination buffer if an argument is big enough or large enough in magnitude. At this level, unknown numeric arguments get assumed to be the minimum value for signed types with a precision greater than 1, and the maximum value for everything else. Unknown string arguments that can't be proven bounded (not by the directive's precision, not by a finite set of string literals they could be, and not by the character array they point to) get assumed to be 1 character long ๐ง
At level 2, GCC diagnoses the example above again, but this time the reason is that with a equal to a 32-bit INT_MIN, the first %i directive writes some of its digits past the end of the destination buffer ๐ญ To make the call safe no matter what the two variables hold, the buffer needs to be at least 34 bytes. GCC even includes the minimum buffer size in an informational note right after the warning ๐
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
Instead of making the buffer bigger, you can also put a leash on the values. You can bound the length of string arguments by giving the format directive a precision. If numeric arguments can be assumed to fit in less than the precision of their type, picking a suitable length modifier in the format specifier shrinks the buffer you need. So if a and b in the example above are guaranteed to fit in a short int, then using either the %hi directive or casting the argument to short brings the maximum required 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 you've got-Wformaton, this tells GCC to stop warning about zero-length formats. Totally allowed, the C standard says so ๐ธ-Wformat-nonliteralโ with-Wformaton, this also warns when the format string isn't a string literal, since GCC can't check it. The exception is when the format function takes its arguments as ava_list๐-Wformat-securityโ with-Wformaton, this one is about possible security problems ๐ Right now it warns aboutprintfandscanfcalls where the format string isn't a string literal and there are no format arguments, likeprintf (foo);. That can be a real security hole if the format string came from untrusted input and contains%n. (Fun fact: this is currently a subset of what-Wformat-nonliteralcatches, but future warnings may be added to-Wformat-securitythat aren't in-Wformat-nonliteral.) ๐-Wformat-signednessโ with-Wformaton, this warns if the format string wants an unsigned argument but you pass a signed one, and vice versa ๐-Wformat-truncation,-Wformat-truncation=levelโ this one warns about formatted output functions likesnprintfandvsnprintfthat might truncate their output โ๏ธ If GCC can't figure out the exact number of bytes a format directive writes at compile time, it guesses using heuristics that depend on the level and on optimization. Turning optimization on usually makes the warning more accurate, but it can also cause false positives. Unless noted otherwise, this option uses the same logic as-Wformat-overflow.-Wformat-truncation,-Wformat-truncation=1โ level 1 is enabled by-Wformatand is pretty chill ๐ It only warns about calls to bounded functions whose return value is unused and that will most likely truncate the output.-Wformat-truncation=2โ level 2 goes further and also warns about bounded calls whose return value is used, if they might truncate given an argument of sufficient length or magnitude ๐
-Wformat-y2kโ with-Wformaton, this warns aboutstrftimeformats that might only give you a two-digit year ๐-Wnonnullโ warns when you pass a null pointer to an argument that thenonnullfunction attribute says must be non-null ๐ซ It's 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 ๐ It's included in-Wall, and you can disable it with-Wno-nonnull-compare.-Wnull-dereferenceโ warns if the compiler finds paths that lead to erroneous or undefined behavior from dereferencing a null pointer ๐ This only works when-fdelete-null-pointer-checksis active, which optimizations turn on for most targets. How precise the warnings are depends on which optimization options you use.-Wno-musttail-local-addrโ stops warnings 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 no drama โจ-Wmaybe-musttail-local-addrโ warns when the address of a local variable can escape into amusttailcall, unless that variable already went out of scope before themusttailcall ๐ฆ
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) โ warns if GCC doesn't elide the copy from a local variable to the return value, even though [class.copy.elision] allows it ๐ค This elision is commonly called the Named Return Value Optimization. In the example below, GCC can't elide the copies from bothv1andv2, so it elides 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 ๐ It works at all optimization levels, but you need optimization on to catch infinite recursion across two or more functions. It's included in-Wall.
Compare this with -Wanalyzer-infinite-recursion, which gives a similar diagnostic but is implemented differently (as part of -fanalyzer).
-Winit-self(C, C++, Objective-C and Objective-C++ only) โ warns about uninitialized variables that get initialized with themselves ๐ Heads up: this option only works together with-Wuninitialized.
For example, GCC warns about i being uninitialized in the following snippet only when -Winit-self is specified:
int f()
{
int i = i;
return i;
}
In C++, this warning is enabled by -Wall.
-Wno-implicit-int(C and Objective-C only) โ controls warnings for declarations that don't specify a type ๐ This warning is on by default as an error in C99 and later dialects, and it's also turned on by-Wall. You can downgrade the error to a warning with-fpermissive(along with some other errors), or just for this error with-Wno-error=implicit-int.
-pedantic-errors upgrades this warning to an error.
-Wno-implicit-function-declaration(C and Objective-C only) โ controls warnings for functions that get used before they're declared ๐ฃ Likeimplicit-int, this is on by default as an error in C99 and later, and-Wallturns it on too. You can downgrade it with-fpermissive(along with certain other errors), or for this error alone with-Wno-error=implicit-function-declaration.
-pedantic-errors upgrades this warning to an error.
-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intplus-Wimplicit-function-declaration๐ It's enabled by-Wall.-Whardenedโ warns when-fhardeneddidn't enable an option from its set (see-fhardenedfor the full list) ๐ก๏ธ For example, if you use-fhardenedand-fstack-protectortogether on the command line,-Whardenedwill warn, because-fstack-protector-strongwon't be enabled by-fhardened.
This warning is on by default, but it only has an effect when -fhardened is enabled.
-Wimplicit-fallthroughโ this is the same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0๐ท-Wimplicit-fallthrough=nโ warns when aswitchcase falls through into the next one without a break. Here's an example:
โจ OPTIONS โจ (continued, bestie) ๐
okay so the -Wimplicit-fallthrough warning is lowkey the best one for catching sneaky bugs ๐
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
This warning does not warn when the last statement of a case cannot fall through, e.g. when there is a return statement or a call to function declared with the noreturn attribute. It's giving "I know what I'm doing" energy ๐
-Wimplicit-fallthrough= also takes into account control flow statements, such as ifs, and only warns when appropriate. E.g.
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Since there are occasions where a switch case fall through is desirable, GCC provides an attribute, __attribute__ ((fallthrough)), that is to be used along with a null statement to suppress this warning that would normally occur ๐ซถ
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 gives you a standard way to suppress the -Wimplicit-fallthrough warning 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, it is also possible to add a fallthrough comment to silence the warning ๐. The whole body of the C or C++ style comment should match the given regular expressions listed below. The option argument n specifies what kind of comments are accepted:
-Wimplicit-fallthrough=0disables the warning altogether.-Wimplicit-fallthrough=1matches".*"regular expression, any comment is used as 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, only attributes disable the warning.
The comment needs to be followed after optional whitespace and other comments by case or default keywords or by a user label that precedes 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) โ okay so this one controls whether warnings triggered by thewarn_if_not_alignedattribute get issued. These warnings are enabled by default ๐ฆ-Wignored-qualifiers(C and C++ only) โ warns if the return type of a function has a type qualifier such asconst. For ISO C such a type qualifier has no effect, since the value returned by a function is not an lvalue. For C++, the warning is only emitted for scalar types orvoid. ISO C prohibits qualifiedvoidreturn types on function definitions, so such return types always receive 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. This is different from the-Wattributesoption in that it warns whenever the compiler decides to drop an attribute, not that the attribute is either unknown, used in a wrong place, etc. This warning is enabled by default ๐-Wmainโ warns if the type ofmainis suspicious.mainshould be a function with external linkage, returningint, taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++ and is enabled by either-Wallor-Wpedantic. This warning is upgraded to an error by-pedantic-errors๐-Wmisleading-indentation(C and C++ only) โ warns when the indentation of the code does not reflect the block structure. Specifically, a warning is issued forif,else,while, andforclauses with a guarded statement that does not use braces, followed by an unguarded statement with the same indentation. In the following example, the call tobaris misleadingly indented as if it were guarded by theifconditional ๐
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
In the case of mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up (defaulting 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);
The warning is not issued after a #line directive, since this typically indicates autogenerated code, and no assumptions can be made about the layout of the file that the directive references. This warning is enabled by -Wall in C and C++ โจ
-Wmissing-attributesโ warns when a declaration of a function is missing one or more attributes that a related function is declared with and whose absence may adversely affect the correctness or efficiency of generated code. For example, the warning is issued for declarations of aliases that use attributes to specify less restrictive requirements than those of their targets. This typically represents a potential optimization opportunity. By contrast, the-Wattribute-alias=2option controls warnings issued when the alias is more restrictive than the target, which could lead to incorrect code generation. Attributes considered includealloc_align,alloc_size,cold,const,hot,leaf,malloc,nonnull,noreturn,nothrow,pure,returns_nonnull, andreturns_twice. In C++, the warning is issued when an explicit specialization of a primary template declared with attributealloc_align,alloc_size,assume_aligned,format,format_arg,malloc, ornonnullis declared without it. Attributesdeprecated,error, andwarningsuppress the warning.. You can use thecopyattribute to apply the same set of attributes to a declaration as that on another declaration without explicitly enumerating the attributes. This attribute can be applied to declarations of functions, variables, or types.-Wmissing-attributesis enabled by-Wall๐ฆ
For example, since the declaration of the primary function template below makes use of both attribute malloc and alloc_size the declaration of the explicit specialization of the template is diagnosed because it is missing one of the attributes ๐
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 if an aggregate or union initializer is not fully bracketed. In the following example, the initializer forais not fully bracketed, but that forbis fully bracketed. This warning is enabled by-Wall๐
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
-Wmissing-include-dirs(C, C++, Objective-C, Objective-C++ and Fortran only) โ warns if a user-supplied include directory does not exist. This option is disabled by default for C, C++, Objective-C and Objective-C++. For Fortran, it is partially enabled by default by warning for-Iand-J, only. ๐ธ-Wno-missing-profileโ this option controls warnings if feedback profiles are missing when using the-fprofile-useoption. This option diagnoses those cases where a new function or a new file is added between compiling with-fprofile-generateand with-fprofile-use, without regenerating the profiles. In these cases, the profile feedback data files do not contain any profile feedback information for the newly added function or file respectively. Also, in the case when profile count data (.gcda) files are removed, GCC cannot use any profile feedback information. In all these cases, warnings are issued to inform you that a profile generation step is due. Ignoring the warning can result in poorly optimized code.-Wno-missing-profilecan be used to disable the warning, but this is not recommended and should be done only when non-existent profile data is justified. > ๐ญ Ignoring this one can give you poorly optimized code, so don't just silence it because it's annoying!-Wmismatched-deallocโ warns for calls to deallocation functions with pointer arguments returned from allocation functions for which the former isn't a suitable deallocator. A pair of functions can be associated as matching allocators and deallocators by use of attributemalloc. Unless disabled by the-fno-builtinoption the standard functionscalloc,malloc,realloc, andfree, as well as the corresponding forms of C++operator newandoperator deleteare implicitly associated as matching allocators and deallocators. In the following examplemydeallocis the deallocator for pointers returned frommyalloc๐ง
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
}
okay so in C++, the related option -Wmismatched-new-delete catches mismatches involving either "operator new" or "operator delete" ๐ฅ
Option -Wmismatched-dealloc is included in -Wall โจ
-Wmultistatement-macros๐ โ Warns about unsafe multi-statement macros that look like they're guarded by an "if", "else", "for", "switch", or "while" clause, but where only the first statement is actually guarded once the macro expands. ๐
For example:
#define DOIT x++; y++
if (c)
DOIT;
will increment "y" unconditionally, not just when "c" holds. The 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 are left out in certain spots, like an assignment where a truth value is expected, or nested operators whose precedence people constantly mix up ๐
It also warns if you write a comparison like "x<=y<=z". That's equivalent to "(x<=y ? 1 : 0) <= z", which is NOT what regular math notation means, so it's a total trap ๐ญ
It also warns about dangerous uses of the GNU extension to "?:" with an omitted middle operand. 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 ๐
For C++, this also warns about some cases of unnecessary parentheses in declarations, which can mean you meant 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 one warns when a value gets moved to itself with "std::move". That kind of "std::move" usually does absolutely nothing, so it's giving pointless โจ
struct T {
...
};
void fn()
{
T t;
...
t = std::move (t);
}
This warning is enabled by -Wall.
-Wsequence-point๐ง โ Warns about code that may have undefined semantics because it breaks the sequence point rules in the C and C++ standards. Lowkey the most chaotic one on this list ๐ญ
The C and C++ standards define the order that expressions get evaluated in, using sequence points. Think of them as a partial ordering between parts of the program: the stuff that runs before the sequence point, and the stuff that runs after it. They show up after a full expression is evaluated (one that isn't part of a bigger expression), after the first operand of a "&&", "||", "? :" or "," (comma) operator is evaluated, before a function gets called (but after its arguments and the expression naming the called function are evaluated), and in a few other places. Apart from what the sequence point rules say, the order of evaluating subexpressions is not specified. These rules only give a partial order, not a total one. For example, if two functions get called inside one expression with no sequence point between them, the order they run in is not specified. Still, the standards committee has ruled that function calls do not overlap.
It's not specified when, between sequence points, changes to object values take effect. Programs whose behavior depends on this 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, the results on any particular implementation are totally unpredictable ๐
Examples of code with undefined behavior are a = a++;, a[n] = b[n++] and a[i++] = i;. Some more complicated cases aren't caught by this option, and it may give the occasional false positive. But overall it's been found pretty effective at catching this sort of problem ๐
The C++17 standard will define the order of evaluation for operands in more cases. In particular, it requires that the right-hand side of an assignment gets evaluated before the left-hand side, so the examples above are no longer undefined. But this option will still warn about them, to help people avoid writing code that's undefined in C and in 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.-Wreturn-mismatch๐ โ Warns aboutreturnstatements with no expression in functions that don't return "void". It also warns about a "return" statement with an expression in a function whose return type is "void", unless the expression's type is also "void". As a GNU extension, that second case is accepted without a warning unless-Wpedanticis used.
Trying to use the return value of a non-"void" function other than "main" that flows off the end by reaching the closing curly brace is undefined. Yikes ๐ญ
This warning is specific to C and enabled by default. In C99 and later language dialects, it's treated as an error. You can downgrade it to a warning with -fpermissive (along with other warnings), or for just this warning, with -Wno-error=return-mismatch.
-Wreturn-type๐ โ Warns whenever a function is defined with a return type that defaults to "int" (unless-Wimplicit-intis active, which takes precedence). It also warns if execution may reach the end of the function body, or if the function doesn't contain any return statement at all.
Again, trying to use the return value of a non-"void" function other than "main" that flows off the end by reaching the closing curly brace is undefined.
Unlike C, in C++, flowing off the end of a non-"void" function other than "main" results in undefined behavior even when the function's value isn't used. Not it ๐
This warning is enabled by default in C++ and by -Wall otherwise.
-Wno-shift-count-negativeโจ โ Controls warnings if a shift count is negative. This warning is enabled by default.-Wno-shift-count-overflow๐ โ Controls warnings if a shift count is greater than or equal to the bit width of the type. This warning is enabled by default.-Wshift-negative-value๐ฅ โ Warns if you left-shift a negative value. This warning is enabled by-Wextrain C99 (and newer) and in 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 warning level of-Wshift-overflowand it's enabled by default in C99 and C++11 modes (and newer). This level doesn't warn about left-shifting 1 into the sign bit. (However, in C, such an overflow is still rejected in contexts where an integer constant expression is required.) No warning is emitted in C++20 mode (and newer), since signed left shifts always wrap now ๐ง-Wshift-overflow=2๐ โ This level also warns about left-shifting 1 into the sign bit, unless C++14 mode (or newer) is active.
-Wswitch๐ โ Warns whenever a "switch" statement has an index of enumerated type and is missing a "case" for one or more of the named codes of that enumeration. (A "default" label stops this warning from happening.) "case" labels that don't match any enumerator also trigger warnings when this option is used, unless the enumeration is marked with the "flag_enum" attribute. This warning is enabled by-Wall.-Wswitch-default๐ซถ โ Warns whenever a "switch" statement doesn't have a "default" case.-Wswitch-enum๐ โ Warns whenever a "switch" statement has an index of enumerated type and is missing a "case" for one or more of the named codes of that enumeration. "case" labels that don't correspond to enumerators also trigger warnings when this option is used, unless the enumeration is marked with the "flag_enum" attribute. The only difference between-Wswitchand this option is that this one warns about an omitted enumeration code even if there's a "default" label. Very thorough, very iconic โจ-Wno-switch-bool๐ โ Don't warn when a "switch" statement has an index of boolean type and the case values are outside the range of a boolean type. You can suppress this warning by casting the controlling expression to a type other than "bool". For example:
switch ((int) (a == 4))
{
...
}
This warning is enabled by default for C and C++ programs.
-Wno-switch-outside-range๐ โ This option controls warnings when a "switch" case has a value that's outside of its respective type range. This warning is enabled by default for C and C++ programs.-Wno-switch-unreachable๐ โ Don't warn when a "switch" statement contains statements between the controlling expression and the first case label, since those will never be executed. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
The -Wswitch-unreachable vibe check: it does not warn if the only thing sitting between the controlling expression and the first case label is a plain declaration. Like this ๐
switch (cond)
{
int i;
...
case 5:
i = 5;
...
}
This one is enabled by default for C and C++ programs โจ
-Wsync-nand(C and C++ only) ๐ธ โ okay so this one yells when you use the__sync_fetch_and_nandand__sync_nand_and_fetchbuilt-ins. Those two changed their semantics in GCC 4.4, so it's giving "heads up, bestie" ๐ซถ-Wtrivial-auto-var-init๐ฆ โ warns when-ftrivial-auto-var-initcan't initialize an automatic variable. The most common way this happens is when an automatic variable is declared between the controlling expression and the firstcaselabel of aswitchstatement. Not it ๐-Wunused-but-set-parameter๐ โ warns whenever a function parameter gets assigned to but is otherwise unused, aside from its declaration. To shut this up, use theunusedattribute. It's also turned on by-Wunusedtogether with-Wextra๐ง-Wunused-but-set-variable๐ โ same energy, but for local variables: warns whenever one gets assigned to and then never used (aside from its declaration). It's enabled by-Wallโจ To suppress it, use theunusedattribute. It's also enabled by-Wunused, which-Wallturns on ๐-Wunused-function๐ โ warns whenever a static function is declared but not defined, or when a non-inline static function is unused. Enabled by-Wall๐-Wunused-label๐ โ warns whenever a label is declared but never used. Enabled by-Wall. Silence it with theunusedattribute ๐-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โญ โ warns when a typedef defined locally inside a function never gets used. Enabled by-Wallโจ-Wunused-parameter๐ซถ โ warns whenever a function parameter is unused, aside from its declaration. This one is not turned on by-Wunusedunless you also specify-Wextra. To suppress it, use theunusedattribute ๐ฅ-Wno-unused-result๐ง โ don't warn if a caller of a function marked with the attributewarn_unused_resultignores its return value. The default is-Wunused-result๐-Wunused-variable๐ โ warns whenever a local or static variable 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 constant static variable is unused, aside from its declaration. Silence it with theunusedattribute ๐ฆ-Wunused-const-variable=1๐ โ warns about unused static const variables defined in the main compilation unit, but not about static const variables declared in any header that gets included. This level is enabled by either-Wunused-variableor-Wunusedfor C, but not for C++. In C this declares variable storage, but in C++ it's not an error, since const variables take the place of#defines ๐ซถ-Wunused-const-variable=2๐ฅ โ this level also warns about unused constant static variables in headers (excluding system headers). It's equivalent to the short form-Wunused-const-variable. You have to request this level explicitly in both C and C++, because it might be hard to clean up all the headers you've included ๐
-Wunused-value๐ โ warns whenever a statement computes a result that is explicitly not used. To suppress it, cast the unused expression tovoid. This covers an expression-statement or the left-hand side of a comma expression that has no side effects. For example,x[i,j]causes a warning, whilex[(void)i,j]does not. Enabled by-Wall๐-Wunused๐ โ all of the above-Wunusedoptions combined, except the ones documented as needing 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.-Wunusedenables only-Wunused-const-variable=1rather than-Wunused-const-variable, and only for C, not C++ โจ-Wuse-after-free(C, Objective-C, C++ and Objective-C++ only),-Wuse-after-free=nโญ โ warns about uses of pointers to dynamically allocated objects that were made indeterminate by a call to a deallocation function. This warning is enabled at all optimization levels, but it may give different results 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 by a successful call torealloc, no matter whether that call actually reallocated memory. This includes double-freecalls as well as uses in arithmetic and relational expressions. Uses of indeterminate pointers in equality (or inequality) expressions are undefined, but they are not diagnosed at this level ๐-Wuse-after-free=2๐ โ at level 2, on top of unconditional uses, the warning also diagnoses conditional uses of pointers made indeterminate by a deallocation call. As at level 2, uses in equality (or inequality) expressions are not diagnosed. For example, the second call tofreein the following function gets diagnosed 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. All uses of indeterminate pointers are undefined, but equality tests sometimes show up after calls toreallocas an attempt to figure out whether the call moved the object to a different address. These get diagnosed at their own separate level to help gradually move legacy code over to safe alternatives. For example, the equality test in the function below is diagnosed 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 approach means 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. This warning does not occur when a class object is converted to a non-reference type, because that's a way to create a temporary. Like this:
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 a non-staticconstmember shows up in a class without constructors ๐
Also, passing a pointer (or, in C++, a reference) to an uninitialized object to a const-qualified argument of a built-in function known to read that object is diagnosed by this warning too. (-Wmaybe-uninitialized is issued for ordinary functions.) ๐ซถ
If you want to warn about code that uses the uninitialized value of a variable in its own initializer, use the -Winit-self option โจ
These warnings show up for individual uninitialized elements of structure, union or array variables, as well as for variables that are uninitialized as a whole. They do not occur for variables or elements declared volatile. Because these warnings depend on optimization, the exact variables or elements that get warned about depend on the precise optimization options and the GCC version you're using ๐ฅ
Also, 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 can delete those computations before the warnings get printed ๐
In C++, this warning also catches using uninitialized objects in member-initializer-lists. For example, GCC warns about b being uninitialized in the following snippet:
struct A {
int a;
int b;
A() : a(b) { }
};
-Wno-invalid-memory-model๐ฆ โ this option controls warnings for invocations of__atomicbuilt-ins,__syncbuilt-ins, and the C11 atomic generic functions whose memory consistency argument is either invalid for the operation or outside the range of values of thememory_orderenumeration. For example, since__atomic_storeand__atomic_store_nare only defined for the relaxed, release, and sequentially consistent memory orders, the following code gets diagnosed:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
-Winvalid-memory-model is 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 is initialized, but there are other paths where it isn't, the compiler emits a warning if it can't prove those uninitialized paths never run at runtime. It's giving "maybe, but I'm not sure" ๐ง
Okay so the uninitialized warning has a sneaky extra trick, bestie ๐
. Passing a pointer (or in C++, a reference) to an uninitialized object into a const-qualified function argument also gets flagged by this warning ๐. (-Wuninitialized fires for built-in functions that are known to read the object ๐ซถ.) If you slap the attribute access (none) on the function, you're telling GCC the argument never touches the object, and the warning goes poof โจ.
These warnings only show up when you're compiling with optimization on ๐ฅ, because otherwise GCC doesn't keep track of what's happening to your variables. It's giving "no tracking, no vibes" ๐.
These warnings are optional, and that's on purpose ๐ฆ. GCC can't always tell when your code is correct even though it looks sus. Here's a classic example ๐
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If y is always 1, 2 or 3, then x is always initialized ๐ฅน, but GCC doesn't know that. To shut the warning up, add a default case with assert(0) or similar code ๐.
This option also warns when a non-volatile automatic variable might get changed by a call to longjmp ๐ญ. The compiler only sees the setjmp calls, and it has no idea where longjmp will be called. A signal handler could even call it at any point in the code ๐. So you might get a warning even when there's no real problem, because longjmp can't actually be called in the spot that would cause trouble โจ.
Some spurious warnings can be avoided if you declare every function you use that never returns as noreturn ๐ง.
This warning is enabled by -Wall or -Wextra ๐.
-Wunknown-pragmasโ Warns when a#pragmadirective shows up that GCC doesn't understand ๐. If you use this command-line option, you'll even get warnings for unknown pragmas in system header files ๐ซฃ. That's not the case if the warnings are only turned on by-Wall๐ .-Wno-pragmasโ Silences warnings about pragma misuse, like wrong parameters, invalid syntax, or pragmas clashing with each other ๐. See also-Wunknown-pragmas๐ฆ.-Wno-pragma-once-outside-headerโ Stops the warning when#pragma onceis used in a file that isn't a header, like your main file ๐ธ.-Wno-prio-ctor-dtorโ Stops the warning when a priority from 0 to 100 is used for a constructor or destructor ๐. The constructor and destructor attributes let you give a priority to control when they run, either beforemainis called or after it returns โญ. Just know the priority values have to be greater than 100, since GCC keeps 0--100 reserved for its own implementation ๐.-Wstrict-aliasingโ This one only works when-fstrict-aliasingis active ๐ฅ. It warns about code that might break the strict aliasing rules GCC uses for optimization ๐. It doesn't catch every case, but it does try to catch the more common pitfalls ๐ซถ. It's included in-Wallโจ. It's equivalent to-Wstrict-aliasing=3๐.-Wstrict-aliasing=nโ Also only active when-fstrict-aliasingis active ๐. It warns about the same kind of code, but higher levels mean higher accuracy (fewer false positives) ๐. Higher levels also take more effort, kind of like how-Oworks ๐ง.-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3๐ .- Level 1 โ The most aggressive, quick, and least accurate ๐ญ. It's possibly useful when the higher levels don't warn but
-fstrict-aliasingstill breaks your code, since it has very few false negatives ๐. The downside is it has many false positives ๐. It warns for all pointer conversions between possibly incompatible types, even if the pointer is never dereferenced ๐. It only runs in the front end ๐. - Level 2 โ Aggressive and quick, but not super precise โจ. It may still have lots of false positives (though not as many as level 1) and few false negatives (possibly more than level 1) ๐ฆ. Unlike level 1, it only warns when an address is taken ๐ธ. It warns about incomplete types ๐. It runs in the front end only ๐.
- Level 3 (the default for
-Wstrict-aliasing) โ This one should have very few false positives and 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 multi-statement cases using flow-sensitive points-to information ๐ง . It only warns when the converted pointer is dereferenced ๐ฅ. It does not warn about incomplete types ๐ .
- Level 1 โ The most aggressive, quick, and least accurate ๐ญ. It's possibly useful when the higher levels don't warn but
-Wstrict-overflow,-Wstrict-overflow=nโ This only works when signed overflow is undefined ๐. It warns about cases where the compiler optimizes based on the assumption that signed overflow never happens โจ. Heads up: it doesn't warn about every spot where your code might overflow ๐. It only warns where the compiler actually applies some optimization, so this warning depends on your optimization level ๐ . An optimization that assumes no signed overflow is totally safe if the values involved never actually overflow ๐ฅน. That means this warning can easily give a false positive, aka 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 get issued for undefined signed overflow when GCC is estimating how many iterations a loop needs, especially when figuring out whether a loop runs at all ๐.-Wstrict-overflow=1โ Warns about cases that are both questionable and easy to avoid ๐ฆ. For example, the compiler simplifiesx + 1 > xto1๐ซฃ. This level is enabled by-Wall; higher levels aren't, so you have to ask for them explicitly ๐ .-Wstrict-overflow=2โ Also 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, becauseabs (INT_MIN)overflows toINT_MIN, which is less than zero ๐ฑ.-Wstrict-overflowwith no level is the same as-Wstrict-overflow=2๐.-Wstrict-overflow=3โ Also warns about other comparisons that get simplified ๐ง. For example:x + 1 > 1is simplified tox > 0๐.-Wstrict-overflow=4โ Also warns about other simplifications not covered by the cases above ๐ธ. For example:(x * 10) / 5is simplified tox * 2โจ.-Wstrict-overflow=5โ Also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison ๐ญ. For example:x + 2 > yis simplified tox + 1 >= y๐. This is only reported at the highest warning level, because this simplification applies to so many comparisons that this level gives a very large number of false positives ๐.
-Wstring-compareโ Warns for calls tostrcmpandstrncmpwhose result is determined to be always zero or always non-zero in equality tests ๐. That happens because one argument is longer than the array the other argument is stored in (or the bound, forstrncmp) ๐ซฃ. These calls could be mistakes ๐. In the example below, thestrcmpcall gets diagnosed because its result is necessarily non-zero no matter what's in the arraya๐ .
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โ Warns about code that can be statically determined to cause buffer overflows or memory overruns ๐จ, likememcpyandstrcpycalls 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 ๐งฎ. The argument only matters for string functions that work on character arrays ๐ค. Raw memory functions likememcpyalways use type-zero Object Size Checking ๐ง . This option also warns for calls that specify a size bigger than the largest possible object, or at mostSIZE_MAX / 2bytes ๐. It gives the best results with optimization enabled ๐ฅ. Even without optimization, it can detect a small subset of simple buffer overflows in calls to GCC built-in functions like__builtin_memcpythat 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, which can do run-time checking when the access can't be proven safe at compile time ๐ต๏ธโโ๏ธ. For example, this option issues a warning for thestrcpycall below, because it copies at least 5 characters (the string"blue"including the terminating NUL) into a buffer of size 4 ๐ญ.
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
}
The effect of this option isn't limited to string or memory functions ๐. In this example, a warning is diagnosed because a 1-element array is 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
}
Option -Wstringop-overflow=2 is enabled by default ๐.
-Wstringop-overflow,-Wstringop-overflow=1โ okay so this one uses type-zero Object Size Checking ๐ to figure out how big destination objects are. At this setting it doesn't warn about writes past the end of a subobject inside a bigger object reached through a pointer, unless the size of the biggest surrounding object is known. If the destination could be one of several objects, it assumes the biggest one ๐ . On Linux, with optimization turned on at this level, it warns for the same code that trips up when the_FORTIFY_SOURCEmacro is defined to a non-zero value โจ-Wstringop-overflow=2โ this one switches to type-one Object Size Checking ๐ฆ and warns about overflows when writing to members of the largest complete objects whose exact size is known. It won't flag excessive writes to the same members of unknown objects reached through pointers, since those might point at arrays with an unknown number of elements ๐คทโโ๏ธ This is the default setting of the option ๐-Wstringop-overflow=3โ type-two Object Size Checking is in charge here ๐ It warns about overflowing the smallest object or data member. This is the most restrictive setting that may still warn about perfectly safe code ๐-Wstringop-overflow=4โ now we're on type-three Object Size Checking ๐ฅ It warns about overflowing any data members, and when the destination is one of several objects it uses the size of the largest one to decide whether to warn. Just like-Wstringop-overflow=3, this setting may warn about benign code ๐
-Wno-stringop-overreadโ warn for calls to string manipulation functions likememchrorstrcpythat are determined to read past the end of the source sequence ๐
Option -Wstringop-overread is enabled by default โ
-Wno-stringop-truncationโ no warnings for bounded string functions likestrncat,strncpy, andstpncpythat might either truncate the copied string or leave the destination unchanged ๐ธ
Okay, example time ๐ง In the snippet below, the call to strncat sets a bound that's smaller than the length of the source string. So the copy gets truncated, and that's why the call is diagnosed. To dodge the warning, use bufsize - strlen (buf) - 1) as the bound ๐
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Next up, the strncpy call here copies just the characters before the terminating NUL into d, and it doesn't append the NUL to the end. Assuming the result of strncpy is definitely a NUL-terminated string is a super common mistake, so this call gets diagnosed ๐ญ If the result isn't supposed to be NUL-terminated, call memcpy instead to avoid the warning ๐ซถ
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
In this one, the strncpy call uses the size of the destination buffer as its bound. If the source string's length is equal to or greater than that size, the copy won't be NUL-terminated, so yep, it gets diagnosed too ๐ To avoid the warning, specify sizeof buf - 1 as the bound and set the last element of the buffer to NUL ๐
void copy (const char *s)
{
char buf[80];
strncpy (buf, s, sizeof buf);
...
}
Now, if a character array is meant to hold a sequence of bytes with no terminating NUL, you can annotate that array with the nonstring attribute to avoid this warning ๐ Just know these arrays aren't suitable arguments for functions that expect NUL-terminated strings. To help catch accidental misuses of them, GCC issues warnings unless it can prove the use is safe ๐ต๏ธโโ๏ธ
-Wstrict-flex-arrays(C and C++ only) โ warns about improper usages of flexible array members, based on the level of thestrict_flex_array (level)attribute attached to the trailing array field of a structure if it's available. Otherwise it goes by the level of the option-fstrict-flex-arrays=levelโจ-Wstrict-flex-arraysonly does anything when level is greater than 0 ๐
At level=1, warnings are issued for a trailing array reference of a structure 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 extra warnings for a trailing one-element array reference of a structure if the array is referenced as a flexible array member ๐
At level=3, you get everything from level=2, plus extra warnings for a trailing zero-length array reference of a structure if the array is referenced as a flexible array member ๐ฅ
This option is more effective when -ftree-vrp is active (which is the default for -O2 and above), but some warnings may still be diagnosed even without optimization ๐ค
-Wsuggest-attribute=attribute-nameโ warns for cases where adding an attribute might be beneficial ๐ The attribute names currently supported are:-Wsuggest-attribute=pure-Wsuggest-attribute=const-Wsuggest-attribute=noreturn-Wmissing-noreturn-Wsuggest-attribute=malloc-Wsuggest-attribute=returns_nonnull
These warn about functions that might be good candidates for the pure, const, noreturn, malloc, or returns_nonnull attributes ๐ The compiler only warns for functions that are visible in other compilation units, or (for pure and const) if it can't prove that the function returns normally. A function returns normally if it doesn't contain an infinite loop and doesn't return abnormally by throwing, calling abort, or trapping ๐
This analysis requires the option -fipa-pure-const, which is enabled by default at -O and higher. Higher optimization levels improve how accurate the analysis is ๐
-Wsuggest-attribute=format,-Wmissing-format-attributeโ warns about function pointers that might be candidates forformatattributes ๐ง Just a heads up: these are only possible candidates, not absolute ones ๐ GCC guesses that function pointers withformatattributes that get used in assignment, initialization, parameter passing, or return statements should have a matchingformatattribute in the resulting type. In other words, 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 candidates for format attributes ๐ Again, these are only possible candidates. GCC guesses that format attributes might be appropriate for any function that calls a function like vprintf or vscanf, but that might not always be the case, and some functions where format attributes are appropriate may not get detected ๐ซ
-Wsuggest-attribute=coldโ warns about functions that might be candidates for thecoldattribute โ๏ธ This is based on static detection, and it generally only warns about functions that always lead to a call to anothercoldfunction, like wrappers of 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 calls to 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, including calls to the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc๐ โโ๏ธ Here's the tea: how these functions behave when called with a zero size differs between implementations (andreallochas been deprecated for this), so relying on it can cause sneaky portability bugs and should be avoided ๐ซฃ-Wcalloc-transposed-argsโ warns about calls to allocation functions decorated with thealloc_sizeattribute that take two arguments, where thesizeofoperator is used in the earlier size argument but not in the later one ๐ 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 havingsizeofin the earlier argument and not the later one is intentional, you can suppress the warning by usingcalloc (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 warnings from this option either by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-alloc-size-larger-than๐ซถ-Wno-alloc-size-larger-thanโ disables-Walloc-size-larger-than=warnings ๐ โโ๏ธ It's the same as-Walloc-size-larger-than=SIZE_MAXor larger ๐-Wallocaโ warns on all uses ofallocain the source ๐จ No exceptions, bestie ๐ค-Walloca-larger-than=byte-size๐ โ okay so this one babysits yourallocacalls. It warns whenallocagets an integer argument that's either zero, or isn't bounded by some check that caps it atbyte-sizebytes. It also yells when the bound is unknown entirely. Heads up: non-integer arguments count as unbounded, even if they look like they're in range. ๐
A bounded alloca looks like this, bestie:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
With -Walloca-larger-than=1000, you get no warning, because that alloca is known to be at most 1000 bytes. But if you pass -Walloca-larger-than=500 instead, the compiler will absolutely warn you. ๐
Unbounded uses are the chaotic ones: alloca with no controlling predicate constraining its integer argument. Like this:
void func ()
{
void *p = alloca (n);
f (p);
}
Pass -Walloca-larger-than=500 and this one gets flagged, but this time it's because there's zero bounds checking happening. ๐ญ
Even code that seems totally correct with signed integers can trigger it, so be careful:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
Here n could be negative, and then a much larger value gets implicitly cast into the alloca call. Not it. ๐
This option also warns when alloca shows up inside a loop. ๐
-Walloca-larger-than=PTRDIFF_MAX is on by default, but it's usually only really effective when -ftree-vrp is active, which is the default for -O2 and above. โจ
See also -Wvla-larger-than=byte-size. ๐ฆ
-Wno-alloca-larger-than๐ง โ switches off the-Walloca-larger-than=warnings. It's the same as passing-Walloca-larger-than=SIZE_MAXor something larger. ๐-Warith-conversionโจ โ this one is extra. It makes GCC warn about implicit conversions coming out of arithmetic operations, even when converting the operands to the same type couldn't change their values. It affects the 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-bounds,-Warray-bounds=n๐ธ โ warns about out of bounds subscripts or offsets into arrays. It's enabled by-Wall. It's way more effective when-ftree-vrpis active (the default for-O2and above), but a subset of cases still gets flagged even without optimization. ๐
By default, the trailing array of a structure gets treated as a flexible array member by -Warray-bounds or -Warray-bounds=n if it's declared as any of these: a flexible array member per the C99 standard onwards ([]), 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. ๐
You can add -fstrict-flex-arrays or -fstrict-flex-arrays=level to control how this option treats that trailing array:
- when
level<=1, nothing changes from the default behavior. ๐คทโโ๏ธ - when
level=2, you get additional warnings for out of bounds subscripts or offsets into one-element arrays. ๐ซถ - when
level=3, you get everything from level 2, plus additional warnings 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, so you have to ask for them explicitly.-Warray-bounds=2๐ โ this level also warns about the intermediate results of pointer arithmetic that might yield out of bounds values. Heads up, it can give you a bigger pile of false positives, so it's deactivated by default. ๐-Wunterminated-string-initialization(C and Objective-C only) ๐ โ warns about character arrays initialized as unterminated character sequences with a string literal, unless the declaration being initialized has thenonstringattribute. For example:
char arr[3] = "foo"; /* Warning. */
char arr2[3] __attribute__((nonstring)) = "bar"; /* No warning. */
This one is enabled by -Wextra. If -Wc++-compat is enabled, the warning uses slightly different wording and warns even if the declaration has the nonstring attribute, because in C++ those initializations are an error. ๐ญ
-Warray-compare๐ฆ โ warns about equality and relational comparisons between two operands of array type. This comparison was deprecated in C++20. Example:
int arr1[5];
int arr2[5];
bool same = arr1 == arr2;
-Warray-compare is enabled by -Wall. โจ
-Warray-parameter,-Warray-parameter=n๐ โ warns about redeclarations of functions involving parameters of array or pointer types with inconsistent kinds or forms. It also turns on detection of out-of-bounds accesses to those parameters by 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. Passing arguments of insufficient size, or accessing more than the maximum number of elements, 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. ๐
Here the warning triggers on the second declaration of f. The first one, with the keyword static, says the array argument must have at least four elements, but the second one allows an array of any size to be passed:
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,-Wno-attribute-alias๐ธ โ warns about declarations using thealiasand similar attributes whose target is incompatible with the type of the alias.-Wattribute-alias=1๐ โ the default warning level diagnoses incompatibilities between the type of the alias declaration and that of its target. These are usually signs of bugs, bestie. ๐-Wattribute-alias=2๐ฅ โ at this level, it also diagnoses cases where the attributes of the alias declaration are more restrictive than the attributes applied to its target. Those mismatches can potentially lead to incorrect code generation. Other times they're benign and could be fixed just by adding the missing attribute to the target. For comparison, see the-Wmissing-attributesoption, which controls diagnostics when the alias declaration is less restrictive than the target, rather than more restrictive.
Attributes considered 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, and that's the default. You can disable these warnings with either -Wno-attribute-alias or -Wattribute-alias=0. ๐
-Wbidi-chars=[none|unpaired|any|ucn]๐ โ warns about possibly misleading UTF-8 bidirectional control characters in comments, string literals, character constants, and identifiers. These characters can flip the writing direction from left-to-right into right-to-left (and vice versa), which can cause confusion between logical order and visual order. This is seriously dangerous, because code can look commented out when it actually isn't. ๐ฑ
GCC supports three levels of this warning. The default is -Wbidi-chars=unpaired, which 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 doesn't check UCNs. You can turn that checking on 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, ObjC++, unless-Wno-bidi-charsor-Wbidi-chars=noneis found. ๐พ
-Wbool-compare๐ โ warns about a boolean expression being compared with an integer value different from"true"/"false". For instance, the following comparison is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
This warning is enabled by -Wall. ๐
๐ okay so the warnings lineup continues, bestie, and it's giving a lot of good stuff ๐
-Wbool-operationโ ๐ Warns about sus operations on boolean expressions. Bitwise negation of a boolean is very likely a bug in your program, no cap ๐ For C, it also warns when you increment or decrement a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing one is invalid in C++17 and deprecated in older versions.) This one is turned on by-Wallโจ-Wduplicated-branchesโ ๐ช Warns when an if-else has identical branches. Like this:
if (p != NULL)
return 0;
else
return 0;
It won't warn if both branches contain just a null statement. It also warns for conditional operators, so this one's flagged too:
int i = x ? *p : *p;
-Wduplicated-condโ ๐ฏ Warns about duplicated conditions in an if-else-if chain. For example, this gets called out:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ ๐จ Warns when__builtin_frame_addressor__builtin_return_addressgets called with an argument greater than 0. These calls may return indeterminate values or crash your program, so yeah, be careful bestie ๐ This one is included in-Wall.-Wno-discarded-qualifiers(C and Objective-C only) โ ๐ซ Don't warn if type qualifiers on pointers are getting discarded. Usually the compiler complains if aconst char *variable gets passed to a function that wants achar *parameter. This option silences that.-Wno-discarded-array-qualifiers(C and Objective-C only) โ ๐งบ Don't warn if type qualifiers on arrays that are pointer targets get discarded. Typically the compiler warns when aconst int (*)[]variable is passed to a function taking anint (*)[]parameter. This option suppresses that warning.-Wno-incompatible-pointer-types(C and Objective-C only) โ ๐ โโ๏ธ Don't warn when there's a conversion between pointers with incompatible types. This covers cases not handled by-Wno-pointer-sign, which warns about pointer argument passing or assignment with different signedness.
By default, in C99 and later dialects of C, GCC treats this as an error ๐ค You can downgrade it to a warning with -fpermissive (along with certain other errors), or just this one error with -Wno-error=incompatible-pointer-types.
This warning gets upgraded to an error by -pedantic-errors.
-Wno-int-conversion(C and Objective-C only) โ ๐ข Don't 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-castand-Wno-pointer-to-int-castinstead.
By default, in C99 and later dialects of C, GCC treats this as an error ๐ค You can downgrade it to a warning with -fpermissive (along with certain other errors), or just this one with -Wno-error=int-conversion.
This warning gets upgraded to an error by -pedantic-errors.
-Wzero-as-null-pointer-constantโ 0๏ธโฃ Warns when a literal0gets used as a null pointer constant.-Wzero-length-boundsโ ๐ Warns about accesses to elements of zero-length array members that might overlap other members of the same object. Interior zero-length arrays are discouraged, because accessing them is undefined ๐ซฃ
Check this example. The first two stores in function bad get flagged because those array elements overlap the members b and c that come after them. The third store is 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
}
Option -Wzero-length-bounds is enabled by -Warray-bounds.
-Wno-div-by-zeroโ โ Don't warn about 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โ ๐๏ธ Prints warning messages for constructs found in system header files. Warnings from system headers are normally hushed, on the assumption that they usually aren't real problems and would just make the compiler output harder to read. This option tells GCC to emit those warnings as if they came from user code.
Heads up though, bestie ๐ Using -Wall together with this option does not warn about unknown pragmas in system headers. For that, you also need -Wunknown-pragmas.
-Wtautological-compareโ ๐ Warns if a self-comparison always evaluates to true or false. This catches mistakes like:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always evaluate to true or false. For instance, this one will always be false:
if ((a & 16) == 10) { ... }
This warning is enabled by -Wall.
-Wtrailing-whitespace,-Wtrailing-whitespace=kindโ ๐ซง Warns about trailing whitespace at the end of lines, including inside comments, but not trailing whitespace in raw string literals.-Wtrailing-whitespaceis the same as-Wtrailing-whitespace=blanks, which warns about trailing spaces and horizontal tabs.-Wtrailing-whitespace=anywarns about those plus trailing form feed or vertical tab characters.-Wno-trailing-whitespaceor-Wtrailing-whitespace=noneturns it off, and off is the default. This is a coding style warning, so it's a vibe check thing ๐-Wleading-whitespace=kindโ ๐ชถ Warns about style issues in leading whitespace, but not about how much indentation you have. Some projects indent with only spaces, some with only tabs, and some with zero or more tabs (for multiples of-ftabstop=n) followed by zero or fewer than n spaces. No warning is emitted on lines that contain only whitespace (though a-Wtrailing-whitespace=warning might still show up), and no warnings are emitted inside raw string literals. Warnings are also emitted for leading whitespace inside multi-line comments.-Wleading-whitespace=spaceswarns about leading whitespace other than spaces, for projects that want to indent with just spaces ๐ธ-Wleading-whitespace=tabswarns about leading whitespace other than horizontal tabs, for projects that want to indent with just horizontal tabs ๐-Wleading-whitespace=blankswarns about leading whitespace other than spaces and horizontal tabs. It also warns about a horizontal tab after a space in the leading whitespace, or about 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.
This is a coding style warning too ๐
-Wtrampolinesโ ๐ช Warns about trampolines generated for pointers to nested functions. A trampoline is a small piece of data or code created at run time on the stack when the address of a nested function is taken, and it's used to call the nested function indirectly. For some targets, it's made up of data only, so it needs no special treatment. But for most targets, it's made up of code, which means the stack has to be made executable for the program to work properly ๐ญ-Wfloat-equalโ ๐งฎ Warns if floating-point values are used in equality comparisons.
The idea is that sometimes it's convenient for the programmer to treat floating-point values as approximations of infinitely precise real numbers. If you're doing that, you need to figure out (by analyzing the code, or some other way) the maximum or likely maximum error the computation introduces, and allow for it when doing comparisons (and when producing output, but that's a different problem). Instead of testing for equality, you should check whether the two values have ranges that overlap. That's done with the relational operators, so equality comparisons are probably a mistake โจ
-Wtraditional(C and Objective-C only) โ ๐ฐ๏ธ Warns about certain 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 avoid. Here's the list of what gets flagged:- Macro parameters that appear within string literals in the macro body. In traditional C, macro replacement happens inside string literals, but in ISO C it doesn't ๐งต
- In traditional C, some preprocessor directives didn't exist. Traditional preprocessors only considered a line to be a directive if the
#appeared 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#pragma, which 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, e.g. the_MIN/_MAXmacros in<limits.h>. Using these macros in user code might 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 that block ๐ฆ
- A
switchstatement with an operand of typelong๐ - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this construct ๐ซถ
- The ISO type of an integer constant has a different width or signedness than its traditional type. This warning only fires for base-ten constants, so hexadecimal and octal values (which are usually bit patterns ๐ง) get a free pass ๐ธ
- Usage of ISO string concatenation gets flagged ๐
- Initialization of automatic aggregates gets flagged too ๐
- Identifiers that clash with labels. Traditional C has no separate namespace for labels, so this is a whole vibe-check ๐ซถ
- Initialization of unions. If the initializer is zero, the warning gets skipped ๐ฆ The logic is that zero initializers in user code are usually wrapped in something like
"__STDC__"so missing-initializer warnings don't pop up, and traditional C relies on default initialization to zero anyway โจ - Conversions by prototypes between fixed-point and floating-point values, and the other way around. Missing these prototypes when compiling with traditional C causes serious problems ๐ญ This is only a subset of the possible conversion warnings. For the full set, use
-Wtraditional-conversion. - Use of ISO C style function definitions. This one is intentionally silent for prototype declarations and variadic functions, because those ISO features sneak into your code when you use libiberty's traditional C compatibility macros,
"PARAMS"and"VPARAMS"๐ It's also bypassed for nested functions, since that's already a GCC extension and not really relevant to traditional C compatibility ๐ -Wtraditional-conversion(C and Objective-C only) โ warns if a prototype causes a type conversion that's different from what would happen to the same argument without a prototype ๐ This covers fixed-point to floating-point and back, plus conversions that change the width or signedness of a fixed-point argument, unless it's the same as the default promotion.-Wdeclaration-after-statement(C and Objective-C only) โ warns when a declaration shows up after a statement in a block ๐ This one is borrowed from C++, came in with ISO C99, and is allowed by default in GCC. ISO C90 does not support it.
This warning gets upgraded to an error by -pedantic-errors ๐จ
-Wshadowโ 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 a struct, class, or enum. Turn this on and you also get every instance of local shadowing. That means-Wno-shadow=localand-Wno-shadow=compatible-localget ignored whenever-Wshadowis in use. This is the same as-Wshadow=global.-Wno-shadow-ivar(Objective-C only) โ skips the warning when a local variable shadows an instance variable inside an Objective-C method ๐-Wshadow=globalโ warns for any shadowing. Same as-Wshadow๐-Wshadow=localโ warns when a local variable shadows another local variable or parameter โจ-Wshadow=compatible-localโ warns when a local variable shadows another local variable or parameter whose type is compatible with the shadowing variable's type. In C++, "compatible" means the shadowing variable's type can be converted to the shadowed variable's type. This flag exists (on top of-Wshadow=local) because when a local variable shadows one of an incompatible type, it's most likely on purpose, not a bug or typo ๐ง Here's a classic example:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two i variables in that example have incompatible types, turning on only -Wshadow=compatible-local won't emit a warning ๐
And that's by design: if a programmer accidentally uses one in place of the other, type checking should catch it and emit an error or warning. Using this flag instead of -Wshadow=local can cut down on warnings triggered by intentional shadowing. Also note that shadowing const char *i with char *i does not emit a warning.
This warning is also enabled by -Wshadow=local ๐ธ
-Wlarger-than=byte-size โ warns whenever an object is defined whose size exceeds byte-size ๐ฃ-Wlarger-than=PTRDIFF_MAXis on by default. You can disable these warnings either by specifying a byte-size ofSIZE_MAXor more, or with-Wno-larger-than.
It also warns for calls to bounded functions like "memchr" or "strnlen" that specify a bound bigger than the largest possible object, which is PTRDIFF_MAX bytes by default. These warnings can only be disabled with -Wno-larger-than ๐ฅ
-Wno-larger-thanโ disables the-Wlarger-than=warnings. It's equivalent to-Wlarger-than=SIZE_MAXor larger ๐-Wframe-larger-than=byte-size โ warns if the size of a function frame exceeds byte-size ๐ฆ The math used to figure out the stack frame size is approximate and not conservative, so the actual requirements might be somewhat bigger than byte-size even if you don't get a warning ๐ฌ Also, any space allocated via"alloca", variable-length arrays, or related constructs is not counted when the compiler decides whether to warn.
-Wframe-larger-than=PTRDIFF_MAX is on by default. You can disable these warnings by specifying a byte-size of SIZE_MAX or more, or with -Wno-frame-larger-than.
-Wno-frame-larger-thanโ disables the-Wframe-larger-than=warnings. It's equivalent to-Wframe-larger-than=SIZE_MAXor larger ๐-Wfree-nonheap-objectโ warns when you try to deallocate an object that either wasn't allocated on the heap, or was reached through a pointer that wasn't returned by a prior call to the matching allocation function ๐งน For example,stpcpyreturns a pointer to the terminating nul character and not the beginning of the object, so thefreecall below gets diagnosed:
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wfree-nonheap-object is included in -Wall โจ
-Wstack-usage=byte-size โ warns if a function's stack usage might exceed byte-size ๐ This calculation is conservative, and any space allocated via"alloca", variable-length arrays, or related constructs is counted when the compiler decides whether to warn. The message matches the output of-fstack-usage:- If the stack usage is fully static but goes over the limit, you'll see:
warning: stack usage is 1120 bytes - If the stack usage is (partly) dynamic but bounded, you'll see:
warning: stack usage might be 1648 bytes - If the stack usage is (partly) dynamic and unbounded, you'll see:
warning: stack usage might be unbounded
- If the stack usage is fully static but goes over the limit, you'll see:
-Wstack-usage=PTRDIFF_MAX is on by default. Disable these warnings by specifying a byte-size of SIZE_MAX or more, or with -Wno-stack-usage ๐
-Wno-stack-usageโ disables the-Wstack-usage=warnings. It's equivalent to-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 ๐ค With-funsafe-loop-optimizations, it warns if the compiler does make those assumptions.-Wno-pedantic-ms-format(MinGW targets only) โ when used with-Wformatand-pedanticwithout GNU extensions, this turns off the warnings about non-ISO"printf"and"scanf"width specifiers"I32","I64", and"I"that get used on Windows targets, since those depend on the MS runtime ๐ช-Wpointer-arithโ warns about anything that depends on the "size of" a function type or of"void". GNU C gives these types a size of 1, for convenience when doing math with"void *"pointers and function pointers ๐งฎ In C++, it also warns when an arithmetic operation involves"NULL". This warning is also enabled by-Wpedantic.
This warning gets upgraded to an error by -pedantic-errors ๐จ
-Wno-pointer-compareโ doesn't warn when a pointer gets compared with a zero character constant. That usually means the pointer was meant to be dereferenced ๐ For example:
const char *p = foo ();
if (p == '\0')
return 42;
The code above is invalid in C++11 โ
This warning is enabled by default ๐
-Wno-tsanโ disables warnings about unsupported features in ThreadSanitizer ๐งต ThreadSanitizer doesn't support"std::atomic_thread_fence"and can report false positives, so this helps you tune out that noise ๐ซ-Wtype-limitsโ warns if a comparison is always true or always false because of the limited range of the data type, but doesn't warn for constant expressions ๐ For example, it warns if an unsigned variable is compared against zero with"<"or">=". This warning is also enabled by-Wextra.-Wabsolute-value(C and Objective-C only) โ warns about calls to standard functions that compute the absolute value of an argument when a more appropriate standard function exists ๐ For example, callingabs(3.14)triggers the warning, because the right function for adoubleis"fabs". It also triggers when the argument in such a call has an unsigned type. You can suppress it with an explicit type cast, and it's also enabled 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 enabled by-Wall.-Wtrigraphsโ warns if any trigraphs are encountered that might change the meaning of the program ๐ง Trigraphs inside comments aren't warned about, except for the ones that would form escaped newlines.
This one's implied by -Wall ๐
If -Wall isn't on, it's still enabled unless trigraphs are turned on. Want trigraph conversion without the warnings but still all the other -Wall goodies? Use -trigraphs -Wall -Wno-trigraphs ๐ซถ
-Wundefโ okay so this one warns if an undefined identifier gets evaluated in an#ifdirective ๐ Those identifiers get replaced with zero, so you're not getting a surprise error, just a heads-up โจ-Wexpansion-to-definedโ this warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective ๐ That usage is not portable, so you'll want to know about it. It's also turned on by-Wpedanticand-Wextra๐ฅ-Wunused-macrosโ this one flags macros defined in the main file that nobody's using ๐ A macro counts as used if it gets expanded or tested for existence at least once. The preprocessor will also side-eye you if the macro hasn't been used by the time it's redefined or undefined ๐
Built-in macros, macros defined on the command line, and macros defined in include files are not warned about, so don't stress those ๐
Heads up: if a macro is used, but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐ญ To dodge the warning, you could improve the scope of the macro's definition, like moving it into the first skipped block. Or you could give it a dummy use with something like:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ this stops the warning when an#elseor an#endifhas text after it ๐ That happens sometimes in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should really be in comments, bestie. This warning is on by default โจ
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a non-matching type ๐ธ For example, it'll warn if a call to a function returning an integer type gets cast to a pointer type.-Wc90-c99-compat(C and Objective-C only) โ this one warns about features that exist in ISO C99 but not in ISO C90 ๐ฆ Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. It doesn't care about your standards mode, and warnings are disabled in the expression that follows__extension__๐-Wc99-c11-compat(C and Objective-C only) โ same energy, but for features in ISO C11 that aren't in ISO C99 ๐ง Like anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. Independent of the standards mode, and warnings are disabled in the expression after__extension__๐-Wc11-c23-compat,-Wc11-c2x-compat(C and Objective-C only) โ warns about features in ISO C23 that aren't in ISO C11 ๐ Think omitting the string in_Static_assert, using[[]]attribute syntax, decimal floating-point types, and so on. It's independent of the standards mode, and warnings are disabled in the expression after__extension__. Also, the name-Wc11-c2x-compatis deprecated, so use the newer one ๐ซ
When you're not compiling in C23 mode, these warnings get upgraded to errors by -pedantic-errors ๐ค
-Wc23-c2y-compat(C and Objective-C only) โ warns about features in ISO C2Y that aren't in ISO C23 โจ For instance,_Genericselecting with a type name instead of an expression. Also independent of the standards mode, with warnings disabled in the expression that follows__extension__.-Wc23-c2y-compat(C and Objective-C only) โ yep, this one's listed twice in the original page, so here it is again ๐ Same vibe: features in ISO C2Y, not in ISO C23, with the same__extension__rule.
When you're not compiling in C2Y mode, these warnings get upgraded to errors by -pedantic-errors ๐
-Wc++-compat(C and Objective-C only) โ warns about ISO C constructs that sit outside the common subset of ISO C and ISO C++ ๐ Like implicitly converting fromvoid *to a pointer to non-voidtype.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changes between ISO C++ 1998 and ISO C++ 2011 ๐ For example, identifiers in ISO C++ 1998 that are keywords in ISO C++ 2011. This one turns on-Wnarrowingand is enabled by-Wall.-Wc++14-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning differs between ISO C++ 2011 and ISO C++ 2014 ๐ Enabled by-Wall.-Wc++17-compat(C++ and Objective-C++ only) โ same idea for ISO C++ 2014 vs ISO C++ 2017 โญ Enabled by-Wall.-Wc++20-compat(C++ and Objective-C++ only) โ and this one covers ISO C++ 2017 vs ISO C++ 2020 ๐ฆ Enabled by-Wall.-Wno-c++11-extensions(C++ and Objective-C++ only) โ don't warn about C++11 constructs when you're compiling with an older C++ standard ๐ธ Even without this option, some C++11 constructs only get flagged if-Wpedanticis used.-Wno-c++14-extensions(C++ and Objective-C++ only) โ same deal, but for C++14 constructs ๐ง Some of them only get diagnosed with-Wpedantic.-Wno-c++17-extensions(C++ and Objective-C++ only) โ you guessed it, C++17 constructs in code compiled with an older standard ๐ Some still only show up under-Wpedantic.-Wno-c++20-extensions(C++ and Objective-C++ only) โ C++20 constructs, same rules ๐ Some only get diagnosed when-Wpedanticis used.-Wno-c++23-extensions(C++ and Objective-C++ only) โ C++23 constructs in code compiled with an older C++ standard โจ Some only get flagged under-Wpedantic.-Wno-c++26-extensions(C++ and Objective-C++ only) โ C++26 constructs, same story ๐ซถ Some still need-Wpedanticto get diagnosed.-Wcast-qualโ warns whenever a pointer gets cast in a way that removes a type qualifier from the target type ๐ญ For example, it'll warn if aconst char *is cast to an ordinarychar *.
It also warns when you make a cast that adds a type qualifier in an unsafe way ๐ Casting char ** to const char ** is unsafe, as in this example:
/* 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 is cast so that the required alignment of the target goes up ๐ For example, it'll warn if achar *is cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries.-Wcast-align=strictโ same vibe, but stricter ๐ค It warns whenever a pointer is cast so the required alignment of the target increases, and it does this for achar *cast to anint *regardless of the target machine.-Wcast-function-typeโ warns when a function pointer is cast to an incompatible function pointer ๐ฅ For casts involving function types with a variable argument list, only the types of the initial arguments that are provided get considered. Any parameter of pointer type matches any other pointer type. Benign differences in integral types get ignored, likeintvs.longon ILP32 targets, and type qualifiers are ignored too. The function typevoid (*) (void)is special and matches everything, so it can be used to suppress this warning ๐ For casts involving pointer to member types, this warning fires whenever the cast changes the pointer to member type. Enabled by-Wextra.-Wcast-user-definedโ warns when a cast to a reference type doesn't involve a user-defined conversion that the programmer might expect to get called ๐ Here's the example:
struct A { operator const int&(); } a;
auto r = (int&)a; // warning
This warning is enabled by default โจ
-Wwrite-stringsโ when compiling C, this gives string constants the typeconst char[length], so copying the address of one into a non-constchar *pointer produces a warning ๐ These warnings help you catch, at compile time, code that might try to write into a string constant, but only if you've been super careful about usingconstin declarations and prototypes. Otherwise, honestly, it's just a nuisance. That's why-Walldoesn't request these warnings ๐
When compiling C++, it warns about the deprecated conversion from string literals to char *. This warning is enabled by default for C++ programs ๐ฆ
In C++11 mode or later, this warning is upgraded to an error by -pedantic-errors ๐ญ
-Wclobberedโ warns for variables that might be changed bylongjmporvfork๐ธ This warning is also enabled by-Wextra.-Wno-complain-wrong-langโ by default, language front ends complain when a command-line option is valid but not applicable to that front end ๐ง You can turn that off with-Wno-complain-wrong-lang, which is mostly useful when you invoke a single compiler driver for multiple source files written in different languages. For example:
$ g++ -fno-rtti a.cc b.f90
The driver g++ invokes the C++ front end to compile a.cc and the Fortran front end to compile b.f90. The latter front end diagnoses f951: Warning: command-line option '-fno-rtti' is valid for C++/D/ObjC++ but not for Fortran, which can be disabled with -Wno-complain-wrong-lang ๐
-Wcompare-distinct-pointer-types(C and Objective-C only) โ warns if pointers of distinct types get compared without a cast ๐ This warning is enabled by default โจ-Wconversionโ okay so this one is all about sneaky implicit conversions that might quietly change a value ๐ It catches real-to-integer stuff likeabs (x)whenxisdouble, signed-to-unsigned stuff likeunsigned ui = -1, and squishing things into smaller types likesqrtf (M_PI). It does not warn for explicit casts likeabs ((int) x)andui = (unsigned) -1, or when the value doesn't actually change, likeabs (2.0). If the signed/unsigned warnings are too much, you can mute just those with-Wno-sign-conversion๐ซถ
For C++, it also flags confusing overload resolution for user-defined conversions, plus conversions that never use a type conversion operator (conversions to void, the same type, a base class, or a reference to them) โจ Heads up though: the signed/unsigned integer warnings are off by default in C++ unless you explicitly turn on -Wsign-conversion ๐
Warnings about conversion from arithmetic on a small type back to that type only show up with -Warith-conversion ๐ธ
-Wdangling-elseโ this one warns when it's unclear whichifanelsebranch actually belongs to ๐ Check out this chaos:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C/C++, every else belongs to the innermost possible if, which here is if (b). That's usually not what the programmer meant, even though the indentation says otherwise. When that confusion is possible, GCC warns if you use this flag ๐จ To kill the warning, slap explicit braces around the innermost if so the else can't possibly belong to the outer one. It ends up looking like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses ๐
-Wdangling-pointer,-Wdangling-pointer=nโ okay this is a big one ๐ฆ It warns about using pointers (or C++ references) to objects with automatic storage duration after their lifetime has ended. That covers 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. It's enabled at every optimization level, but the results can look different with optimization than without, so keep that in mind ๐-Wdangling-pointer=1โ at level 1, it only diagnoses unconditional uses of dangling pointers ๐ท-Wdangling-pointer=2โ at level 2, it also diagnoses conditional uses of dangling pointers ๐
The short form -Wdangling-pointer is the same as -Wdangling-pointer=2. Meanwhile, -Wno-dangling-pointer and -Wdangling-pointer=0 both turn the warnings off ๐ And -Wdangling-pointer=2 is already included in -Wall โจ
Here's a level 1 example. The address of the unnamed temporary gets unconditionally used outside of its scope, so it gets flagged:
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 one, storing the address of the local variable x into the escaped pointer *p triggers the level 1 warning ๐ง
void g (int **p)
{
int x = 7;
// warning: storing the address of local variable 'x' in '*p'
*p = &x;
}
And 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 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โ this warns whenever the macros__TIME__,__DATE__or__TIMESTAMP__show up ๐ฐ๏ธ The reason? They might stop your compilations from being bit-wise-identical and reproducible, which is a whole vibe-killer for builds ๐ญ-Wempty-bodyโ warns if an empty body shows up in anif,elseordo whilestatement ๐ This one is also enabled by-Wextra๐-Wno-endif-labelsโ stops GCC from complaining about stray tokens after#elseand#endif๐-Wenum-compareโ warns about comparing values of different enumerated types ๐ In C++, enumerated type mismatches in conditional expressions get diagnosed too, and that one is enabled by default. In C, this warning comes along with-Wallโจ-Wenum-conversionโ warns when a value of one enumerated type gets implicitly converted to a different enumerated type ๐ฅ In C, it's enabled by-Wextra๐-Wenum-int-mismatch(C and Objective-C only) โ this one warns about mismatches between an enumerated type and an integer type in declarations ๐ง For example:
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 since the choice of underlying type for an enumerated type is implementation-defined, these mismatches can cause portability issues ๐ In C++, mismatches like this are 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 that variable has already been initialized ๐ It only cares about variables that are initialized when they're declared. This is only supported for C and Objective-C, because in C++ this sort of branch is an error anyway ๐ซ
In C++, jumping like this is always an error, so there's no need to worry about this warning there.
-Wjump-misses-init is included in -Wc++-compat, and you can disable it with the -Wno-jump-misses-init option ๐ซถ
-Wsign-compareโ warns when a comparison between signed and unsigned values could give a wrong result because the signed value gets converted to unsigned โ ๏ธ In C++, this is also enabled by-Wall. In C, it's enabled by-Wextratoo ๐-Wsign-conversionโ warns about implicit conversions that might change the sign of an integer value, like assigning a signed integer expression to an unsigned integer variable ๐ธ An explicit cast silences the warning โจ In C, this option is also enabled by-Wconversion๐-Wflex-array-member-not-at-end(C and C++ only) โ warns when a structure that has a C99 flexible array member as its last field ends up not at the end of another structure ๐งฉ This warning goes off for code like this:
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 conversions from higher precision real values to lower precision ones. This option is also enabled by-Wconversion๐ฆ-Wno-scalar-storage-orderโ stops GCC from warning 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 ๐งฎ In that case, the math won't give you the number of elements in the array, which is probably not what you wanted. This warning goes off for code like this:
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 the usual trick for computing an array's size, but it won't work with pointers ๐ The warning goes off forsizeof (ptr) / sizeof (ptr[0])ifptris a pointer and not an array. It's enabled by-Wallโจ-Wsizeof-pointer-memaccessโ warns about suspicious length parameters passed to certain string and memory built-in functions when the argument usessizeof๐ง For example, it triggers onmemset (ptr, 0, sizeof (ptr));ifptris a pointer and not an array, and it suggests a possible fix. It also triggers on things likememcpy (&foo, ptr, sizeof (&foo));๐
This option also warns about calls to bounded string copy functions like strncat or strncpy that use the sizeof of the source array as the bound. In the following function, the strncat call uses the size of the source string as its bound. That's 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");
...
}
-Wsizeof-pointer-memaccess is enabled by -Wall ๐
-Wno-sizeof-array-argumentโ stops GCC from warning when thesizeofoperator is 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, so this flag is how you turn it off ๐ซ-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function. It triggers when 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 usually means you forgot to multiply by the element size ๐ This warning is enabled by-Wall๐ซถ
โจ OPTIONS โจ (continued)
-Wmemset-transposed-argsโ okay so this one yells at you ๐ when you call thememsetbuilt-in with a non-zero second argument and a literal zero as the third.memset (buf, sizeof buf, 0)gets flagged because you probably meantmemset (buf, 0, sizeof buf)๐ . It only fires when 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 it stays quiet. This one is turned on by-Wall๐ซถ.-Waddressโ this is the suspicious-address-expression check and it is giving detective ๐ต๏ธโโ๏ธ. It catches comparing the address of a function or declared object against the null pointer constant, like this:
void f (void);
void g (void)
{
if (!f) // warning: expression evaluates to false
abort ();
}
It also side-eyes comparing a pointer to a string literal:
void f (const char *x)
{
if (x == "abc") // warning: expression evaluates to false
puts ("equal");
}
And it flags testing the result of pointer addition or subtraction for equality to null:
void f (const int *p, int i)
{
return p + i == NULL;
}
Real talk, these usually mean a programmer error ๐ญ. The address of most functions and objects always evaluates to true (the exceptions are 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 the warning can be shushed by casting the pointer operand to an integer type like intptr_t or uintptr_t. Comparisons against string literals give unspecified behavior and aren't portable, and they hint that you meant to call strcmp ๐. The warning gets suppressed if the sus expression came out of a macro expansion. The -Waddress warning is enabled by -Wall โจ.
-Wno-address-of-packed-memberโ the "don't warn me" option ๐ฆ. Skip the warning when the address of a packed member of a struct or union is taken, which usually ends up as an unaligned pointer value. This is enabled by default ๐.-Wlogical-opโ warns about sus logical operators in expressions ๐. That includes using a logical operator where a bit-wise operator is probably what you wanted. It also flags when both operands of a logical operator are the same, like this:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ this one is looking for a logical not on the left hand side of a comparison ๐ง. It doesn't warn if the right operand is considered a boolean expression. The whole point is catching code like this:
int a;
...
if (!a > 1) { ... }
You can shut the warning up by wrapping the LHS in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall ๐ธ.
-Waggregate-returnโ warns if any function that returns a structure or union gets defined or called ๐ฆ. In languages where you can return an array, this also gives you a warning, so keep an eye out.-Wno-aggressive-loop-optimizationsโ the "chill, don't warn me" option ๐. Skip the warning when the compiler detects undefined behavior in a loop with a constant number of iterations.-Waggressive-loop-optimizationsis enabled by default ๐.-Wno-attributesโ silences warnings when you use an unexpected__attribute__, like unrecognized attributes or function attributes slapped on variables ๐. It doesn't stop errors for using supported attributes wrong, though, so don't get too comfy.
Heads up: ill-formed uses of standard attributes get upgraded to errors by -pedantic-errors.
Also, with -Wno-attributes=, you can suppress warnings about unknown scoped attributes (in C++11 and C23) ๐ง. For example, -Wno-attributes=vendor::attr disables the warning about this declaration:
[[vendor::attr]] void f();
You can also hush warnings about all attributes in a namespace with -Wno-attributes=vendor::, which stops the warning about both of these:
[[vendor::safe]] void f();
[[vendor::unsafe]] void f2();
Note that -Wno-attributes= does not imply -Wno-attributes โ ๏ธ.
-Wno-builtin-declaration-mismatchโ the "I know what I'm doing" option ๐ . This warns when a built-in function is declared with an incompatible signature or as a non-function, or when a built-in declared with a type that doesn't include a prototype gets called with args whose promoted types don't match what the function expects. With-Wextra, it also warns when a built-in that takes arguments is declared without a prototype. The-Wbuiltin-declaration-mismatchwarning is enabled by default. To avoid it, include the right header so the built-in prototypes are in scope ๐ซถ.
Like here, the call to memset gets diagnosed because the function expects a size_t as its argument but 32 is an int. With -Wextra, the declaration gets called out too ๐:
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ no more warnings when certain built-in macros get redefined ๐. This suppresses warnings for redefining__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__โฐ.-Wfree-labels(C and Objective-C only) โ warns if a label is slapped on a non-statement, or shows up at the end of a compound statement ๐ท๏ธ. C23 and later dialects of C allow these, and they're a GCC extension in all other dialects.
This warning is also turned on by -Wc11-c23-compat. It becomes an error if you're building for a C version before C23 with -pedantic-errors ๐ซ.
-Wheader-guardโ this one is a total detective for header guards ๐. It warns when a valid preprocessor header multiple-inclusion guard has a#defineright after the#ifndefor#if !defineddirective, where that#definedefines a different macro from the guard with a similar name. The real guard macro 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 !defineddirective 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 its argument types ๐. An old-style function definition is allowed without a warning if a declaration that specifies the argument types came before it.-Wold-style-declaration(C and Objective-C only) โ warns about obsolescent declaration usages, 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 ๐ต. You get the warning even if there's a previous prototype. In C23 mode, a definition using()is not considered old-style, because it's equivalent to(void)in that case. For older standards, though, it counts as an old-style definition.-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 turned on 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 is handy for documenting that a parameter is unused in the definition. It's part of C23 and later dialects of C, and available as a GCC extension in all other dialects.
This warning is also turned on by -Wc11-c23-compat. It becomes an error if you're building for a C version before C23 with -pedantic-errors ๐ซ.
-Wmissing-parameter-type(C and Objective-C only) โ warns when a function parameter gets declared without a type specifier in K&R-style functions ๐ฐ๏ธ:
void foo(bar) { }
This warning is also enabled by -Wextra ๐ธ.
-Wno-declaration-missing-parameter-type(C and Objective-C only) โ stops the warning when a function declaration has a parameter name with no type ๐ โโ๏ธ. Those declarations don't give you a function prototype, and they block most type checking in function calls.
This warning is enabled by default. In C99 and later dialects of C, it's treated as an error ๐ฑ. You can downgrade that error to a warning with -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=declaration-missing-parameter-type.
This warning is upgraded to an error by -pedantic-errors ๐ซ.
-Wmissing-prototypes(C and Objective-C only) โ warns if a global function gets defined without a previous prototype declaration ๐. You get the warning even if the definition itself provides a prototype. Use this to catch global functions that don't have a matching prototype declaration in a header file ๐. This option isn't valid for C++, because all function declarations there provide prototypes, and a non-matching declaration declares an overload rather than conflicting with an earlier one. Use-Wmissing-declarationsto find missing declarations in C++ ๐.-Wmissing-variable-declarations(C and Objective-C only) โ warns if a global variable gets defined without a previous declaration ๐งพ. Use this to catch global variables that don't have a matchingexterndeclaration in a header file โจ.
Okay so we're still deep in the OPTIONS drama ๐ and this batch is packed with warnings, bestie ๐ซถ
-Wmissing-declarationsโ okay, this one's a vibe check on global functions ๐. It warns if a global function gets defined without a previous declaration, even if the definition already comes with a prototype. Use it to catch global functions that never got declared in header files. In C, nothing gets flagged for functions with earlier non-prototype declarations, so reach for-Wmissing-prototypesif you want to catch missing prototypes. In C++, it skips function templates, inline functions, and functions in anonymous namespaces โจ-Wmissing-field-initializersโ this one is SO relatable ๐ญ. It warns when a struct's initializer leaves some fields out. Like, herex.hjust quietly becomes zero:
struct s { int f, g, h; };
struct s x = { 3, 4 };
In C, this option doesn't yell about designated initializers, so this one's totally 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 };
Same deal in C++ with the empty { } initializer, no warning ๐:
struct s { int f, g, h; };
s x = { };
This one is part of -Wextra. If you want the other -Wextra warnings without this one, go with -Wextra -Wno-missing-field-initializers ๐
-Wno-missing-requiresโ the compiler warns about a concept-id showing up as a C++20 simple-requirement by default ๐ง. Check this out:
bool satisfied = requires { C<T> };
Here satisfied will be true if C<T> is a valid expression, which it is for all T. The person probably meant this instead:
bool satisfied = requires { requires C<T> };
That way satisfied is only true if concept C is satisfied for type T. You can switch this warning off with -Wno-missing-requires ๐
-Wno-missing-template-keywordโ the member access tokens.,->and::need the "template" keyword ๐ if the parent object is dependent and the member you're naming is a template. Look at the good and the not-so-good:
template <class X>
void DoStuff (X x)
{
x.template DoSomeOtherStuff<X>(); // Good.
x.DoMoreStuff<X>(); // Warning, x is dependent.
}
Every once in a while you can get false positives. To silence them, wrap the expression in parentheses. Like, this one gets treated as a template even when 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.
}
You can disable this warning with -Wno-missing-template-keyword ๐
-Wno-multicharโ don't warn about multicharacter constants like 'FOOF' ๐. Usually these are a typo in your code, since they have implementation-defined values, so they really shouldn't show up in portable code.-Wnormalized=[none|id|nfc|nfkc]โ this is the identifier normalization era ๐. In ISO C and ISO C++, two identifiers are different if they're different character sequences. BUT with characters outside basic ASCII you can get two different sequences that look exactly the same ๐ต. ISO 10646 has normalization rules that turn lookalikes into one shared sequence, and GCC can warn you when your identifiers haven't been normalized. This option controls that warning.
There are four warning 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 one recommended for most uses, and it's the same as -Wnormalized.
Some characters that ISO C and ISO C++ let you use in identifiers can't be used once they're turned into NFC. So there's no way to use those symbols in portable ISO C or C++ and keep all your identifiers in NFC ๐ซ . -Wnormalized=id suppresses the warning for those characters. The hope is that future versions of the standards fix this, which is why it isn't the default.
You can switch the warning off for every character 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 example, "\u207F", "SUPERSCRIPT LATIN SMALL LETTER N", looks just like a regular "n" that's been placed in a superscript ๐. ISO 10646 also defines the NFKC normalization scheme to turn all of these into a standard form, and GCC warns you if your code isn't NFKC when you use -Wnormalized=nfkc. This is kind of like warning about every identifier with the letter O, since it might get mixed up with the digit 0. That's why it isn't the default, but it can be a handy local coding convention if your environment can't be fixed to display these characters differently โจ
-Wno-attribute-warningโ don't warn about using functions declared with the "warning" attribute ๐ฆ. This warning is on by default. You can turn the warning off with-Wno-attribute-warning, or use-Wno-error=attribute-warningto turn off the error you'd get when compiling with-Werror๐-Wno-deprecatedโ don't warn about deprecated features ๐ธ. Heads up though: in C++, explicitly specifying-Wdeprecatedalso turns on warnings about features that are deprecated in later language standards. Those are-Wcomma-subscript,-Wvolatile,-Wdeprecated-enum-float-conversion,-Wdeprecated-enum-enum-conversion,-Wdeprecated-literal-operator, and-Wdeprecated-variadic-comma-omission๐ฅน-Wno-deprecated-declarationsโ don't warn about uses of functions, variables, and types marked as deprecated with the "deprecated" attribute ๐-Wno-overflowโ don't warn about compile-time overflow in constant expressions ๐ข-Wno-odrโ warn about One Definition Rule violations during link-time optimization โ๏ธ. It's enabled by default, so you'd have to actively turn it off to lose it.-Wopenacc-parallelismโ warn about potentially suboptimal choices related to OpenACC parallelism ๐-Wno-openmpโ warn about suspicious OpenMP code ๐ง-Wopenmp-simdโ warn if the vectorizer cost model overrides the OpenMP simd directive that the user set ๐ซฃ. If you want to relax the cost model, you can use-fsimd-cost-model=unlimited๐-Woverride-init(C and Objective-C only) โ warn if an initialized field without side effects gets overridden when you're using designated initializers ๐. This one is part of-Wextra. To get the other-Wextrawarnings without it, use-Wextra -Wno-override-init๐-Wno-override-init-side-effects(C and Objective-C only) โ don't warn if an initialized field with side effects gets overridden when using designated initializers. This is enabled by default ๐-Wpackedโ warn if a structure gets the packed attribute but that attribute has no effect on the layout or size of the structure ๐ค. Structures like that can end up misaligned for basically zero benefit. In this code, the variablef.xinsidestruct baris misaligned even thoughstruct bardoesn't have the packed attribute itself ๐:
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 ๐ฐ๏ธ. That got fixed in GCC 4.4, but the change can cause 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 fieldsaandbin this structure โจ:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default. To disable it, use -Wno-packed-bitfield-compat ๐
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ warn if a structure field with explicitly specified alignment in a packed struct or union is misaligned ๐งฉ. For example, this code gets a warning onstruct S, like: "warning: alignment 1 of 'struct S' is less than 8" ๐ฌ
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall ๐
-Wpaddedโ warn if padding is included in a structure, either to align one of its elements or to align the whole structure ๐ซง. Sometimes you can rearrange the fields to reduce the padding and make the structure smaller ๐-Wredundant-declsโ warn if anything gets declared more than once in the same scope, even when multiple declarations are valid and change nothing ๐-Wrestrictโ this one catches sneaky aliasing ๐ต๏ธโโ๏ธ. It 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 those objects overlap. In thestrcpycall below, the code tries to truncate the string by overwriting its start with its last four characters. But because the call writes the terminating NUL intoa[4], the copies overlap and the call gets diagnosed ๐ญ:
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
-Wrestrict catches 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) โ warn if an "extern" declaration shows up inside a function ๐ โโ๏ธ-Winlineโ ๐ฆ okay so this one yells if a function you markedinlinecan't actually get inlined ๐ญ Even with it on, GCC stays quiet about functions living in system headers, so no drama there. The compiler is basically running a vibe check on its own heuristics: the size of the function and how much inlining already happened in the current function both factor in. That means tiny edits to your source can make these warnings pop up or vanish, so don't panic if it changes randomly ๐-Winterference-sizeโ โจ this one warns about using C++17'sstd::hardware_destructive_interference_sizewithout setting its value via--param destructive-interference-size. It also side-eyes any questionable values you pass for that option ๐
This variable is built for controlling class layout so concurrent code doesn't suffer from false sharing ๐ง Check out this serve:
struct independent_fields {
alignas(std::hardware_destructive_interference_size)
std::atomic<int> one;
alignas(std::hardware_destructive_interference_size)
std::atomic<int> two;
};
The whole point is that one and two sit far enough apart that writing to one won't force a reload of the cache line holding two ๐
By default, --param destructive-interference-size and --param constructive-interference-size get set based on the current -mtune option. Usually that lands on the L1 cache line size for the target CPU, though for a generic target it can be a range instead ๐ธ So every translation unit that relies on ABI compatibility for these variables needs to be compiled with the same -mtune (or -mcpu), or things get messy fr fr.
If ABI stability matters, like when you're using it in a header for a library, you should probably skip the hardware interference size variables entirely ๐ซถ Or, if you want, you can force a specific value with --param. And if you're totally sure your use doesn't touch ABI outside one build of your project, you can silence the warning with -Wno-interference-size ๐ฅ
-Wint-in-bool-contextโ ๐ this one flags sus integer values showing up where booleans are expected. Think conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). It also catches left shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. And it's the same deal for all kinds of multiplications, no matter the data type ๐ This warning is enabled by-Wall, so you're covered if you're already using that ๐-Wno-int-to-pointer-castโ ๐ suppresses warnings about casts to a pointer type from an integer of a different size. Quick heads up though: in C++, casting to a pointer type of smaller size is an error ๐Wint-to-pointer-castis turned on by default.-Wno-pointer-to-int-cast(C and Objective-C only) โ ๐ same energy but flipped. This one silences warnings about casts from a pointer to an integer type of a different size.-Winvalid-pchโ ๐ง warns if a precompiled header shows up in the search path but can't actually be used. Rude, but useful ๐ญ-Winvalid-utf8โ ๐ warns when an invalid UTF-8 character shows up. It's on by default for C++23 as long as-finput-charset=UTF-8is in use, and it becomes a full-on error with-pedantic-errors๐ซ-Wno-unicodeโ ๐ธ stops GCC from diagnosing invalid forms of delimited or named escape sequences that get treated as separate tokens.Wunicodeis enabled by default, so this is the opt-out ๐-Wlong-longโ โญ warns if thelong longtype gets used. It's enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. Want those warnings gone? Use-Wno-long-long๐ซถ
๐จ This warning gets upgraded to an error by -pedantic-errors, so be careful with that combo!
-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. To shush the messages, use-Wno-variadic-macrosโจ-Wno-varargsโ ๐ tells GCC to chill about questionable usage of the macros that handle variable arguments, likeva_start. These warnings are on by default, so this is how you turn them off ๐-Wvector-operation-performanceโ ๐ฅ warns if a vector operation isn't implemented using the architecture's SIMD capabilities. It's mainly handy for performance tuning. Here's the lineup: a vector operation can be done "piecewise", meaning the scalar operation runs on every vector element; "in parallel", meaning it's implemented using scalars of a wider type, which is usually more performance efficient; or "as a single scalar", meaning 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 warning gets upgraded to an error by -pedantic-errors. Don't say I didn't warn you ๐
-Wvla-larger-than=byte-sizeโ ๐ when this is used, 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 past byte-size bytes. It's basically the VLA cousin of how-Walloca-larger-than=byte-sizeworks ๐ง
Heads up: GCC might optimize small variable-length arrays with a known value into plain arrays, so this warning might not fire for those ๐ธ
-Wvla-larger-than=PTRDIFF_MAX is enabled 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โ ๐ disables the-Wvla-larger-than=warnings. It's the same as-Wvla-larger-than=SIZE_MAXor larger ๐ซถ-Wvla-parameterโ ๐ฎ warns about redeclarations of functions involving arguments of Variable Length Array types with inconsistent kinds or forms. It also enables detecting 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 passing arguments of sufficient size, or accessing more than that maximum, may get diagnosed ๐
For example, 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 must have at least n elements. Plus, calling f with the associated VLA bound parameter bigger than the actual VLA bound triggers a warning too ๐ญ
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);
...
}
-Wvla-parameter is included in -Wall. The -Warray-parameter option triggers warnings for similar problems involving ordinary array arguments ๐
-Wvolatile-register-varโ ๐ warns if a register variable is declaredvolatile. Here's the 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 warnings about uses of^, the exclusive or operator, when it looks like the code meant exponentiation. Specifically, the warning pops up 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 ๐ง
This warning can be silenced 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, though: 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 itself would likely take an inordinate amount 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 gets upgraded to an error by -pedantic-errors ๐ซ
-Wstack-protectorโ ๐ก๏ธ this one's 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 are generally fine with string constants way longer than that minimum, but very portable programs should steer clear of longer strings ๐
The limit applies after string constant concatenation, and it doesn't count the trailing NUL. In C90 the limit was 509 characters, and 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) โ ๐ฆ issues a warning for any floating constant that doesn't have a suffix. When it's used together with-Wsystem-headers, it warns about those constants in system header files too ๐ This can be really handy when you're getting code ready to use with the"FLOAT_CONST_DECIMAL64"pragma 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 coming 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 the"designated_init"attribute ๐
โจ Options That Control Static Analysis โจ
-fanalyzer ๐
okay so this one turns on a static analysis of program flow that hunts for "interesting" interprocedural paths through your code and yells at you about problems it finds along them ๐ฃ no cap, it's a whole vibe
heads up though, this analysis is way more expensive than your regular GCC warnings ๐
technically speaking, it does coverage-guided symbolic execution of the code being compiled ๐ง it is neither sound nor complete, so it can throw false positives and false negatives ๐ it's a bug-finding tool, not a tool for proving your program correct, so don't go using it as your proof ๐ซถ
the analyzer is only suitable for C code in this release ๐
enabling this option effectively turns on 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-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 only works if GCC was configured with analyzer support enabled, so check that before you get your hopes up ๐ฅบ
-Wanalyzer-symbol-too-complex ๐
if -fanalyzer is on, the analyzer uses a bunch of heuristics to keep track of the state of memory โจ but honestly, sufficiently complicated code can totally defeat them ๐ญ
by default, the analysis quietly stops tracking the values of expressions that go over the threshold set by --param analyzer-max-svalue-depth=value, and it falls back to an imprecise representation for those expressions ๐ซ -Wanalyzer-symbol-too-complex is the one that actually warns you when this happens ๐ข
-Wanalyzer-too-complex ๐ช๏ธ
same energy as above: with -fanalyzer enabled, the analyzer uses heuristics to explore control flow and data flow in your program ๐ฆ but again, sufficiently complicated code can defeat it ๐
by default, the analysis quietly gives up if the code is too complicated to fully explore and it hits an internal limit ๐ -Wanalyzer-too-complex is what warns you when that happens ๐จ
-Wno-analyzer-allocation-size ๐
this warning needs -fanalyzer to be on, which is what enables it ๐ to turn it off, use -Wno-analyzer-allocation-size ๐
โโ๏ธ
this diagnostic warns about paths through the code where a pointer to a buffer gets assigned to point at a buffer whose size is not a multiple of sizeof (*pointer) ๐ง
see also CWE-131: Incorrect Calculation of Buffer Size (https://cwe.mitre.org/data/definitions/131.html) ๐
-Wno-analyzer-deref-before-check ๐ซฃ
this one also requires -fanalyzer to enable it, and you can disable it with -Wno-analyzer-deref-before-check ๐
this diagnostic warns about paths where a pointer gets checked for NULL after it's already been dereferenced, which suggests the pointer could have been NULL all along ๐ฌ those cases mean the NULL check is either redundant, or it needs to move to before the dereference ๐
it also treats values passed to a function argument marked with __attribute__((nonnull)) as needing a non-NULL value, so it'll complain if those values get checked for NULL after the function call returns ๐
โ ๏ธ this diagnostic is unlikely to show up when any level of optimization is enabled, because GCC's optimizer usually sees those NULL checks as redundant and optimizes them away before the analyzer ever gets a look ๐ฅฒ so if you're trying to trigger it, turn optimization off first ๐
-Wno-analyzer-double-fclose ๐
requires -fanalyzer to be on, and you turn it off with -Wno-analyzer-double-fclose ๐ธ
this diagnostic warns about paths where a FILE * can have fclose called on it more than once ๐
see also CWE-1341: Multiple Releases of Same Resource or Handle (https://cwe.mitre.org/data/definitions/1341.html) ๐
-Wno-analyzer-double-free ๐ชฆ
again, you need -fanalyzer for this one, and you disable it with -Wno-analyzer-double-free ๐
this diagnostic warns about paths where a pointer can have a deallocator called on it more than once ๐ฑ that deallocator can be free, or a deallocator referenced by attribute malloc ๐งน
see also CWE-415: Double Free (https://cwe.mitre.org/data/definitions/415.html) ๐
-Wno-analyzer-exposure-through-output-file ๐คซ
needs -fanalyzer to enable it, and to disable it you use -Wno-analyzer-exposure-through-output-file ๐
โโ๏ธ
this diagnostic warns about paths where a security-sensitive value gets written to an output file, like writing a password into a log file ๐ญ
see also CWE-532: Information Exposure Through Log Files (https://cwe.mitre.org/data/definitions/532.html) ๐
-Wanalyzer-exposure-through-uninit-copy ๐ต๏ธโโ๏ธ
this one needs both -fanalyzer and the use of a plugin that specifies a function copying across a "trust boundary" ๐ to disable it, use -Wno-analyzer-exposure-through-uninit-copy ๐
โโ๏ธ
this diagnostic warns about "infoleaks", which are paths where uninitialized values get copied across a security boundary ๐ซฃ think of code inside an OS kernel copying a partly initialized struct from the stack out to user space ๐
see also CWE-200: Exposure of Sensitive Information to an Unauthorized Actor (https://cwe.mitre.org/data/definitions/200.html) ๐
-Wno-analyzer-fd-access-mode-mismatch ๐
this warning needs -fanalyzer to be on, and you turn it off with -Wno-analyzer-fd-access-mode-mismatch ๐
this diagnostic warns about paths where a "read" is attempted on a write-only file descriptor, or the other way around ๐
it also warns about code paths where a function with attribute fd_arg_read (N) gets called with a file descriptor opened with O_WRONLY at referenced argument N, or a function with attribute fd_arg_write (N) gets called with a file descriptor opened with O_RDONLY at referenced argument N โจ
-Wno-analyzer-fd-double-close โ๏ธ
requires -fanalyzer to enable, and you disable it with -Wno-analyzer-fd-double-close ๐
this diagnostic warns about paths where a file descriptor can be closed more than once ๐ต
see also CWE-1341: Multiple Releases of Same Resource or Handle (https://cwe.mitre.org/data/definitions/1341.html) ๐
-Wno-analyzer-fd-leak ๐ง
you need -fanalyzer for this one, and to turn it off use -Wno-analyzer-fd-leak ๐ซถ
this diagnostic warns about paths where an open file descriptor gets leaked ๐ฐ
see also 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 โณ
requires -fanalyzer, and you disable it with -Wno-analyzer-fd-phase-mismatch ๐ท
this diagnostic warns about paths where an operation gets attempted in the wrong phase of a file descriptor's lifetime ๐งฌ for example, it'll warn if you try to call accept on a stream socket that hasn't had listen successfully called on it yet ๐
see also CWE-666: Operation on Resource in Wrong Phase of Lifetime (https://cwe.mitre.org/data/definitions/666.html) ๐
-Wno-analyzer-fd-type-mismatch ๐งฉ
needs -fanalyzer to enable, and you turn it off with -Wno-analyzer-fd-type-mismatch ๐
this diagnostic warns about paths where an operation is attempted on the wrong type of file descriptor ๐
โโ๏ธ for example, it'll warn if you try socket operations on a file descriptor you got from open, or if you try a stream socket operation on a datagram socket ๐ก
-Wno-analyzer-fd-use-after-close ๐ช
this one requires -fanalyzer, and you disable it with -Wno-analyzer-fd-use-after-close ๐
this diagnostic warns about paths where a read or write gets called on a closed file descriptor ๐
it also warns about paths where a function with attribute fd_arg (N), fd_arg_read (N), or fd_arg_write (N) gets called with a closed file descriptor at referenced argument N ๐ซ
-Wno-analyzer-fd-use-without-check ๐
needs -fanalyzer to be on, and to disable it you use -Wno-analyzer-fd-use-without-check ๐
this diagnostic warns about paths where a file descriptor gets used without being checked for validity ๐
it also warns about paths where a function with attribute fd_arg (N), fd_arg_read (N), or fd_arg_write (N) gets called with a file descriptor at referenced argument N without being checked for validity ๐ซถ
-Wno-analyzer-file-leak ๐๏ธ
requires -fanalyzer, and you turn it off with -Wno-analyzer-file-leak โจ
this diagnostic warns about paths through the code where a <stdio.h> FILE * stream object gets leaked ๐ฅน
see also CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime (https://cwe.mitre.org/data/definitions/775.html) ๐
Okay so the analyzer warnings keep rolling in, bestie ๐ ๐ธ
-Wno-analyzer-free-of-non-heapโ ๐ซถ this one needs-fanalyzerto be on (that's what switches it on), and if it's bugging you,-Wno-analyzer-free-of-non-heapshuts it up. It flags paths wherefreegets called on a pointer that isn't on the heap, like an on-stack buffer or something global. Lowkey a classic mistake ๐- See CWE-590: Free of Memory not on the Heap (
https://cwe.mitre.org/data/definitions/590.html).
- See CWE-590: Free of Memory not on the Heap (
-Wno-analyzer-imprecise-fp-arithmeticโ โจ again, this needs-fanalyzerto be enabled, and-Wno-analyzer-imprecise-fp-arithmeticturns it off. It warns on paths where floating-point math is used somewhere that needs precise results. Right now it only checks floating-point operands that go into calculating an allocation size ๐งฎ-Wno-analyzer-infinite-loopโ ๐ requires-fanalyzer, and-Wno-analyzer-infinite-loopis the mute button. This one warns on paths that look like they lead into an infinite loop. The analyzer speaks up when it spots a loop where:- no externally-visible work could be happening inside the loop
- there's no way to escape from the loop
- the analyzer is confident enough about the program state across the whole loop to know that both of the above are true
One way this gets triggered is when there's an execution path through a loop where taking that path on one iteration means it gets taken on every iteration after too. Like, consider this:
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 absolutely complain about that one ๐ญ because if opcode ever matches none of the cases, the switch falls into the implicit default case. That makes the loop body a "no-op" with cpu_state.pc unchanged, so every later iteration uses the same opcode value, and boom, infinite loop ๐
- See CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop') (
https://cwe.mitre.org/data/definitions/835.html).
-Wno-analyzer-infinite-recursionโ ๐ needs-fanalyzer, and-Wno-analyzer-infinite-recursionsilences it. This one warns on paths that seem to lead into infinite recursion. Here's the vibe: whenever the analyzer sees 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 for that same function on the stack. If nothing in memory seems to change, it warns. But if parameters or globals change, it assumes the recursion will eventually end and keeps quiet ๐คซ
This one can miss cases where the optimizer turns the recursion into iteration before the analyzer gets a look, so you should turn optimization off if you're trying to trigger it on purpose.
- Compare with
-Winfinite-recursion, which gives a similar diagnostic but works in a totally different way. - See CWE-674: Uncontrolled Recursion (
https://cwe.mitre.org/data/definitions/674.html).
-Wno-analyzer-jump-through-nullโ ๐ requires-fanalyzer, and-Wno-analyzer-jump-through-nullturns it off. It warns on paths where aNULLfunction pointer gets called. Yikes, don't call the void ๐ป-Wno-analyzer-malloc-leakโ ๐ง needs-fanalyzer, and-Wno-analyzer-malloc-leakmutes it. This one warns on paths where a pointer from an allocator gets leaked, whether that allocator ismallocor a function marked with attributemalloc. Memory that never gets released is not it ๐ โโ๏ธ- 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โ ๐ requires-fanalyzer, and-Wno-analyzer-mismatching-deallocationis the off switch. It warns on paths where the wrong deallocation function gets called on a pointer, based on which function allocated it. It'll catch mismatches betweenfree, scalardelete, and vectordelete[], plus any allocator and deallocator pairs marked with attributemalloc. Mixing up your partners is a no-go ๐- 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โ ๐ง needs-fanalyzer, and-Wno-analyzer-out-of-boundsturns it off. It warns on paths where a buffer is definitely read or written out of bounds. It works when the analyzer can work out a constant offset, and for accesses past the end of a buffer with a constant capacity. It also does a bit of 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).
- See CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer (
When it can, the analyzer also prints a text art diagram showing how the memory it predicts would be accessed relates to the memory that's actually valid to access. It shows whether they overlap, touch, sit close together, or are far apart, which one comes first in memory, the relative sizes, whether it's a read or a write, and sometimes even the data values involved. Honestly so cute ๐ฆ If you don't want the diagram, you can suppress it with -fdiagnostics-text-art-charset=none.
-Wno-analyzer-overlapping-buffersโ ๐งฉ requires-fanalyzer, and-Wno-analyzer-overlapping-buffersmutes it. This one warns on paths where overlapping buffers get passed to an API that behaves undefined on overlapping buffers. Specifically, it triggers on calls to these functions:memcpystrcatstrcpy
but only when the buffers are known to overlap โ ๏ธ
-Wno-analyzer-possible-null-argumentโ ๐ค needs-fanalyzer, and-Wno-analyzer-possible-null-argumentsilences it. This one warns on paths where a possibly-NULLvalue gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULLvalue.- 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โ ๐ซฃ requires-fanalyzer, and-Wno-analyzer-possible-null-dereferenceturns it off. It warns on paths where a possibly-NULLvalue 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โ ๐ซ needs-fanalyzer, and-Wno-analyzer-null-argumentis the mute button. It warns on paths where a value known to beNULLgets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULLvalue.- See CWE-476: NULL Pointer Dereference (
https://cwe.mitre.org/data/definitions/476.html).
- See CWE-476: NULL Pointer Dereference (
-Wno-analyzer-null-dereferenceโ ๐ฅ requires-fanalyzer, and-Wno-analyzer-null-dereferenceshuts it up. It warns on paths where a value known to beNULLgets 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โ ๐ฟ needs-fanalyzer, and-Wno-analyzer-putenv-of-auto-varis the off switch. It warns on paths where a call toputenvgets 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โ โ requires-fanalyzer, and-Wno-analyzer-shift-count-negativeturns it off. It warns on paths where a shift is attempted with a negative count. It's the analyzer's cousin of-Wshift-count-negative, which lives in the C/C++ front ends. The difference is that this one works by analyzing interprocedural paths instead of just parsing the syntax tree. Heads up though: the analyzer doesn't prioritize finding these paths, so false negatives are more likely compared to other warnings ๐ฅบ-Wno-analyzer-shift-count-overflowโ ๐ needs-fanalyzer, and-Wno-analyzer-shift-count-overflowsilences it. It warns on paths where a shift is attempted with a count greater than or equal to the precision of the operand's type. It's the analyzer's version of-Wshift-count-overflowfrom the C/C++ front ends, but it works by analyzing interprocedural paths rather than just parsing the syntax tree. Same catch as before: the analyzer doesn't prioritize detecting these paths, so false negatives are more likely relative to other warnings.-Wno-analyzer-stale-setjmp-bufferโ ๐ฐ๏ธ requires-fanalyzer, and-Wno-analyzer-stale-setjmp-bufferis the mute option. It warns on paths wherelongjmpgets called to rewind to ajmp_buftied to asetjmpcall in a function that has already returned. That's a stale buffer, and jumping into it is a whole mess ๐ตโ๐ซ
The analyzer has a sneaky habit of checking whether a setjmp rewind point is still alive. When setjmp is called on a jmp_buf to record a rewind location, it records the stack frame. That frame becomes invalid once the function containing the setjmp call returns. Trying to rewind to it with longjmp would point at a stack frame that no longer exists, which likely leads to a crash (or worse) ๐ญ๐ซฃ
-Wno-analyzer-tainted-allocation-sizeโ โจ this one needs-fanalyzerto turn it on, and you can silence it with-Wno-analyzer-tainted-allocation-size. It flags 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 cause a denial of service ๐ โโ๏ธ
Check out CWE-789: Memory Allocation with Excessive Size Value ("https://cwe.mitre.org/data/definitions/789.html").
-Wno-analyzer-tainted-assertionโ ๐ฆ also needs-fanalyzer, and you turn it off with-Wno-analyzer-tainted-assertion. It warns about paths where an unsanitized, attacker-controllable value is part of a condition, and that condition guards a call to a function marked with attributenoreturn(like__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, two things can happen:
- when assertion-checking is enabled, an attacker could trigger a denial of service by injecting an assertion failure
- when assertion-checking is disabled (say, 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 strips the assertions out 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. The optimizer sometimes removes these functions 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 catch problematic constructions like this one:
switch (some_tainted_value) {
case 0:
/* [...etc; various valid cases omitted...] */
break;
default:
__builtin_unreachable (); /* BUG: attacker can trigger this */
}
Strictly speaking that's not an assertion failure, but the warning still shows up for it ๐
-Wno-analyzer-tainted-array-indexโ ๐ธ requires-fanalyzerto enable, and-Wno-analyzer-tainted-array-indexswitches it off. It flags paths where an attacker-controllable value is used as an array index without 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").
-Wno-analyzer-tainted-divisorโ ๐ง needs-fanalyzeron, and you can turn it off with-Wno-analyzer-tainted-divisor. It warns about paths where an unsanitized, attacker-controllable value is used as the divisor in a division or modulus operation, which means an attacker could inject a division-by-zero.
See CWE-369: Divide By Zero ("https://cwe.mitre.org/data/definitions/369.html").
-Wno-analyzer-tainted-offsetโ ๐ requires-fanalyzer, and-Wno-analyzer-tainted-offsetdisables it. It warns about 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").
-Wno-analyzer-tainted-sizeโ ๐ needs-fanalyzerto be on, and you disable it with-Wno-analyzer-tainted-size. It warns about paths where an unsanitized, attacker-controllable value is used as the size of an operation such asmemset, 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").
-Wno-analyzer-undefined-behavior-ptrdiffโ โญ requires-fanalyzer, and you silence it with-Wno-analyzer-undefined-behavior-ptrdiff. It flags paths where a pointer subtraction happens between pointers that refer to different chunks of memory. That code leans on undefined behavior, because pointer subtraction is only defined when both pointers point within (or just past) the same array ๐
See CWE-469: Use of Pointer Subtraction to Determine Size ("https://cwe.mitre.org/data/definitions/469.html").
-Wno-analyzer-undefined-behavior-strtokโ ๐ requires-fanalyzer, and-Wno-analyzer-undefined-behavior-strtokturns it off. It warns about paths where a call tostrtokhas undefined behavior. Specifically, passing NULL as the first parameter for the initial call tostrtokwithin a process has undefined behavior.-Wno-analyzer-unsafe-call-within-signal-handlerโ ๐ซถ requires-fanalyzer, and you can disable it with-Wno-analyzer-unsafe-call-within-signal-handler. 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").
-Wno-analyzer-use-after-freeโ ๐ needs-fanalyzeron, and-Wno-analyzer-use-after-freeswitches it off. It warns about paths where a pointer gets used after a deallocator has been called on it. A deallocator here is eitherfree, or a deallocator referenced by attributemalloc.
See CWE-416: Use After Free ("https://cwe.mitre.org/data/definitions/416.html").
-Wno-analyzer-use-of-pointer-in-stale-stack-frameโ ๐ requires-fanalyzer, and you can turn it off with-Wno-analyzer-use-of-pointer-in-stale-stack-frame. It warns about paths where a pointer is dereferenced and points to a variable in a stale stack frame.-Wno-analyzer-va-arg-type-mismatchโ ๐ needs-fanalyzer, and-Wno-analyzer-va-arg-type-mismatchdisables it. It warns about interprocedural paths where the analyzer detects an attempt to useva_argto extract a value passed to a variadic call, but with a type that 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").
-Wno-analyzer-va-list-exhaustedโ ๐ฆ requires-fanalyzerto enable, and you disable it with-Wno-analyzer-va-list-exhausted. It warns about interprocedural paths where the analyzer sees 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").
-Wno-analyzer-va-list-leakโ ๐ธ needs-fanalyzer, and-Wno-analyzer-va-list-leakturns it off. It warns about 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โ ๐ requires-fanalyzer, and you silence it with-Wno-analyzer-va-list-use-after-va-end. It warns about interprocedural paths where ava_listgets used afterva_endhas been called on it. "va_list".-Wno-analyzer-write-to-constโ ๐ง needs-fanalyzeron, and-Wno-analyzer-write-to-constdisables it. It warns about paths where the analyzer detects an attempt to write through a pointer to aconstobject. Heads up though: the analyzer doesn't prioritize catching these paths, so false negatives are more likely compared to other warnings ๐ฅบ-Wno-analyzer-write-to-string-literalโ ๐ requires-fanalyzer, and-Wno-analyzer-write-to-string-literalswitches it off. It warns about paths where the analyzer detects an attempt to write through a pointer to a string literal. Same deal as above: the analyzer doesn't prioritize these paths, so false negatives are more likely compared to other warnings.-Wno-analyzer-use-of-uninitialized-valueโ ๐ needs-fanalyzerto be enabled, and you can disable it with-Wno-analyzer-use-of-uninitialized-value. It warns about paths where an uninitialized value gets used.
See CWE-457: Use of Uninitialized Variable ("https://cwe.mitre.org/data/definitions/457.html").
The analyzer has hardcoded knowledge about the behavior of the following memory-management functions:
okay so the analyzer already knows a whole squad of memory functions, bestie ๐ง and it's giving very specific vibes with each one:
"alloca"- The built-in functions
"__builtin_alloc","__builtin_alloc_with_align",@item "__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" "calloc""free""malloc""memset""operator delete""operator delete []""operator new""operator new []""realloc""strdup""strndup"
It also knows these file descriptor functions, which are so iconic ๐ธ
"open""close""creat""dup","dup2", and"dup3""isatty""pipe", and"pipe2""read""write""socket","bind","listen","accept", and"connect"
Then there's the <stdio.h> stream crew ๐ which is a whole mood:
- 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" "fopen""fclose""ferror""fgets""fgets_unlocked""fileno""fread""getc""getchar""fprintf""printf""fwrite"
And of the following functions too, periodt ๐
- 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
"error"and"error_at_line" "getpass""longjmp""putenv""setjmp""siglongjmp""signal""sigsetjmp""strcat""strchr""strlen"
Also, any function with an "__analyzer_" prefix has special meaning to the analyzer ๐ฎ and that's all written up in the GCC Internals manual. no cap, go read it if you're curious โจ
Pertinent parameters for controlling the exploration are these four bad boys ๐
--param analyzer-bb-explosion-factor=value--param analyzer-max-enodes-per-program-point=value--param analyzer-max-recursion-depth=value--param analyzer-min-snodes-for-call-summary=value
The following options control the analyzer ๐
-fanalyzer-call-summariesโ okay this one simplifies interprocedural analysis by computing the effect of certain calls, instead of exploring every single path through the function from the callsite to each possible return. It's giving efficiency ๐ง If enabled, call summaries are only used for functions with more than one call site, and that are sufficiently complicated (as per--param analyzer-min-snodes-for-call-summary=value).-fanalyzer-checker=nameโ restricts the analyzer to run just the named checker, and enables it too ๐ฏ-fanalyzer-debug-text-art-headingsโ this one is for the analyzer developers ๐ ๏ธ If enabled, the analyzer adds extra annotations to any diagrams it generates.-fno-analyzer-feasibilityโ also for analyzer developers. By default the analyzer checks that there is a feasible control flow path for each diagnostic it emits, meaning the conditions that hold are not mutually exclusive. Diagnostics where no feasible path can be found get rejected ๐ โโ๏ธ This filtering can be suppressed with-fno-analyzer-feasibility, for debugging issues in this code.-fanalyzer-fine-grainedโ developer-only vibes ๐งช Internally the analyzer builds an "exploded graph" that combines control flow graphs with data flow information. By default, an edge in this graph can contain the effects of a run of multiple statements within a basic block. With-fanalyzer-fine-grained, each statement gets its own edge.-fanalyzer-show-duplicate-countโ another developer one ๐ If multiple diagnostics have been detected as duplicates of each other, it emits a note when reporting the best diagnostic, giving the number of additional diagnostics that were suppressed by the deduplication logic.-fanalyzer-show-events-in-system-headersโ by default the analyzer hides events fully located within a system header so the diagnostic paths stay simplified โจ With-fanalyzer-show-events-in-system-headers, those events stop getting suppressed.-fno-analyzer-state-mergeโ developer-only ๐ซถ By default the analyzer tries to simplify things by merging sufficiently similar states at each program point as it builds its "exploded graph". With-fno-analyzer-state-mergethis merging can be suppressed, for debugging state-handling issues.-fno-analyzer-state-purgeโ developer-only ๐งน By default the analyzer purges aspects of state at a program point that appear to no longer be relevant, e.g. the values of locals that aren't accessed later in the function and which aren't relevant to leak analysis. With-fno-analyzer-state-purgethis purging can be suppressed, for debugging state-handling issues.-fno-analyzer-suppress-followupsโ developer-only ๐ By default the analyzer stops exploring an execution path after encountering certain diagnostics, so it doesn't spam a cascade of follow-up diagnostics. The diagnostics that terminate 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 such paths even after those diagnostics, which may be helpful for debugging issues in the analyzer, or for microbenchmarks for detecting undefined behavior.
-fanalyzer-transitivityโ enables transitivity of constraints within the analyzer ๐-fno-analyzer-undo-inliningโ developer-only ๐ฆ-fanalyzerruns relatively late compared to other code analysis tools, and some optimizations have already been applied to the code. In particular, function inlining may have occurred, so 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 to emit events showing the inlined calls. With-fno-analyzer-undo-inliningthis attempt to reconstruct the original frame information gets disabled, which may help when debugging issues in the analyzer.-fanalyzer-verbose-edgesโ developer-only ๐ It enables more verbose, lower-level detail in the descriptions of control flow within diagnostic paths.-fanalyzer-verbose-state-changesโ developer-only ๐ It enables more verbose, lower-level detail in the descriptions of events relating to state machines within diagnostic paths.-fanalyzer-verbosity=levelโ controls how complex the control flow paths emitted for analyzer diagnostics are ๐ The level can be one of:0โ at this level, interprocedural call and return events are displayed, along with the most pertinent state-change events relating to a diagnostic. For example, for a double-"free" diagnostic, both calls to "free" will be shown.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 events relating to control flow that are significant to triggering the issue (e.g. "true path taken" at a conditional). This level is the default ๐3โ same as the previous level, but shows all control flow events, not just significant ones.4โ developer-only ๐ ๏ธ this level adds various other events intended 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 suitable for viewing with GraphViz tofile.callgraph.dot๐บ๏ธ-fdump-analyzer-exploded-graphโ dumps a representation of the "exploded graph" suitable for viewing with GraphViz tofile.eg.dot. Nodes are color-coded based on state-machine states to emphasize state changes ๐-fdump-analyzer-exploded-nodesโ emits diagnostics showing where nodes in the "exploded graph" are 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, asfile.eg-id.txt. This is typically a large number of dump files, so brace yourself ๐ญ-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 viewing with GraphViz, to filenames of the formfile.*.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 viewing with GraphViz, to filenames of the formfile.*.infinite-loop.dotโพ๏ธ-fdump-analyzer-jsonโ dumps a compressed JSON representation of analyzer internals tofile.analyzer.json.gz. The precise format is subject to change, so don't build your life around it ๐ซ
Okay so the analyzer dumps are next, bestie ๐ ๐ซถ
-fdump-analyzer-state-purgeโ ๐ฎ Same deal as-fdump-analyzer-supergraph, but this one annotates the "supergraph" with what state gets purged at each node. It's written tofile.state-purge.dot, and you view it with GraphViz.-fdump-analyzer-supergraphโ ๐บ๏ธ Dumps the "supergraph" for GraphViz intofile.supergraph.dotandfile.supergraph-eg.dot. It shows every control flow graph in the program, with interprocedural edges for calls and returns. The second dump is the glow-up: it has annotations for nodes in the "exploded graph" plus any diagnostics tied to them โจ-fdump-analyzer-untrackedโ ๐ ๏ธ Emits custom warnings packed with internal details. This one is for the analyzer developers, not us mortals ๐
๐ Options for Debugging Your Program
Okay so if you want GCC to throw extra info at your debugger, you literally only need to add -g to your other options in almost every case ๐ซถ Some debug formats can co-exist (like DWARF with CTF) as long as you enable each one explicitly with its own option.
-g with -O is allowed!! But the shortcuts optimized code takes can be lowkey surprising ๐ Some variables you declared might not exist at all, control flow might jump somewhere you didn't expect, some statements won't run because they compute constant results or their values are already at hand, and some statements might execute in different places because they got moved out of loops. Still, you can debug optimized output, so it's reasonable to use the optimizer for programs that might have bugs ๐ฅ
If you aren't using some other optimization option, consider -Og with -g. With no -O option at all, some compiler passes that collect debugging info don't run, so -Og might give you a better debugging experience โจ
-gโ ๐ Produces debugging info in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can read this.
On most systems that use stabs, -g turns on extra info that only GDB can use. That makes debugging in GDB way better, but other debuggers might crash or refuse to read the program ๐ญ If you want to be certain about whether the extra info gets generated, use -gvms (see below).
-ggdbโ ๐ Produces debugging info for GDB. It uses the most expressive format available (DWARF, stabs, or the native format if neither of those are supported), and it includes GDB extensions whenever possible.-gdwarf,-gdwarf-versionโ ๐ธ Produces debugging info in DWARF format (if your target supports it). version can be 2, 3, 4 or 5. The default is 5 for most targets, except VxWorks, TPF and Darwin / macOS, which default to 2, and AIX, which defaults to 4.
Heads up: 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-assignments for the maximum benefit. Version 5 needs GDB 8.0 or higher.
GCC no longer supports DWARF Version 1, which is substantially different from Version 2 and later. For historical reasons, some other DWARF-related options such as -fno-dwarf2-cfi-asm) keep a reference to DWARF Version 2 in their names, but they apply to all currently supported versions of DWARF.
-gbtfโ ๐ฆ Requests BTF debug info. BTF is the default debugging format for the eBPF target. On other targets, like x86, BTF debug info can be generated along with DWARF debug info when both formats are enabled explicitly through their respective command line options.-gprune-btf,-gno-prune-btfโ โ๏ธ Prunes BTF info before it's 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. On top of that, 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 those types were only present in the input as forward declarations.
This option substantially shrinks the BTF info, but you lose a lot of detailed type info in the process. It's mainly useful for the BPF target, to minimize the size of the object and drop BTF info that isn't immediately relevant to the BPF program loading process ๐
This option is enabled by default for the BPF target when generating BTF info.
-gctf,-gctflevelโ ๐งฉ Requests CTF debug info, and level tells GCC how much CTF info to produce. If you use-gctfwithout a value for level, the default level is 2.
CTF debug info can be generated along with DWARF debug info when both formats are enabled explicitly through their respective command line options.
- Level 0 produces no CTF debug info at all, so
-gctf0negates-gctf. - Level 1 produces CTF info for tracebacks only. This includes callsite info, but no type info.
- Level 2 produces type info for entities (functions, data objects etc.) at file-scope or global-scope only.
-gvmsโ ๐ฅ๏ธ Produces debugging info in Alpha/VMS debug format (if supported). This is the format DEBUG uses on Alpha/VMS systems.-gcodeviewโ ๐ช Produces debugging info in CodeView debug format (if supported). This is the format Microsoft Visual C++ uses on Windows.-glevel,-ggdblevel,-gvmslevelโ ๐๏ธ Requests debugging info and uses level to decide how much. The default level is 2.- Level 0 produces no debug info at all, so
-g0negates-g. - Level 1 produces minimal info, enough for backtraces in parts of the program you don't plan to debug. This includes descriptions of functions and external variables, plus line number tables, but no info about local variables.
- Level 3 includes extra info, like all the macro definitions present in the program. Some debuggers support macro expansion when you use
-g3.
- Level 0 produces no debug info at all, so
If you use multiple -g options, with or without level numbers, the last one is the one that takes effect ๐
-gdwarf doesn't accept a concatenated debug level, to avoid confusion with -gdwarf-level. Instead, use an additional -glevel option to change the debug level for DWARF.
-fno-eliminate-unused-debug-symbolsโ ๐ By default, no debug info is produced for symbols that aren't actually used. Use this option if you want debug info for all symbols.-femit-class-debug-alwaysโ ๐ Instead of emitting debugging info for a C++ class in only one object file, this emits it in all object files that use the class. Only use this with debuggers that can't handle how GCC normally emits class debug info, because it can make the debug info up to a factor of two bigger ๐ฌ-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 shrinks the debug info in the output file but makes link processing take longer. Merging is enabled by default.-fdebug-prefix-map=old=new โ ๐บ๏ธ When compiling files in directory old, records debugging info as if the files lived in directory new instead. This is handy for swapping a build-time path for an install-time path in the debug info. You can also use it to change an absolute path to a relative one by using.for new. It can give more reproducible, location-independent builds, but you may 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, which works out where variables are stored at each position in the code. Better debug info gets generated (if the format supports it).
It's enabled by default when you compile with optimization (-Os, -O, -O2, ...), debugging info (-g), and a debug info format that 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 enabled even when var-tracking is disabled. In that case the annotations are created and maintained, but discarded at the end. By default this flag is enabled together with -fvar-tracking, except when selective scheduling is enabled.
-gsplit-dwarfโ ๐ฆ If DWARF debug info is enabled, this separates as much of it as possible into a separate output file with the extension.dwo. This lets your build system avoid linking files with 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 DWARF format. The default is target specific, though on most targets it's-gdwarf32. The 32-bit format is smaller but can't hold more than 2GiB of debug info in any of the DWARF debug info sections. The 64-bit format allows larger debug info, but 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โ Okay so this one makes DWARF".debug_pubnames"and".debug_pubtypes"sections. ๐-ggnu-pubnamesโ This makes".debug_pubnames"and".debug_pubtypes"sections too, but in a format that's ready to be turned into a GDB index. Heads up, it's only useful if your linker can produce GDB index version 7. ๐ฅ-fdebug-types-sectionโ When you're on DWARF Version 4 or higher, type DIEs can get their own".debug_types"section instead of living inside".debug_info". It's more efficient in a separate comdat section, since the linker can then remove duplicates โจ. BUT not every DWARF consumer supports".debug_types"yet, and on some objects it makes the debug info bigger instead of smaller ๐.-grecord-gcc-switches,-gno-record-gcc-switchesโ This one tacks the command-line options that might affect code generation onto theDW_AT_producerattribute in your DWARF debug info ๐ง. The options get joined with spaces, separating them from each other and from the compiler version. It's on by default. See also-frecord-gcc-switchesfor another way to stash compiler options in the object file.-gstrict-dwarfโ Bans using extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ โโ๏ธ. On most targets, using non-conflicting extensions from later versions is actually allowed.-gno-strict-dwarfโ Lets you use extensions from a later DWARF standard version than the one picked with-gdwarf-version๐ฆ.-gas-loc-supportโ Tells the compiler that the assembler supports".loc"directives, so it can use them to have the assembler generate DWARF2+ line number tables ๐ธ. This is usually the move, because assembler-generated line-number tables are a lot more compact than the ones the compiler makes itself. This option turns on by default if, at GCC configure time, the assembler was found to support those directives.-gno-as-loc-supportโ Forces GCC to generate DWARF2+ line number tables internally, if those tables are going to be generated at all ๐.-gas-locview-supportโ Tells the compiler that the assembler supports"view"assignment and reset assertion checking in".loc"directives ๐. This turns on by default if the assembler was found to support them at GCC configure time.-gno-as-locview-supportโ Forces GCC to assign view numbers internally, if-gvariable-location-viewsis explicitly requested ๐ .-gcolumn-info,-gno-column-infoโ Puts location column information into DWARF debug info, not just the file and line ๐. Enabled by default.-gstatement-frontiers,-gno-statement-frontiersโ This makes GCC drop markers into the internal representation at the start of statements, and keeps them roughly in place through the whole compilation โญ. Those markers then guide the output of"is_stmt"markers in the line number table. It's enabled 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โ Augments variable location lists with progressive view numbers implied from the line number table ๐. This lets debug info consumers inspect state at certain points in the program, even when no instructions tied to the corresponding source locations are there. If the assembler doesn't support view numbers in line number tables, this makes the compiler emit the line number table, which makes them 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, but they won't get any benefit from them either.
This is enabled by default when outputting DWARF 2 debug info at the normal level, as long as there's assembler support, -fvar-tracking-assignments is enabled, and -gstrict-dwarf is not. When assembler support isn't available, it may still be enabled, but that forces GCC to output internal line number tables. And if -ginternal-reset-location-views isn't enabled, that will most certainly lead to silently mismatching location views ๐ญ.
There's a proposed representation for view numbers 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, and they'd be unable to decode location lists that use it.
โ ๏ธ Heads up bestie: -gvariable-location-views=incompat5 is NOT backward compatible with the DWARF 5 location list format, and debug info consumers aren't expected to support it. They'd literally be unable to decode the location lists. Only reach for it if you're experimenting with the reference implementation ๐.
-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 needs the compiler to have very accurate insn length estimates, which isn't always the case. It may also silently generate incorrect view lists when you're using an assembler that doesn't support location view lists. The GNU assembler will flag any such error as a"view number mismatch". This is 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 get 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 ๐๏ธ. If type isn't given, the default depends on what the assembler and linker are capable of. type can be one ofnone(don't compress debug sections) orzlib(use zlib compression in ELF gABI format). If the linker doesn't support writing compressed debug sections, the option gets 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 there's a 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 is 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 which struct-like types the compiler generates debug info for ๐งฉ. The goal is to cut down on duplicate struct debug info between different object files in the same program. This is the detailed version of-femit-struct-debug-reducedand-femit-struct-debug-baseonly, and it covers most needs.
A specification uses 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 come through pointers to structs. In other words, when use of an incomplete struct is valid, the use is indirect. An example is struct one direct; struct 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-detailed doesn't implement them yet.
The third word specifies the source files for those structs that the compiler should emit debug info for. The values none and any have their normal meaning. The value base means the base of the name of the file where the type declaration appears must match the base of the name of the main compilation file. In practice, this means that when compiling foo.c, debug info is generated for types declared in that file and foo.h, but not other header files. The value sys means those types satisfying base, or declared in system or compiler headers.
You may need to experiment to find 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_frame"section, 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 you want debug info for all types declared in a compilation unit, whether or not they're actually used there. For example, you might want to cast a value to a type that's declared but not actually used in your program, right in the debugger. Honestly though, this usually just results in a significant amount of wasted space ๐ .
๐ธ Options That Control Optimization ๐ธ
These options control various sorts of optimizations. โจ
Okay so with no optimization flag at all, the compiler's whole vibe is cutting compile time and making debugging act right ๐ Statements stay independent, which means if you pause at a breakpoint between statements, you can give any variable a new value or jump the program counter to any other statement in the function and get exactly what the source code promised โจ
Turning on optimization flags is a total glow-up for performance and/or code size ๐ฆ but it costs you compilation time and maybe your ability to debug the program ๐ฅฒ
The compiler optimizes based on what it knows about your program ๐ง Compiling multiple files at once into a single output file lets it use info from all of those files while it works on each one, which is so iconic ๐
Not every optimization has its own flag, btw ๐ Only the ones that do have a flag get listed in this section.
Most optimizations are fully switched off at -O0, or whenever no -O level is set on the command line, even if you add individual optimization flags ๐ And -Og suppresses a bunch of optimization passes too, so keep that in mind.
Which exact set of optimizations gets enabled at each level can change depending on the target and how GCC was configured ๐ If you want the real list for your setup, invoke GCC with -Q --help=optimizers and it'll spill every enabled optimization at each level ๐ซถ
โจ -O levels โจ
-O,-O1โ Optimize! This takes a bit more time to compile, and a lot more memory for a big function ๐ง
With -O, the compiler tries to shrink code size and speed up execution, but it skips any optimization that eats a ton of compile time ๐
-O is the recommended level for large machine-generated code, because it's the sensible middle ground between compile time and memory use. Higher levels run optimizations with more algorithmic complexity than -O does ๐ซถ
-O turns on these optimization 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 runs nearly every supported optimization that doesn't involve a space-speed tradeoff. Compared to-O, this one increases both compilation time and the performance of the generated code ๐
-O2 turns on every optimization flag that -O1 does. It also turns on these:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fcaller-saves -fcode-hoisting -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -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 -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
Please note the warning under -fgcse about invoking -O2 on programs that use computed gotos. โ ๏ธ
NOTE: In Ubuntu 8.10 and later versions, -D_FORTIFY_SOURCE=2 is set by default, and in Ubuntu 24.04 and later versions, -D_FORTIFY_SOURCE=3 is set by default. Either one is activated when -O is set to 2 or higher ๐ก๏ธ It turns on extra compile-time and run-time checks for several libc functions. To turn it off, specify either -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0.
NOTE: In Debian 13 and Ubuntu 24.04 and later versions, -D_TIME_BITS=64 together with -D_FILE_OFFSET_BITS=64 is set by default on the 32bit architectures armel, armhf, hppa, m68k, mips, mipsel, powerpc and sh4 ๐ธ
-O3โ Optimize yet more ๐-O3turns on everything-O2does, plus these:
-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, bestie.
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 ๐
โโ๏ธ A lot of the optimizations GCC does depend on code analysis or canonicalization passes that only -O turns on, so running individual passes in isolation wouldn't be useful anyway.
-Osโ Optimize for size ๐งธ-Osenables all the-O2optimizations except the ones that often make code bigger:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, makes the compiler tune for code size instead of execution speed, and runs extra optimizations designed to shrink code ๐
-Ofastโ Disregard strict standards compliance ๐ค-Ofastenables all-O3optimizations, plus 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-sizeis specified), and-fno-protect-parens. It turns off-fsemantic-interposition๐-Ogโ Optimize the debugging experience ๐-Ogshould be your go-to level for the standard edit-compile-debug cycle. It offers a reasonable amount of optimization while keeping compilation fast and debugging smooth ๐ซถ It's a better pick than-O0for debuggable code, because some compiler passes that collect debug information are disabled at-O0.
Like -O0, -Og completely disables a number of optimization passes, so the individual options that control them have no effect. Otherwise, -Og enables all the -O1 optimization flags except the ones that can get in the way of 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.-Ozbehaves similarly to-Os, including enabling most-O2optimizations.
If you use multiple -O options, with or without level numbers, the last one is the one that takes effect ๐
โจ -f flags โจ
Options of the form -fflag are machine-independent flags ๐ฆ Most flags have both a positive and a negative form, and the negative form of -ffoo is -fno-foo. The table below only lists one of the forms, the one you'll typically use. You can figure out the other one by either removing no- or adding it ๐
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" the optimizations to be performed is needed ๐ฏ
-fno-defer-popโ For machines that have to pop arguments after a function call, this always pops the arguments as soon as each function returns ๐งน At-O1and higher,-fdefer-popis the default, which lets the compiler let arguments pile up on the stack across several function calls and pop them all at once.-fforward-propagateโ Performs 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 run, and the second one is scheduled after loop unrolling.
This option is enabled by default at optimization levels -O1, -O2, -O3, -Os.
-favoid-store-forwarding,-fno-avoid-store-forwardingโ Many CPUs stall for many cycles when a load partially depends on previous smaller stores ๐ฉ This pass tries to detect 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=offdisables floating-point expression contraction.-ffp-contract=fastenables it, such as forming fused multiply-add operations when 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.
-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 does nothing, 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 so this one is ๐ฅ. GCC hunts down loops that do CRC calculations (that polynomial long division thing) and swaps them for a much faster version. It can spot 8, 16, 32, and 64 bit CRCs with a constant polynomial that doesn't include the leading 1 bit, in both bit-forward and bit-reversed flavours. If your target has a CRC instruction and the polynomial in your code matches the one that instruction uses, GCC generates that instruction. If not, but the target has a carry-less-multiplication instruction, it generates CRC with that. Otherwise, it falls back to a table-based CRC. ๐
Enabled by default at -O2 and higher. โจ
-foptimize-sibling-callsโ optimizes sibling and tail recursive calls. Main character energy ๐
Enabled at levels -O2, -O3, -Os. ๐ธ
-foptimize-strlenโ makes various standard C string functions (like"strlen","strchr"or"strcpy") and their"_FORTIFY_SOURCE"counterparts run faster by swapping in quicker alternatives. ๐ง
Enabled at levels -O2, -O3. ๐ซถ
-finline-stringops[=fn]โ expands memory and string operations inline (for now, only"memset"), even when the length is variable or big enough that it'd normally need a loop. This is most useful alongside-ffreestandingand-fno-builtin. ๐
Sometimes it can use known alignment and length multipliers to make nicer code, but even then it might be less efficient than optimized runtime implementations. It can also bloat your code size so much that a slower but shared implementation actually runs faster, thanks to better use of code caches. ๐ญ This option is disabled by default.
-fno-inlineโ don't expand any functions inline, except the ones marked with the"always_inline"attribute. This is the default when you're not optimizing. ๐
You can exempt individual functions from inlining by marking them with the "noinline" attribute. ๐ฆ
-finline-small-functionsโ integrates functions into their callers when their body is smaller than the code for the function call itself, so the overall program gets smaller. GCC heuristically decides which functions are simple enough to be worth it. This applies to all functions, even ones not declared inline. โจ
Enabled at levels -O2, -O3, -Os. ๐
-findirect-inliningโ also inlines indirect calls that become known at compile time thanks to earlier inlining. This only has an effect when inlining is turned on by-finline-functionsor-finline-small-functions. ๐ฅ
Enabled at levels -O2, -O3, -Os. ๐
-finline-functionsโ considers all functions for inlining, even if they aren't declared inline. GCC heuristically decides which ones are worth integrating. ๐ง
If every call to a given function gets integrated and the function is declared "static", then it's normally not output as assembler code on its own. Iconic. ๐
Enabled at levels -O2, -O3, -Os. Also enabled by -fprofile-use and -fauto-profile. ๐
-finline-functions-called-onceโ considers all"static"functions that get called once for inlining into their caller, even if they aren't marked"inline". If the call gets integrated, the function isn't output as assembler code by itself. ๐
Enabled at levels -O1, -O2, -O3 and -Os, but not -Og. ๐
-fearly-inliningโ inlines functions marked by"always_inline", plus functions whose body seems smaller than the function call overhead, early, before the-fprofile-generateinstrumentation and the real inlining pass. Doing this makes profiling way cheaper and usually makes inlining faster for programs with big 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, -O3 and -Os. ๐
-finline-limit=nโ by default GCC limits the size of functions that can be inlined. This flag gives you coarse control over that limit. n is the size of functions that can be inlined, measured in pseudo instructions. ๐ง
Inlining is actually controlled by a bunch of parameters, which you can set one at a time with --param name=value. The -finline-limit=n option sets some of them like this:
max-inline-insns-singleโ is set ton/2.max-inline-insns-autoโ is set ton/2.
See below for documentation on the individual parameters controlling inlining and for their defaults. ๐ซถ
Note: there may be no value of -finline-limit that results in default behavior. ๐
Note: "pseudo instruction" here is just an abstract measurement of a function's size. It in no way counts assembly instructions, so its exact meaning might change from one release to another. ๐
-fno-keep-inline-dllexportโ a more fine-grained version of-fkeep-inline-functions, which 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 they've been inlined into all of their 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 they aren't referenced. ๐
GCC enables this one by default. If you want the compiler to check whether a variable is referenced, regardless of optimization, use -fno-keep-static-consts. ๐
-fmerge-constantsโ tries to merge identical constants (string constants and floating-point constants) across compilation units. ๐ซถ
This is the default for optimized compilation if the assembler and linker support it. Use -fno-merge-constants to stop this from happening. Enabled at levels -O1, -O2, -O3, -Os. โจ
-fmerge-all-constantsโ tries to merge identical constants and identical variables. ๐ฅ
This option implies -fmerge-constants. On top of that, it also considers things like constant initialized arrays, or initialized constant variables with integral or floating-point types. Careful, bestie! C and C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations, so using this option results in non-conforming behavior. ๐
-fmodulo-schedโ performs swing modulo scheduling right before the first scheduling pass. It looks at innermost loops and reorders their instructions by overlapping different iterations. ๐ง-fmodulo-sched-allow-regmovesโ performs 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 only works when -fmodulo-sched is also enabled. ๐ธ
-fno-branch-count-regโ disables the optimization pass that looks 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 only matters on architectures that support those instructions, which include x86, PowerPC, IA-64 and S/390. ๐
Heads up: -fno-branch-count-reg doesn't remove decrement and branch instructions that other optimization passes already put into the instruction stream. ๐
The default is -fbranch-count-reg at -O1 and higher, except for -Og. ๐
-fno-function-cseโ doesn't put function addresses in registers. Instead, every instruction that calls a constant function contains the function's address explicitly. ๐
This gives you less efficient code, but some strange hacks that alter the assembler output might get confused by the optimizations performed when this option is not used. ๐ญ
The default is -ffunction-cse
-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 it. ๐ซถ
The default is -fzero-initialized-in-bss except in Ada. ๐
-fthread-jumpsโ performs optimizations that check whether a jump branches to a location where another comparison, subsumed by the first, is found. If so, the first branch gets redirected to either the destination of the second branch or a point right after it, depending on whether the condition is known to be true or false. ๐ง
Enabled at levels -O1, -O2, -O3, -Os. ๐ธ
-fsplit-wide-typesโ when using a type that occupies multiple registers, like"long long"on a 32-bit system, GCC splits the registers apart and allocates them independently. This usually generates better code for those types, but it may make debugging harder. ๐ฅ
Enabled at levels -O1, -O2, -O3, -Os. ๐
-fsplit-wide-types-earlyโ fully splits wide types early, instead of very late. This option does nothing unless-fsplit-wide-typesis turned on. ๐
This is the default on some targets. ๐
-fcse-follow-jumpsโ during common subexpression elimination (CSE), scans through jump instructions when the jump's target isn't reached by any other path. For example, when CSE meets an"if"statement with an"else"clause, it follows the jump when the condition tested is false. ๐
Enabled at levels -O2, -O3, -Os. ๐
-fcse-skip-blocksโ similar to-fcse-follow-jumps, but this makes CSE follow jumps that conditionally skip over blocks. When CSE meets a simple"if"statement with no"else"clause,-fcse-skip-blocksmakes CSE follow the jump around the body of the"if". ๐ฆ
Okay so this next batch is all about the -f flags that squeeze extra juice out of your code ๐งโจ Keep reading, bestie, it's giving optimization main character energy ๐
Enabled at levels -O2, -O3, -Os. ๐ธ
-frerun-cse-after-loopโ okay so this one re-runs common subexpression elimination after the loop optimizations are done, because why not do it twice, periodt ๐
Enabled at levels -O2, -O3, -Os. ๐
-fgcseโ this one runs a global common subexpression elimination pass ๐ฅ It also handles global constant and copy propagation too, so it's pulling double duty.
Note: if you're compiling a program that uses computed gotos (a GCC extension, not standard C, so be aware ๐), you might get better run-time performance by turning off this pass. Just add -fno-gcse to your command line.
Enabled at levels -O2, -O3, -Os. โจ
-fgcse-lmโ when this one is on, global common subexpression elimination tries to move loads that only get killed by stores into themselves ๐ง That means a loop with a load/store sequence can be rearranged so the load happens outside the loop, and a copy/store happens inside it.
Enabled by default when -fgcse is enabled. ๐ฆ
-fgcse-smโ this one turns on a store motion pass after global common subexpression elimination ๐ It tries to pull stores out of loops. Team it up with-fgcse-lmand loops with a load/store sequence can become a load before the loop and a store after it, iykyk ๐ซถ
Not enabled at any optimization level. ๐
-fgcse-lasโ with this one on, the global common subexpression elimination pass gets rid of redundant loads that come right after stores to the same memory location. It catches both partial and full redundancies, so it's thorough af ๐
Not enabled at any optimization level. ๐
-fgcse-after-reloadโ when enabled, this one runs a redundant load elimination pass after reload ๐งน Its whole purpose is to clean up redundant spilling, very much a tidy-up girl.
Enabled by -O3, -fprofile-use and -fauto-profile. โญ
-faggressive-loop-optimizationsโ this one tells the loop optimizer to use language constraints to work out bounds for the number of iterations of a loop ๐ง It assumes your loop code doesn't invoke undefined behavior, like causing signed integer overflows or out-of-bound array accesses. Those bounds then guide loop unrolling, loop 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) might later be overridden with longer trailing arrays ๐ Because of that, it stops certain optimizations that depend on knowing the array bounds. Bit of a trade-off, bestie.-fcrossjumpingโ this performs the cross-jumping transformation, which unifies equivalent code and saves code size ๐ฆ Heads up though: the resulting code may or may not perform better than without cross-jumping, so it's a vibe check, not a guarantee ๐คทโโ๏ธ
Enabled at levels -O2, -O3, -Os. ๐
-fauto-inc-decโ this 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 -O1 and higher on architectures that support this. โจ
-fdceโ performs dead code elimination (DCE) on RTL ๐๏ธ Bye bye, useless code.
Enabled by default at -O1 and higher. ๐ธ
-fdseโ performs dead store elimination (DSE) on RTL ๐ Stores that nobody reads? Gone.
Enabled by default at -O1 and higher. ๐ธ
-fif-conversionโ this tries to transform conditional jumps into branch-less equivalents ๐ช It includes conditional moves, min, max, set flags and abs instructions, plus some tricks you can do with standard arithmetic. Whether conditional execution gets used on chips that support 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 this one is a whole story ๐ The C++ ABI needs 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, which means two copies of the function. With this option, those two variants become thunks that call a common implementation, so you only keep one real copy ๐งโโ๏ธ
Enabled by -Os. ๐
-fdelete-null-pointer-checksโ this one assumes programs can't safely dereference null pointers, and that no code or data element lives at address zero ๐ โโ๏ธ It enables simple constant folding optimizations at all optimization levels. Other passes in GCC use this flag to control global dataflow analyses that get rid of useless null pointer checks. Those analyses assume that a memory access to address zero always results in a trap, so if a pointer gets checked after it's already been dereferenced, it can't be null.
Careful, bestie: in some environments this assumption isn't true. If your program depends on that behavior, use -fno-delete-null-pointer-checks to turn this optimization off ๐จ
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โ tries 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โ this one tries to convert calls to virtual functions into speculative direct calls ๐ฎ Based on the analysis of the type inheritance graph, it figures out the set of likely targets for a given call. If that set is small, ideally of size 1, the call becomes a conditional that picks between a direct call and an indirect call. Those speculative calls unlock more optimizations, like inlining. If they seem useless after further optimization, they get converted back into their original form.-fdevirtualize-at-ltransโ this streams extra information needed for aggressive devirtualization when the link-time optimizer runs in local transformation mode ๐ It enables more devirtualization, but it significantly increases the size of the streamed data. For that reason it's disabled by default.-fexpensive-optimizationsโ performs a number of minor optimizations that are relatively expensive ๐ธ
Enabled at levels -O2, -O3, -Os. ๐
-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 only gets 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 persisting beyond the object's lifetime, use this flag to disable the optimization. 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, you can use-flifetime-dse=1. The default behavior can be explicitly selected with-flifetime-dse=2. And-flifetime-dse=0is equivalent to-fno-lifetime-dse. ๐ซถ-flive-range-shrinkageโ attempts to decrease register pressure through register live range shrinkage ๐ฌ๏ธ It's 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โ lets you choose 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 for loops with small register pressure as the regions. This value 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 option 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 too.
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โ disables sharing of stack slots allocated for pseudo-registers ๐ โโ๏ธ Each pseudo-register that doesn't get a hard register gets its own stack slot, so, yep, the stack frames are larger.-flra-rematโ enables CFG-sensitive rematerialization in LRA ๐งโโ๏ธ Instead of loading values of spilled pseudos, LRA tries to rematerialize (recalculate) them when that's profitable.
Enabled at levels -O2, -O3, -Os. ๐
-fdelayed-branchโ ๐ง If the target machine supports it, the compiler tries to shuffle instructions around so they fill the empty slots right after delayed branch instructions. Enabled at levels-O1,-O2,-O3,-Os, but not at-Og. ๐-fschedule-insnsโ โจ If the target supports it, the compiler reorders instructions so the CPU isn't left twiddling its thumbs waiting for data that isn't ready yet. This is a lifesaver on machines with slow floating point or memory loads, because other instructions can get issued while the load or float op is still cooking. Conventionally enabled at-O2and-O3. However, many targets override this. For example, on x86 it's disabled at all levels, while on AArch64 it's only enabled at-O3. ๐-fschedule-insns2โ ๐ Basically the same vibe as-fschedule-insns, but this one asks for an extra scheduling pass after register allocation is done. It's especially useful on machines with a relatively small number of registers, where memory loads take more than one cycle. Enabled at levels-O2,-O3,-Os. ๐ฅ-fno-sched-interblockโ ๐ซ Turns off 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โ ๐ โโ๏ธ Turns off speculative motion of non-load instructions. This is normally on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher. ๐-fsched-pressureโ ๐ธ Turns on register pressure sensitive instruction scheduling before register allocation. This only makes sense when that kind of scheduling is on, i.e. with-fschedule-insnsor at-O2or higher. Using it can improve the generated code and shrink its size, because it stops register pressure from climbing above the number of available hard registers, which means fewer spills during register allocation. ๐-fsched-spec-loadโ ๐ Lets the compiler speculatively move some load instructions. Again, this only makes sense when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher. โจ-fsched-spec-load-dangerousโ ๐ญ Lets the compiler speculatively move more load instructions. Same deal: it only makes sense when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher. This one is spicy, bestie, so proceed with care. ๐-fsched-stalled-insns,-fsched-stalled-insns=nโ ๐ง Decides how many instructions (if any) can be yanked early from the queue of stalled instructions and dropped into the ready list during the second scheduling pass.-fno-sched-stalled-insnsmeans no instructions get moved early.-fsched-stalled-insns=0means there's no limit at all on how many queued instructions can be moved early. Using-fsched-stalled-insnswith no value is the same as-fsched-stalled-insns=1. โญ-fsched-stalled-insns-dep,-fsched-stalled-insns-dep=nโ ๐ Sets how many instruction groups (cycles) get checked for a dependency on a stalled instruction that's a candidate for being moved early. This only has an effect during the second scheduling pass, and only if-fsched-stalled-insnsis being used.-fno-sched-stalled-insns-depis the same as-fsched-stalled-insns-dep=0. Using-fsched-stalled-insns-depwith no value is the same as-fsched-stalled-insns-dep=1. ๐ซถ-fsched2-use-superblocksโ ๐ When scheduling after register allocation, this uses superblock scheduling. That lets instructions move across basic block boundaries, which can give you faster schedules. โ ๏ธ This option is experimental, because not all machine descriptions used by GCC model the CPU closely enough to avoid unreliable results from the algorithm, so it's not guaranteed to be trustworthy yet. It only makes sense when scheduling after register allocation, i.e. with-fschedule-insns2or at-O2or higher. ๐งช
โ ๏ธ Heads up, bestie: -fsched2-use-superblocks is experimental. Some machine descriptions don't model the CPU closely enough, so the results can be unreliable. Use it with your eyes open. ๐
-fsched-group-heuristicโ ๐ Turns on the group heuristic in the scheduler. This heuristic favors the instruction that belongs to a schedule group. It's enabled by default whenever scheduling is enabled, i.e. with-fschedule-insns,-fschedule-insns2, or at-O2or higher. ๐-fsched-critical-path-heuristicโ ๐ค๏ธ Turns on the critical-path heuristic in the scheduler. This one favors instructions that sit on the critical path. It's enabled by default whenever scheduling is enabled, i.e. with-fschedule-insns,-fschedule-insns2, or at-O2or higher. ๐-fsched-spec-insn-heuristicโ ๐ฆ Turns on the speculative instruction heuristic in the scheduler. It favors speculative instructions with greater dependency weakness. Enabled by default whenever scheduling is enabled, i.e. with-fschedule-insns,-fschedule-insns2, or at-O2or higher. โจ-fsched-rank-heuristicโ ๐ Turns on the rank heuristic in the scheduler. It favors the instruction living in a basic block with greater size or frequency. Enabled by default whenever scheduling is enabled, i.e. with-fschedule-insns,-fschedule-insns2, or at-O2or higher. ๐ธ-fsched-last-insn-heuristicโ ๐ฏ Turns on the last-instruction heuristic in the scheduler. It favors the instruction that is less dependent on the last instruction scheduled. Enabled by default whenever scheduling is enabled, i.e. with-fschedule-insns,-fschedule-insns2, or at-O2or higher. ๐-fsched-dep-count-heuristicโ ๐ Turns on the dependent-count heuristic in the scheduler. It favors the instruction that has more instructions depending on it. Enabled by default whenever scheduling is enabled, i.e. with-fschedule-insns,-fschedule-insns2, or at-O2or higher. ๐ซถ-freschedule-modulo-scheduled-loopsโ ๐ Modulo scheduling happens before the traditional scheduling. If a loop gets modulo scheduled, later scheduling passes are allowed to change its schedule. Use this option to control that behavior. ๐ง-fselective-schedulingโ ๐ Schedules instructions using the selective scheduling algorithm. Selective scheduling runs instead of the first scheduler pass. ๐-fselective-scheduling2โ ๐ฆ Schedules instructions using the selective scheduling algorithm too, but this time it runs instead of the second scheduler pass. ๐-fsel-sched-pipeliningโ ๐ Enables software pipelining of innermost loops during selective scheduling. This does nothing unless-fselective-schedulingor-fselective-scheduling2is turned on. ๐-fsel-sched-pipelining-outer-loopsโ ๐ช When pipelining loops during selective scheduling, this also pipelines the outer loops. It has no effect unless-fsel-sched-pipeliningis turned on. โจ-fsemantic-interpositionโ ๐ง Some object formats, like ELF, let the dynamic linker interpose symbols. That means that for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, because the function or variable might get swapped out at runtime. Interposition is useful, for example, when you want to replace memory allocation functions with a debugging implementation, but it costs you a lot in 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. This flag has no effect on functions explicitly declaredinline(where interposition is never allowed to change semantics), and it has no effect on 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 of the function. Enabled by default at-Oand higher. โจ-fshrink-wrap-separateโ โ๏ธ Shrink-wraps the separate parts of the prologue and epilogue on their own, so those parts only run when they're needed. This option is on by default, but it has no effect unless-fshrink-wrapis also turned on and the target supports this. ๐ธ-fcaller-savesโ ๐พ Lets the compiler allocate values to registers that get clobbered by function calls, by emitting extra instructions to save and restore those registers around such calls. That allocation only happens when it seems to produce 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โ ๐ง Lets the compiler use 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 (which happens on targets that don't expose prologues and epilogues in RTL). ๐-fconserve-stackโ ๐ชถ Tries to minimize stack usage. The compiler works to use less stack space, even if that makes the program slower. This option implies setting the large-stack-frame parameter to100and the large-stack-frame-growth parameter to400. ๐-ftree-reassocโ ๐ณ Performs reassociation on trees. Enabled by default at-O1and higher. ๐-fcode-hoistingโ ๐๏ธ Performs code hoisting. This 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. Enabled by default at-O2and higher. โจ-ftree-preโ ๐ฎ Performs partial redundancy elimination (PRE) on trees. Enabled by default at-O2and-O3. ๐-ftree-partial-preโ ๐ฅ Makes partial redundancy elimination (PRE) more aggressive. Enabled by default at-O3. ๐-ftree-forwpropโ โก๏ธ Performs forward propagation on trees. Enabled by default at-O1and higher. ๐ฆ-ftree-freโ okay so this one does full redundancy elimination (FRE) on trees ๐ . The difference between FRE and PRE is that FRE only looks at expressions that are computed on all paths leading to the redundant computation. It's faster than PRE, though it catches fewer redundancies ๐ซถ. This flag is enabled by default at-O1and higher โจ.-ftree-phipropโ this one hoists loads from conditional pointers on trees ๐ฆ. It's enabled by default at-O1and higher.-fhoist-adjacent-loadsโ ngl this one is so cute ๐. It speculatively hoists loads from both branches of an if-then-else, but only when the loads come from adjacent locations in the same structure and the target architecture has a conditional move instruction. It's enabled by default at-O2and higher.-ftree-copy-propโ copy propagation on trees, bestie ๐ง. It gets rid of unnecessary copy operations. Enabled by default at-O1and higher.-fipa-pure-constโ this one figures out which functions are pure or constant ๐ฎ. Enabled by default at-O1and higher.-fipa-referenceโ this one finds out which static variables don't escape the compilation unit ๐ธ. Enabled by default at-O1and higher.-fipa-reference-addressableโ this one discovers read-only, write-only and non-addressable static variables ๐. Enabled by default at-O1and higher.-fipa-reorder-for-localityโ main character energy ๐. It groups call chains close together in the binary layout, which improves code locality and shortens jump distances between functions that get called a lot ๐. Unlike-freorder-functions, this pass looks at the call chains between functions and clusters them together, instead of sorting everything into separate hot/normal/cold/never-executed sections. Unlike-fprofile-reorder-functions, it's going for locality across the whole runtime of the program, not just startup ๐.
This option is incompatible with an explicit -flto-partition= option, since it enforces its own custom partitioning scheme. If you use it, 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 when it's possible โจ. Enabled by default.-fipa-ptaโ interprocedural pointer analysis plus interprocedural modification and reference analysis ๐ง.
This one can cause excessive memory and compile-time usage on large compilation units, so be careful ๐ญ. It is not enabled by default at any optimization level.
-fipa-profileโ interprocedural profile propagation ๐. Functions that are only called from cold functions get marked as cold, and functions that run once (like "cold", "noreturn", static constructors or destructors) get identified too. Cold functions, plus the loop-less parts of functions that run once, then get optimized for size. Enabled by default at-O1and higher.-fipa-modrefโ interprocedural mod/ref analysis ๐. It analyzes the side effects of functions (the memory locations they modify or reference), which allows better optimization across the function call boundary. Enabled by default at-O1and higher.-fipa-cpโ interprocedural constant propagation ๐ฅ. It figures out when values passed to functions are constants, then optimizes accordingly. This can seriously boost performance if your app passes constants into functions. Enabled by default at-O2,-Osand-O3, and also enabled by-fprofile-useand-fauto-profile.-fipa-cp-cloneโ function cloning to make interprocedural constant propagation stronger ๐ฆ. When enabled, it clones externally visible functions that can be called with constant arguments. Since this can create multiple copies of functions, it may significantly increase code size (see--param ipa-cp-unit-growth=value) โ ๏ธ. Enabled by default at-O3, and also enabled by-fprofile-useand-fauto-profile.-fipa-bit-cpโ when enabled, does interprocedural bitwise constant propagation ๐. Enabled by default at-O2, and also by-fprofile-useand-fauto-profile. It requires that-fipa-cpis enabled.-fipa-vrpโ when enabled, does interprocedural propagation of value ranges ๐. Enabled by default at-O2. It requires that-fipa-cpis enabled.-fipa-icfโ Identical Code Folding for functions and read-only variables ๐ง. It shrinks code size, but it can mess with unwind stacks, because a function gets replaced by an equivalent one with a different name ๐. It works better with link-time optimization turned on.
Although it's similar to the Gold Linker's ICF optimization, GCC's ICF works on different levels, so the optimizations aren't the same. Some equivalences are only found by GCC, and some are only found by Gold ๐ค.
This flag is enabled by default at -O2 and -Os.
-flate-combine-instructionsโ turns on two instruction combination passes that run pretty late in compilation ๐งฉ. 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 by default at-O2and-Os.-flive-patching=levelโ controls GCC's optimizations so the output is suitable for live-patching ๐ฉน.
So here's the deal: if an optimization uses a function's body (or info pulled from its body) to optimize a different function, that other function is called an impacted function of the first one. If a function gets patched, its impacted functions should be patched too ๐ซถ. 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 gets cloned and its caller is changed to call the clone, or when a function's pureness/constness info gets used to optimize its direct or indirect callers.
Usually, the more IPA optimizations you have enabled, the more impacted functions each function ends up with. To keep that number under control and make the list easier to compute, IPA optimizations can be partially enabled at two different levels ๐ธ.
The level argument should be one of the following:
inline-cloneโ only inlining and cloning optimizations get enabled. That includes inlining, cloning, interprocedural scalar replacement of aggregates and partial inlining. So when you patch a function, all its callers and its clones' callers are impacted, and need patching too. This 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-modrefinline-only-staticโ only inlining of static functions is enabled ๐. So when you patch a static function, all its callers are impacted and need patching too. On top of everythinginline-clonedisables,-flive-patching=inline-only-staticalso 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 by dereferencing a null pointer ๐ต๏ธโโ๏ธ. It isolates those paths from the main control flow and turns the statement with the erroneous or undefined behavior into a trap. Enabled by default at-O2and higher, and it depends on-fdelete-null-pointer-checksalso being enabled.-fisolate-erroneous-paths-attributeโ detects paths that trigger erroneous or undefined behavior because a null value is used in a way that areturns_nonnullornonnullattribute forbids ๐ โโ๏ธ. It isolates those paths and turns the statement into a trap, same as above. This one is not currently enabled, but it may be enabled by-O2in the future ๐.-ftree-sinkโ forward store motion on trees ๐ผ. Enabled by default at-O1and higher.-ftree-bit-ccpโ sparse conditional bit constant propagation on trees, plus propagation of pointer alignment information ๐ง . This pass only operates on local scalar variables. It's enabled by default at-O1and higher, except for-Og, and it requires that-ftree-ccpis enabled.-ftree-ccpโ sparse conditional constant propagation (CCP) on trees ๐ซ. This pass only operates on local scalar variables, and it's enabled by default at-O1and higher.-fssa-backpropโ propagates info about how a value gets used back up the definition chain so the definitions can be simplified ๐ช. For example, this pass strips sign operations if the sign of a value never matters. Enabled by default at-O1and higher.-fssa-phioptโ pattern matching on SSA PHI nodes to optimize conditional code ๐ฏ. Enabled by default at-O1and higher, except for-Og.-ftree-switch-conversionโ turns simple initializations in a switch into initializations from a scalar array ๐ญ. Enabled by default at-O2and higher.-ftree-tail-mergeโ looks for identical code sequences, and when it finds them, replaces one with a jump to the other ๐งต. This is known as tail merging or cross jumping. Enabled by default at-O2and higher. The compilation time for this pass can be limited with themax-tail-merge-comparisonsparameter and themax-tail-merge-iterationsparameter.-ftree-cselimโ conditional store elimination on trees ๐ท. Enabled by default at-O1and higher, on targets that have conditional move instructions.
Okay bestie, let's keep going with the optimization flags ๐ โจ
-ftree-dceโ ๐งน Does dead code elimination (DCE) on trees, aka it yeets code that never actually does anything. This one's switched on by default at-O1and higher, so you get it for free ๐-ftree-builtin-call-dceโ ๐ Does conditional DCE for calls to built-in functions that might seterrnobut otherwise have no side effects. It's on by default at-O2and higher, but only if-Osisn't also specified. Main character energy, but make sure you're not stacking-Osin there ๐-ffinite-loopsโ ๐ Tells the compiler to assume that a loop with an exit will eventually take that exit and won't loop forever. That lets it remove loops that have no side effects, and it doesn't count eventual endless looping as a side effect. This is turned on by default at-O2for C++ with-std=c++11or higher ๐-ftree-dominator-optsโ ๐งผ Runs a bunch of simple scalar cleanups based on a dominator tree traversal: constant/copy propagation, redundancy elimination, range propagation, and expression simplification. It also does jump threading, which reduces jumps to jumps โจ Enabled by default at-O1and higher.-ftree-dseโ ๐๏ธ Does dead store elimination (DSE) on trees. A dead store is a store into a memory location that gets overwritten by another store later on with no loads in between, so the earlier store can be deleted ๐ฆ Enabled by default at-O1and higher.-ftree-chโ ๐ Does loop header copying on trees. It's super beneficial because it makes code motion optimizations more effective, and it also saves one jump ๐ธ Enabled by default at-O1and higher, but NOT for-Os, since it usually bumps up code size.-ftree-loop-optimizeโ ๐ Does loop optimizations on trees. Enabled by default at-O1and higher ๐-ftree-loop-linear,-floop-strip-mine,-floop-blockโ ๐งฉ Loop nest optimizations. These are the same as-floop-nest-optimize. To actually use this transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure gets turned on ๐ ๏ธ-fgraphite-identityโ ๐ช Enables the identity transformation for Graphite. For every SCoP, it builds the polyhedral representation and transforms it back into GIMPLE. This is how you can check the costs or benefits of the GIMPLE -> GRAPHITE -> GIMPLE round trip ๐ Along the way the isl code generator does some minimal optimizations too, 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 based on the Pluto optimization algorithms, and it calculates a loop structure that's optimized for data locality and parallelism. Heads up: this option is experimental โ ๏ธ-floop-parallelize-allโ ๐งต Uses the Graphite data dependence analysis to find loops that can be parallelized. It parallelizes ALL the loops that can be analyzed as having no loop carried dependences, and it does this without checking whether parallelizing them is actually profitable ๐-ftree-coalesce-varsโ ๐ค When the program is being transformed out of SSA representation, this tries to cut down on copying by coalescing versions of different user-defined variables, not just compiler temporaries. Fair warning: this can severely limit your ability to debug an optimized program compiled with-fno-var-tracking-assignments๐ญ In the negated form, this flag stops SSA coalescing of user variables. It's enabled by default if optimization is enabled, and it does very little otherwise.-ftree-loop-if-convertโ ๐ช Tries to transform conditional jumps in the innermost loops into branch-less equivalents. The goal is to get rid of control flow in the innermost loops so the vectorization pass can handle them better. It's enabled by default if vectorization is enabled โจ-ftree-loop-distributionโ โ๏ธ Performs loop distribution. This can improve cache performance on big loop bodies and lets further loop optimizations, like parallelization or vectorization, happen. Here's the vibe with a Fortran loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
It gets split into this:
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
This is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-ftree-loop-distribute-patternsโ ๐ Does loop distribution for patterns that can be code generated as calls to a library. It's enabled by default at-O2and higher, and by-fprofile-useand-fauto-profiletoo. This pass distributes the initialization loops and generates a call tomemsetzero. Check out this loop:
DO I = 1, N
A(I) = 0
B(I) = A(I) + I
ENDDO
It becomes:
DO I = 1, N
A(I) = 0
ENDDO
DO I = 1, N
B(I) = A(I) + I
ENDDO
And then the initialization loop gets turned into a call to memset zero ๐งธ
-floop-interchangeโ ๐ Performs loop interchange outside of Graphite. This can improve cache performance on loop nests and lets further loop optimizations, like vectorization, take place. Like 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 flipped 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];
This is enabled by default at -O3, and also by -fprofile-use and -fauto-profile ๐ซถ
-floop-unroll-and-jamโ ๐ฅช Applies unroll and jam transformations on feasible loops. In a loop nest, this unrolls the outer loop by some factor and fuses the resulting multiple inner loops together. Enabled by default at-O3, and also by-fprofile-useand-fauto-profile๐ฅ-ftree-loop-imโ ๐ Performs loop invariant motion on trees. This pass only moves invariants that are hard to handle at the RTL level, like function calls and operations that expand into nontrivial sequences of insns. With-funswitch-loops, it also moves operands of conditions that are invariant out of the loop, so that trivial invariantness analysis can be used in loop unswitching. The pass also includes store motion ๐ง-ftree-loop-ivcanonโ ๐ข Creates a canonical counter for the number of iterations in loops where figuring out the iteration count takes complicated analysis. Later optimizations can then figure out the number easily. It's especially useful alongside unrolling ๐ท-ftree-scev-cpropโ ๐ฏ Performs final value replacement. If a variable gets modified in a loop in such a way that its value when exiting the loop can be determined using only its initial value and the number of loop iterations, then uses of the final value get replaced by that computation, as long as it's sufficiently cheap. This reduces data dependencies and may allow further simplifications. Enabled by default at-O1and higher ๐-fivoptsโ ๐ Performs induction variable optimizations on trees: strength reduction, induction variable merging, and induction variable elimination. Enabled by default at-O1and higher ๐ฆ-ftree-parallelize-loops=nโ ๐งถ Parallelizes loops by splitting their iteration space so it runs in n threads. This is only possible for loops whose iterations are independent and can be arbitrarily reordered. It's only really profitable on multiprocessor machines, and only for CPU-intensive loops rather than loops that are constrained by something like memory bandwidth. This option implies-pthread, so it's only supported on targets that support-pthread๐งต-ftree-ptaโ ๐ Performs function-local points-to analysis on trees. It's enabled by default at-O1and higher, except for-Og๐ธ-ftree-sraโ ๐ช Performs scalar replacement of aggregates. This pass swaps structure references out for scalars, so structures don't get committed to memory too early. Enabled 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 combines them into fewer, wider stores to cut down on instructions. Enabled by default at-O2and higher, as well as-Osโจ-ftree-terโ ๐ Performs temporary expression replacement during the SSA->normal phase. Single use/single def temporaries get replaced at their use location with their defining expression. This results in non-GIMPLE code, but it gives the expanders much more complex trees to work with, which leads to better RTL generation ๐ง Enabled by default at-O1and higher.-ftree-slsrโ ๐ Performs straight-line strength reduction on trees. It recognizes related expressions involving multiplications and swaps them for less expensive calculations when possible. Enabled by default at-O1and higher ๐-ftree-vectorizeโ ๐ Performs vectorization on trees. This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified already ๐-ftree-loop-vectorizeโ ๐๏ธ Performs loop vectorization on trees. Enabled by default at-O2, and also by-ftree-vectorize,-fprofile-use, and-fauto-profile๐-ftree-slp-vectorizeโ ๐ Performs basic block vectorization on trees. Enabled by default at-O2, and also by-ftree-vectorize,-fprofile-use, and-fauto-profile๐ซง
โจ -ftrivial-auto-var-init=choice โจ
okay so this one is about initializing automatic variables ๐ to make your program safer and more predictable by stopping uninitialized memory from leaking out or getting used ๐ญ. GCC still treats an automatic variable with no explicit initializer as uninitialized, so -Wuninitialized and -Wanalyzer-use-of-uninitialized-value will still flag them ๐ฉ, and the optimizer still treats them as uninitialized too. With this option, GCC also zeroes any padding in automatic variables that are structs or unions ๐ซถ. bestie, the catch is that the current implementation can't initialize automatic variables declared between the controlling expression and the first case of a "switch" statement ๐. Use -Wtrivial-auto-var-init to report all such cases.
The three values of choice are:
uninitializedโ doesn't initialize any automatic variables at all. This is C and C++'s default ๐ .patternโ initializes automatic variables with values that will likely turn logic bugs into crashes down the line ๐ฅ. They're easy to spot in a crash dump and aren't values programmers can rely on for real program semantics โจ. The current value is a byte-repeatable pattern with the byte0xFE. The values used for pattern initialization might change in the future ๐.zeroโ initializes automatic variables with zeroes ๐ธ.
The default is uninitialized ๐ฆ.
Note that the initializer values, whether zero or pattern, refer to the data representation (in memory or machine registers), not to how the value gets interpreted as a number ๐ง. This distinction matters a lot 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 0x00 or 0xFE, depending on choice. That's true whether or not those representations stand for values in that range, and even if they do, the interpretation of the held value depends on the bias ๐. A hardbool variable that uses say "0X5A" and 0xA5 for "false" and "true", respectively, will trap with either choice of trivial initializer. So zero initialization won't convert to the representation for "false", even though it would for a "static" variable of the same type ๐. This means the initializer pattern doesn't generally depend on the type of the initialized variable. One notable exception: (non-hardened) boolean variables that fit in registers are initialized with "false" (zero), even when pattern is requested ๐ซถ.
You can control this behavior for a specific variable by using the variable attribute "uninitialized" ๐.
โจ -fvect-cost-model=model โจ
this one changes the cost model used for vectorization ๐. The model argument should be one of unlimited, dynamic, cheap or very-cheap. With unlimited, the vectorized code path is assumed to be profitable ๐ช. With dynamic, a runtime check guards the vectorized code path so it only runs for iteration counts that will likely execute faster than the original scalar loop ๐โโ๏ธ. cheap disables vectorization of loops where doing so would be cost prohibitive, like when it needs runtime checks for data dependence or alignment, but otherwise it's the same as dynamic ๐ง. 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 the same as cheap ๐ฅฒ.
The default cost model depends on other optimization flags and is either dynamic or cheap โญ.
โจ -fsimd-cost-model=model โจ
this one is like the one above, but for loops marked with the OpenMP simd directive ๐ฆ. The model argument should be one of unlimited, dynamic, cheap. All values of model mean the same thing as described in -fvect-cost-model, and by default, a cost model defined with -fvect-cost-model is used ๐ซถ.
โจ -ftree-vrp โจ
this turns on Value Range Propagation on trees ๐ฟ. It's kind of like the constant propagation pass, except instead of propagating values, it propagates ranges of values โจ. That lets the optimizers remove unnecessary range checks, like array bound checks and null pointer checks ๐ง . It's enabled by default at -O2 and higher. Null pointer check elimination only happens if -fdelete-null-pointer-checks is enabled ๐.
โจ -fsplit-paths โจ
this splits paths that lead to loop backedges ๐ค๏ธ. It can improve dead code elimination and common subexpression elimination ๐งน. It's enabled by default at -O3 and above ๐ฅ.
โจ -fsplit-ivs-in-unroller โจ
this lets the compiler express the values of induction variables in later iterations of an unrolled loop using the value from the first iteration ๐งฎ. That breaks up long dependency chains, which makes the scheduling passes more efficient ๐.
A combination of -fweb and CSE is often enough to get the same effect ๐
. But that isn't reliable when the loop body is more complicated than a single basic block ๐ฌ. It also doesn't work at all on some architectures because of restrictions in the CSE pass ๐.
This optimization is enabled by default ๐.
โจ -fvariable-expansion-in-unroller โจ
with this option, the compiler makes multiple copies of some local variables when it unrolls a loop, which can result in superior code ๐.
This optimization is enabled by default for PowerPC targets, but disabled by default otherwise ๐ธ.
โจ -fpartial-inlining โจ
this inlines parts of functions ๐งฉ. It only has any effect when inlining itself is turned on by the -finline-functions or -finline-small-functions options ๐.
Enabled at levels -O2, -O3, -Os ๐.
โจ -fpredictive-commoning โจ
this performs predictive commoning, which means reusing computations (especially memory loads and stores) that were done in previous iterations of loops ๐.
This option is enabled at level -O3 ๐ฅ. It's also enabled by -fprofile-use and -fauto-profile ๐.
โจ -fprefetch-loop-arrays โจ
if the target machine supports it, this generates instructions to prefetch memory, which can speed up loops that access large arrays ๐๏ธ.
This option may generate better or worse code ๐ซ . The results depend heavily on the structure of the loops in your source code ๐.
Disabled at level -Os ๐ญ.
โจ -fno-printf-return-value โจ
this stops GCC from substituting constants for the known return value of formatted output functions like "sprintf", "snprintf", "vsprintf", and "vsnprintf" (but not "printf" or "fprintf") ๐
โโ๏ธ. That transformation lets GCC optimize or even eliminate branches based on the known return value of these functions, when they're called with arguments that are either constant or known to be in a range that makes the exact return value possible ๐ง . For example, when -fprintf-return-value is in effect, both the branch and the body of the "if" statement (but not the call to "snprint") can be optimized away when i is 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 gives the best results with -O2 and above ๐
. It works in tandem with the -Wformat-overflow and -Wformat-truncation options ๐ซถ. The -fprintf-return-value option is enabled by default โจ.
โจ -fno-peephole and -fno-peephole2 โจ
these disable any machine-specific peephole optimizations ๐. The difference between -fno-peephole and -fno-peephole2 is how they're implemented in the compiler ๐ ๏ธ. Some targets use one, some use the other, and a few use both ๐คทโโ๏ธ.
-fpeephole is enabled by default. -fpeephole2 is enabled at levels -O2, -O3, -Os ๐.
โจ -fno-guess-branch-probability โจ
this stops GCC from guessing branch probabilities with 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", then the heuristics guess the probabilities for the rest of the control flow graph, taking the "__builtin_expect" info into account ๐ง . The interactions between the heuristics and "__builtin_expect" can get really complex, so in some cases it might help to disable the heuristics so the effects of "__builtin_expect" are easier to understand ๐ฅน.
You can also specify the expected probability of an expression with the "__builtin_expect_with_probability" built-in function ๐.
The default is -fguess-branch-probability at levels -O, -O2, -O3, -Os ๐ธ.
โจ -freorder-blocks โจ
this reorders basic blocks in the compiled function to reduce the number of taken branches and improve code locality ๐งฉ.
Enabled at levels -O1, -O2, -O3, -Os ๐.
โจ -freorder-blocks-algorithm=algorithm โจ
this picks the algorithm used for basic block reordering ๐งญ. The algorithm argument can be simple, which doesn't increase code size (except sometimes because of secondary effects like alignment) ๐ค. Or it can be stc, the "software trace cache" algorithm, which tries to put all the often-executed code together and minimizes the number of branches executed by making extra copies of code ๐โโ๏ธ.
The default is simple at levels -O1 and -Os, and stc at levels -O2 and -O3 ๐.
โจ -freorder-blocks-and-partition โจ
in addition to reordering basic blocks in the compiled function to reduce taken branches, this partitions hot and cold basic blocks into separate sections of the assembly and .o files ๐ง๐ฅ. The goal is better paging and cache locality performance ๐.
This optimization is automatically turned off in the presence of exception handling or unwind tables (on targets usingsetjump/longjumpor a target-specific scheme) ๐ โโ๏ธ. It's also off for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections ๐. When-fsplit-stackis used, this option isn't enabled by default (to avoid linker errors), but you can still turn it on explicitly if you're using a working linker ๐ ๏ธ.
Enabled for x86 at levels -O2, -O3, -Os ๐.
-freorder-functions: okay so this one shuffles the functions in your object file around to boost code locality โจ. Unlike-fipa-reorder-for-locality, it keeps every function in the same category (hot/normal/cold/never-executed) grouped together ๐ซถ. It does this with special subsections: ".text.hot" for the most frequently executed functions and ".text.unlikely" for the unlikely ones. The linker does the actual reordering, so your object file format has to support named sections and the linker has to place them in a reasonable way ๐ .
This option isn't effective unless you either provide profile feedback (see -fprofile-arcs for details) or manually annotate functions with "hot" or "cold" attributes ๐.
Enabled at levels -O2, -O3, -Os.
-fstrict-aliasing: this one lets the compiler assume the strictest aliasing rules that apply to the language being compiled ๐ฅ. For C (and C++), it turns on optimizations based on the type of expressions. The main idea is that an object of one type is assumed never to live at the same address as an object of a different type, unless the types are almost the same. 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 most recently written to (called "type-punning") is super common ๐ญ. Even with -fstrict-aliasing, type-punning is allowed, as long as the memory is accessed through the union type. 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;
}
Accessing memory by taking the address, casting the resulting pointer and dereferencing the result 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; }
The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os.
-fipa-strict-aliasing: controls whether the rules of-fstrict-aliasingget applied across function boundaries ๐ฆ. Heads up: 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 and is effective only in combination with -fstrict-aliasing.
-falign-functions,-falign-functions=n,-falign-functions=n:m,-falign-functions=n:m:n2,-falign-functions=n:m:n2:m2: this lines up the start of functions to the next power-of-two that's greater than or equal to n, skipping up to m-1 bytes ๐ธ. That way 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 gets ignored for functions considered cold. If you need alignment for all functions, use-fmin-function-alignmentinstead โจ.
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 this can be done by skipping 23 bytes or less, -falign-functions=32:7 aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less.
The second pair of n2:m2 values lets you set a secondary alignment: -falign-functions=64:7:32:3 aligns to the next 64-byte boundary if this can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if this 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, it 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 option value is 65536.
Enabled at levels -O2, -O3.
-flimit-function-alignment: when this is enabled, the compiler tries to avoid overaligning functions for no reason ๐ง. It tries to tell the assembler to align by the amount specified by-falign-functions, but without skipping more bytes than the size of the function.-falign-labels,-falign-labels=n,-falign-labels=n:m,-falign-labels=n:m:n2,-falign-labels=n:m:n2:m2: aligns all branch targets to a power-of-two boundary ๐.
The parameters of this option work the same way as they do for -falign-functions. -fno-align-labels and -falign-labels=1 are equivalent and mean that labels are not aligned.
If -falign-loops or -falign-jumps apply and are greater than this value, then their values get 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 option value is 65536.
Enabled at levels -O2, -O3.
-falign-loops,-falign-loops=n,-falign-loops=n:m,-falign-loops=n:m:n2,-falign-loops=n:m:n2:m2: aligns loops to a power-of-two boundary ๐. If the loops run many times, this makes up for the cost of executing 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, then its value is used instead.
The parameters of this option work the same way as they do for -falign-functions. -fno-align-loops and -falign-loops=1 are equivalent and mean that loops are not aligned. The maximum allowed n option value is 65536.
If n isn't specified or is zero, the compiler uses a machine-dependent default.
Enabled at levels -O2, -O3.
-falign-jumps,-falign-jumps=n,-falign-jumps=n:m,-falign-jumps=n:m:n2,-falign-jumps=n:m:n2:m2: aligns branch targets to a power-of-two boundary, but only for branch targets that can only be reached by jumping ๐ฆ. In this case, no dummy operations need to be executed. It's a code performance optimization, and alignment is ignored for jumps considered cold.
If -falign-labels is greater than this value, then its value is used instead.
The parameters of this option work the same way as they do for -falign-functions. -fno-align-jumps and -falign-jumps=1 are equivalent and mean that loops are not aligned ๐.
If n isn't specified or is zero, the compiler uses a machine-dependent default. The maximum allowed n option value is 65536.
Enabled at levels -O2, -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 is applied to all functions, even the ones considered cold. The alignment also isn't affected by-flimit-function-alignment.-fno-allocation-dce: do not remove unused C++ allocations (using operator "new" and operator "delete") during dead code elimination ๐.
See also -fmalloc-dce.
-fallow-store-data-races: lets the compiler perform 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 option if you know that global data won't be accessed by multiple threads.
Examples of optimizations enabled by -fallow-store-data-races include hoisting or if-conversions that might cause a value already in memory to be rewritten with that same value. That kind of rewriting is safe in a single-threaded context, but may be unsafe in a multi-threaded one. Note that on some processors, if-conversions may be required in order to enable vectorization โจ.
Enabled at level -Ofast.
-funit-at-a-time: this one is only kept around for compatibility reasons ๐ซถ.-funit-at-a-timehas no effect, while-fno-unit-at-a-timeimplies-fno-toplevel-reorderand-fno-section-anchors.
Enabled by default.
-fno-toplevel-reorder: do not reorder top-level functions, variables, and "asm" statements ๐. Output them in the same order they appear in the input file. When this option is used, unreferenced static variables are not removed. It's meant to support existing code that relies on a particular ordering. For new code, it's better to use attributes when possible.
-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested. Additionally, -fno-toplevel-reorder implies -fno-section-anchors.
-funreachable-traps: with this option, the compiler turns calls to "__builtin_unreachable" into traps, instead of using them for optimization ๐ญ. This also affects any such calls the compiler generates implicitly.
This option has the same effect as -fsanitize=unreachable -fsanitize-trap=unreachable, but it doesn't affect the values of those options. If -fsanitize=unreachable is enabled, that option takes priority over this one.
This option is enabled by default at -O0 and -Og.
-fweb: constructs webs as commonly used for register allocation purposes, and assigns each web its own individual pseudo register ๐ง. This lets the register allocation pass work on pseudos directly, and it also strengthens several other optimization passes, such as CSE, the loop optimizer and the trivial dead code remover. It can, however, make debugging impossible, since variables no longer stay in a "home register" ๐ฅบ.
Enabled by default with -funroll-loops.
-fwhole-program: assumes that the current compilation unit represents the whole program being compiled ๐. All public functions and variables, with the exception ofmainand those merged by the attributeexternally_visible, become static functions, and in effect get optimized more aggressively by interprocedural optimizers ๐ธ.
With -flto this option has limited use, bestie ๐ฅบ Most of the time the linker plugin already knows exactly which symbols get used or exported from the binary, and it passes that info to the link-time optimizer. It's still useful if no linker plugin is used, or during an incremental link step where the final code gets produced (with -flto -flinker-output=nolto-rel). ๐ฆ
โจ -flto[=n] โจ
okay so this one is the standard link-time optimizer and it's giving main character ๐ When you feed it source code, it generates GIMPLE (one of GCC's internal representations) and writes it into special ELF sections in the object file. Then when the object files get linked together, all the function bodies are read back out of those ELF sections and instantiated as if they had been part of the same translation unit. iconic, right? ๐
To use the link-time optimizer, -flto and your optimization options should be specified at compile time AND during the final link. It's recommended that you compile every file in the same link with the same options, and also specify those options at link time. 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 to GCC save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o. The final invocation reads the 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 foo.o and bar.o 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 ๐คฏ. That means, for example, the inliner can inline functions in bar.o into functions in foo.o and vice-versa. literally so cool.
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 together into a single GIMPLE representation, and optimizes them as usual to produce myprog. ๐
The important thing to keep in mind is that to enable link-time optimizations you need to use the GCC driver to do 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. not me needing an override button ๐
To make whole program optimization effective, you have to make certain whole program 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 info to the compiler about used and externally visible symbols. When the linker plugin isn't available, use -fwhole-program so the compiler can make these assumptions, which leads to more aggressive optimization decisions. โจ
When a file is compiled with -flto but without -fuse-linker-plugin, the generated object file is bigger than a regular one, because it contains GIMPLE bytecodes AND the usual final code (see -ffat-lto-objects). This means object files with LTO information can be linked as normal object files. If -fno-lto is passed to the linker, 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 the 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 files to link without further processing. ๐ซถ
Generally, options specified at link time override those specified at compile time, although in some cases GCC tries 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 the 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 that GCC preserves when generating bytecodes, since they need to be used during the final link. Right now, 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 following options -fPIC, -fpic, -fpie and -fPIE are 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, and trying to override them at link time with a conflicting value is 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 are 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 are passed through to the link stage, 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 those 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, as an alternative. ๐ง
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 will enable 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 in different translation units is discouraged. ๐
If LTO encounters objects with C linkage declared with incompatible types in separate translation units that are being linked together (undefined behavior according to ISO C99 6.2.7), a non-fatal diagnostic may be issued. The behavior is still undefined at run time. Similar diagnostics may be raised for other languages. โ ๏ธ
Another feature of LTO is that you can apply interprocedural optimizations on 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 you would 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 if 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, and 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 to make them part of the aggregated GIMPLE image to be optimized. ๐ฆ
If you're not using a linker with plugin support, and/or you don't enable the linker plugin, then the objects inside libfoo.a are extracted and linked as usual, but they do not participate in the LTO optimization process. To make a static library suitable for both LTO optimization and usual linkage, compile its object files with -flto -ffat-lto-objects. ๐
Link-time optimizations don't require the presence of the whole program to operate. If the program doesn't require any symbols to be exported, you can combine -flto and -fwhole-program to let the interprocedural optimizers use more aggressive assumptions, which may lead to better optimization opportunities. Using -fwhole-program isn't needed when the linker plugin is active (see -fuse-linker-plugin). โจ
The current implementation of LTO makes no attempt to generate bytecode that is portable between different types of hosts. The bytecode files are versioned and there's a strict version check, so bytecode files generated by one version of GCC do not work with an older or newer version of GCC. ๐ซ
Link-time optimization does not work well with generation of debugging information on systems other than those using a combination of ELF and DWARF. ๐ธ
If you pass the optional n, the link-time optimization and code generation run in parallel with n jobs, using an installed make program. The MAKE environment variable can be set to override which program gets used. ๐ง
You can also say -flto=jobserver to let GNU make's job server decide how many parallel jobs to run. This is super useful when the Makefile calling GCC is already running in parallel ๐ฅ. You have to put a + in front of the command recipe in the parent Makefile for this to work. This option probably only works if MAKE is GNU make. Even without an option value, GCC will try to auto-detect a running GNU make job server, so it's kind of doing the work for you ๐
.
Use -flto=auto if you want GNU make's job server when it's available. If it isn't, GCC falls back to auto-detecting how many CPU threads your system has โจ.
-flto-partition=algโ Picks the partitioning algorithm the link-time optimizer uses. The options are1to1, which mirrors your original source files;balanced, which makes equally sized chunks whenever it can (this is the default ๐);max, which makes a new partition for every symbol where possible; andcache, which balances chunk sizes while keeping related symbols together so incremental LTO caches better ๐ฆ. Choosingnoneturns partitioning and streaming off completely ๐.1to1can be used as a workaround for various code ordering issues, butmaxis intended for internal testing only, so don't go there in real life ๐. The valueonemeans exactly one partition gets used, andnoneskips partitioning and runs the link-time optimization step straight from the WPA phase.-flto-incremental=pathโ Turns on incremental LTO and stores its cache in the given directory, which has to already exist ๐ธ. This can seriously shorten your edit-compile cycles with LTO ๐ญ.
When you use LTO (-flto), the output of the translation units inside LTO gets cached. Cached translation units are likely to show up again when you recompile after small code changes, so your recompile times go down ๐ซถ.
Multiple GCC instances can share the same cache in parallel, so no fighting over it ๐.
-flto-incremental-cache-size=nโ Sets how many cache entries incremental LTO keeps before it prunes the old ones. This is a soft limit, so you might briefly have more entries than that ๐งน.-flto-compression-level=nโ Controls how hard the intermediate language written to LTO object files gets compressed. It only matters together with LTO mode (-flto) ๐๏ธ. GCC currently supports two LTO compression algorithms. For zstd, valid values run from0(no compression) to19(maximum compression), while zlib goes from0to9. Anything outside that range gets clamped to the minimum or maximum of whatever's supported. If you don't give this option, GCC uses a default balanced compression setting ๐.-fuse-linker-pluginโ Turns on the linker plugin during link-time optimization ๐. This relies on plugin support in the linker, which you'll find in gold or in GNU ld 2.21 or newer โจ.
This option lets GCC pull object files with GIMPLE bytecode out of library archives. That's a big glow-up for optimization quality, since it exposes more code to the link-time optimizer ๐ฆ. The plugin also shares which symbols can be accessed externally (from non-LTO objects or during dynamic linking). The code quality gains for binaries (and shared libraries that use hidden visibility) are similar to -fwhole-program. Check out -flto for a description of what this flag does and how to use it ๐.
This option is enabled by default when LTO support is enabled in GCC and GCC was configured for a linker that supports plugins (GNU ld 2.21 or newer, or gold). Main character energy ๐ .
-ffat-lto-objectsโ Fat LTO objects are object files that hold both the intermediate language and the object code ๐. That means they work for both LTO linking and normal linking. This option only does anything when you're compiling with-flto, and it's ignored at link time ๐ซ .-fno-fat-lto-objectsโ Compiles faster than plain LTO, but it needs your whole toolchain to be LTO-aware ๐ ๏ธ. It needs a linker with linker plugin support for basic functionality. On top of that,nm,arandranlibneed to support linker plugins for a full-featured build environment (one that can build static libraries and so on). GCC provides thegcc-ar,gcc-nmandgcc-ranlibwrappers to pass the right options to these tools. Without fat LTO, your makefiles need to be modified to use them ๐.
Heads up: modern binutils have 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, GCC looks for arithmetic instructions that compute processor flags the way a comparison would. If it can, it removes the explicit comparison entirely ๐งผ. This pass only applies to certain targets that can't explicitly represent the comparison before register allocation is done ๐ฏ.
Enabled at levels -O1, -O2, -O3, -Os ๐.
-ffold-mem-offsets,-fno-fold-mem-offsetsโ Tries to get rid of 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 does a copy-propagation pass to reduce scheduling dependencies and occasionally eliminate the copy ๐.
Enabled at levels -O1, -O2, -O3, -Os ๐.
-fprofile-correctionโ Profiles collected from an instrumented binary for multi-threaded programs can come out inconsistent because counter updates got missed ๐ตโ๐ซ. When you use this option, GCC uses heuristics to correct or smooth out those inconsistencies. By default, GCC throws an error message when it detects an inconsistent profile ๐จ.
This option is enabled by -fauto-profile ๐.
-fprofile-partial-trainingโ With-fprofile-use, every part of the program that wasn't executed during the train run gets optimized aggressively for size instead of speed ๐. Sometimes it isn't practical to train every possible hot path (say your program has functions specific to some hardware, and training can't cover every hardware configuration it runs on ๐ฅ๏ธ). With-fprofile-partial-training, profile feedback gets ignored for all functions that weren't executed during the train run. Those functions get optimized as if they were compiled without profile feedback ๐ง. This gives better performance when the train run isn't representative, but it also makes the code significantly bigger ๐ฆ.-fprofile-use,-fprofile-use=pathโ Turns on profile feedback-directed optimizations, plus the following optimizations, many of which are only really 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 might give you poorly optimized code ๐ฌ. Also by default, GCC emits a warning message if the feedback profiles don't exist at all (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โ Turns on sampling-based feedback-directed optimizations, plus the following optimizations, many of which are only really profitable with profile feedback 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 a file containing AutoFDO profile information. If you leave it out, it defaults to fbdata.afdo in 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 more info, check out <https://perf.wiki.kernel.org/> ๐.
E.g.
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Then use the create_gcov tool to convert the raw profile data into a format GCC can use ๐. You also have to hand this tool the unstripped binary for your program. See <https://github.com/google/autofdo> ๐ง .
E.g.
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
The following options control how the compiler handles floating-point arithmetic. These options trade speed for correctness, so they all have to be turned on specifically ๐ง.
-fexcess-precision=styleโ Lets you control excess precision on machines where floating-point operations happen in a format with more precision or range than the IEEE standard and interchange floating-point types ๐ค. A 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 excess precision is harmless, but some programs might rely on the C or C++ language standards' rules for handling IEEE values ๐ฅน.
By default, -fexcess-precision=fast is in effect, which means operations may be carried out in a wider precision than the types in the source if that gives faster code. It's unpredictable when rounding to the source types actually happens ๐ When compiling C or C++, if you specify -fexcess-precision=standard, excess precision follows the rules in ISO C99 or C++. Casts and assignments both cause values to be rounded to their semantic types, whereas -ffloat-store only affects assignments ๐
This option is enabled by default for C or C++ if a strict conformance option like -std=c99 or -std=c++17 is used. -ffast-math turns on -fexcess-precision=fast by default no matter whether a strict conformance option is used โจ If you specify -fexcess-precision=16, constants and the results of expressions with the types _Float16 and __bf16 are computed without excess precision.
-fexcess-precision=standard isn't implemented for languages other than C or C++. On x86, it does nothing if you specify -mfpmath=sse or -mfpmath=sse+387. With the former, IEEE semantics apply without excess precision, and with the latter, rounding is unpredictable ๐ฅบ
-ffloat-storeโ Okay so this one tells GCC not to keep floating-point variables in registers, and it also blocks other options that might change whether a float gets pulled from a register or from memory ๐ง It's mostly been absorbed by-fexcess-precision=standard, which is more general. If you do use-ffloat-store, you might need to rewrite your program so intermediate results go into temporary variables explicitly, because-ffloat-storeonly handles rounding to IEEE format on assignments and not on casts the way-fexcess-precision=standarddoes ๐-ffast-mathโ This one is a whole vibe ๐ฅ It sets-fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans,-fcx-limited-rangeand-fexcess-precision=fastall at once. It also causes the preprocessor macro__FAST_MATH__to be defined ๐ธ
This option isn't turned on by any -O option besides -Ofast, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, make faster code for programs that don't need those guarantees ๐ฆ
-fno-math-errnoโ Don't seterrnoafter calling math functions that run as a single instruction, likesqrt. A program that relies on IEEE exceptions for math error handling might want this flag for speed while keeping IEEE arithmetic compatibility ๐ซถ
Just like before, this isn't turned on by any -O option besides -Ofast, for the same reason: it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO math rules. It might yield faster code for programs that don't need those guarantees.
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-errno is 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. Used at link time, it may include libraries or startup files that change the default FPU control word or make other similar optimizations ๐ญ
Same deal as before: this isn't turned on by any -O option besides -Ofast, because it can produce incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may still yield faster code for programs that don't need those guarantees. It enables -fno-signed-zeros, -fno-trapping-math, -fassociative-math and -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 standard by possibly changing the computation result. โ ๏ธ Heads up: 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 behaviour like(x + 2**52) - 2**52. It may also reorder floating-point comparisons, so don't use it when ordered comparisons are required ๐ฅ
This option requires that both -fno-signed-zeros and -fno-trapping-math be in effect. Also, it doesn't make much sense with -frounding-math. For Fortran, the option is automatically enabled when both -fno-signed-zeros and -fno-trapping-math are in effect.
The default is -fno-associative-math.
-freciprocal-mathโ Lets the reciprocal of a value 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. Just know this loses precision and increases the number of flops operating on the value ๐งฎ
The default is -fno-reciprocal-math.
-ffinite-math-onlyโ Allows optimizations for floating-point arithmetic that assume arguments and results are not NaNs or +-Infs โพ๏ธ
This one also isn't turned on by any -O option besides -Ofast, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, yield faster code for programs that don't need those guarantees.
The default is -fno-finite-math-only.
-fno-signed-zerosโ Allows optimizations for floating-point arithmetic that ignore the signedness of zero. IEEE arithmetic specifies the behaviour of distinct+0.0and-0.0values, which then prohibits simplifying expressions likex+0.0or0.0*x, even with-ffinite-math-only. This option implies that the sign of a zero result isn't significant ๐
The default is -fsigned-zeros.
-fno-trapping-mathโ Compiles code assuming that floating-point operations can't generate user-visible traps. These traps include division by zero, overflow, underflow, inexact result and invalid operation. This option requires that-fno-signaling-nansbe in effect. Setting it may allow faster code if you rely on "non-stop" IEEE arithmetic, for example โจ
This option isn't turned on by any -O option besides -Ofast, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions.
The default is -ftrapping-math.
Future versions of GCC may offer finer control of this setting using C99'sFENV_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 behaviour (round-to-nearest). Use this for programs that change the FP rounding mode dynamically, or that may run with a non-default rounding mode ๐ It disables constant folding of floating-point expressions at compile time, since that may be affected by rounding mode, and it disables arithmetic transformations that are unsafe in the presence of sign-dependent rounding modes.
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 offer finer control of this setting using C99'sFENV_ACCESSpragma. This command-line option will be used along with-ftrapping-mathto specify the default state forFENV_ACCESS.
-fsignaling-nansโ Compiles code assuming that IEEE signaling NaNs may generate user-visible traps during floating-point operations. Setting this option disables optimizations that may change the number of exceptions visible with signaling NaNs. This option implies-ftrapping-math๐จ
This option causes the preprocessor macro __SUPPORT_SNAN__ to be defined.
The default is -fno-signaling-nans.
This option is experimental, and it doesn't currently guarantee that all GCC optimizations affecting signaling NaN behaviour get disabled.
-fno-fp-int-builtin-inexactโ Doesn't allow the built-in functionsceil,floor,roundandtrunc, plus theirfloatandlong doublevariants, to generate code that raises theinexactfloating-point exception for noninteger arguments. ISO C99 and C11 let these functions raise theinexactexception, but ISO/IEC TS 18661-1:2014, the C bindings to IEEE 754-2008 as integrated into ISO C23, doesn't allow them to do so ๐ โโ๏ธ
The default is -ffp-int-builtin-inexact, which allows the exception to be raised, unless C23 or a later C standard is selected. This option does nothing unless -ftrapping-math is in effect.
Even if -fno-fp-int-builtin-inexact is used, if the functions generate a call to a library function, the inexact exception may still be raised if the library implementation doesn't follow TS 18661.
-fsingle-precision-constantโ Treats floating-point constants as single precision, instead of implicitly converting them to double-precision constants ๐ญ-fcx-limited-rangeโ When enabled, this option says a range reduction step isn't needed when performing complex division. There's also no checking for whether the result of a complex multiplication or division isNaN + I*NaN, and no attempt to rescue the situation in that case ๐ซ The default is-fno-cx-limited-range, but-ffast-mathenables it.
This option controls the default setting of the ISO C99 CX_LIMITED_RANGE pragma. Even so, the option applies to all languages.
-fcx-fortran-rulesโ Complex multiplication and division follow Fortran rules. Range reduction is done as part of complex division, but there's no checking for whether the result of a complex multiplication or division isNaN + I*NaN, and no attempt to rescue the situation in that case ๐
The default is -fno-cx-fortran-rules.
The following options control optimizations that may improve performance, but are not enabled by any -O options. โจ This section includes experimental options that may produce broken code, so ๐ tread carefully bestie ๐
-fbranch-probabilities๐ธ โ okay so after you run a program built with-fprofile-arcs, you compile it again with-fbranch-probabilitiesand the optimizations get smarter about how many times each branch was actually taken. When the-fprofile-arcsprogram exits, 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 the file naming details under-fprofile-arcs.- With
-fbranch-probabilities, GCC puts aREG_BR_PROBnote on eachJUMP_INSNandCALL_INSN๐ง These can be used to improve optimization. Right now they're only used in one place:reorg.cc. Instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to exactly figure out which path gets taken more often. Iconic. - Enabled by
-fprofile-useand-fauto-profileโจ
- With
-fprofile-values๐ฆ โ if you combine it with-fprofile-arcs, it adds code so data about the values of expressions in your program gets gathered.- With
-fbranch-probabilities, it reads back that value-profiling data and uses it for 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, since the text segments load more efficiently.- Enabled with
-fprofile-use๐ซถ
- Enabled with
-fvpt๐ฎ โ if combined with-fprofile-arcs, this tells the compiler to add code that gathers info about the values of expressions.- With
-fbranch-probabilities, it reads back that data and actually performs optimizations based on it. Right now that includes specializing division operations using what it knows about the value of the denominator. Main character energy ๐ - Enabled with
-fprofile-useand-fauto-profile
- With
-frename-registers๐ โ attempts to avoid false dependencies in scheduled code by using registers left over after register allocation. This is most helpful for 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๐ โ a target dependent pass over the instruction stream that schedules instructions of the same type together, since the target machine 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
-ftracer๐ โ performs tail duplication to enlarge superblock size. This simplifies the control flow of the function 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 determined 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 means fully removing loops with a small constant number of iterations.- > โ ๏ธ This option makes your code bigger, and it may or may not make it run faster. Vibe check: it's a gamble ๐ฒ
- Enabled by
-fprofile-useand-fauto-profile
-funroll-all-loops๐ โ unrolls all loops, even if the number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly ๐-funroll-all-loopsimplies the same options as-funroll-loops.-fpeel-loops๐ง โ peels loops that don't roll much, based on enough info from profile feedback or static analysis. It also turns on complete loop peeling (fully removing loops with a small constant number of iterations).- Enabled by
-O3,-fprofile-use, and-fauto-profile
- Enabled by
-fmalloc-dce๐๏ธ โ controls whether"malloc"(and its variants like"calloc"or"strdup") can be optimized away, as long as its return value is only used as a parameter of a"free"call or compared with"NULL". With-fmalloc-dce=1, only calls to"free"are allowed. With-fmalloc-dce=2, comparisons with the"NULL"pointer are also considered safe to remove.- The default is
-fmalloc-dce=2. See also-fallocation-dceโจ
- The default is
-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. This moves invariant stores to after the end of the loop, in exchange for carrying the stored value in a register across the iteration.- Note: for this option to have an effect,
-ftree-loop-imhas to be enabled as well ๐ซ - Enabled at level
-O1and higher, except for-Og
- Note: 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. For example:
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-use and -fauto-profile.
-ffunction-sections,-fdata-sections๐๏ธ โ places 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 determines the section's name in the output file.- Use these on systems where the linker can perform optimizations to improve locality of reference in the instruction space. Most systems using the ELF object format have linkers with such optimizations. On AIX, the linker rearranges sections (CSECTs) based on the call graph. The performance impact varies.
- Together with linker garbage collection (the
linker --gc-sectionsoption), these options may lead to smaller statically-linked executables (after stripping) ๐ฑ - On ELF/DWARF systems, these options do not 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. They also affect code generation: they prevent optimizations by the compiler and assembler that use relative locations inside a translation unit, since those locations aren't known until link time. An example of such an optimization is relaxing calls to short call instructions. Be careful, bestie ๐ฅบ
-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. This transformation can help reduce the number of GOT entries and GOT accesses on some targets.- For example, the implementation of the following function
foo:
- For example, the implementation of the following function
static int a, b, c;
int foo (void) { return a + b + c; }
usually calculates the addresses of all three variables. But if you compile it with -fsection-anchors, it accesses the variables from a common anchor point instead. The effect is similar to this pseudocode (which isn't valid C) ๐ค:
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
Not all targets support this option ๐
-fzero-call-used-regs=choice๐ก๏ธ โ zeros the call-used registers at function return to boost program security, either by mitigating Return-Oriented Programming (ROP) attacks or by preventing information leakage through registers.- The possible values of
choiceare the same as for the"zero_call_used_regs"attribute. The default isskip. - You can control this behavior for a specific function by using the function attribute
"zero_call_used_regs"๐
- The possible values of
--param name=value๐๏ธ โ okay so GCC uses various constants to control how much optimization gets done. For example, GCC won't inline functions that contain more than a certain number of instructions. You can control some of these constants on the command line using the--paramoption.- > โ ๏ธ The names of specific parameters, and what the values mean, are tied to the compiler's internals. They're subject to change without notice in future releases, so don't get too attached ๐ญ
- To get the minimal, maximal and default values of a parameter, use
--help=param -Q. - In each case, the value is an integer. The following choices of
nameare recognized for all targets:phiopt-factor-max-stmts-liveโ when factoring statements out of an if/then/else, this is the max number of statements after the defining statement that are allowed to extend the lifetime of a name ๐predictable-branch-outcomeโ when a branch is predicted to be taken with a probability lower than this threshold (in percent), it's considered well predictable โจ
max-rtl-if-conversion-insnsโ okay so RTL if-conversion ๐ tries to yeet conditional branches around a block and swap them for conditionally executed instructions โจ. This param sets the max number of instructions in a block that get considered for if-conversion. GCC also runs its own heuristics to figure out whether if-conversion is actually worth it ๐ง .file-cache-filesโ the max number of files kept in the file cache ๐. The file cache is what GCC uses to print source lines in diagnostics and to run some source checks, like-Wmisleading-indentation๐.file-cache-linesโ the max number of lines that get indexed into the file cache ๐งพ. When this is0, it gets sized automatically ๐ช. Same deal as above: the file cache powers the source lines in diagnostics and checks like-Wmisleading-indentation๐.max-rtl-if-conversion-predictable-costโ same RTL if-conversion idea, where it tries to remove conditional branches and replace them with conditionally executed instructions ๐ธ. These params cap the cost of the sequence if-conversion would generate. There are two versions, depending on whether the branch is statically determined to be predictable or not ๐ฎ. The units match GCC's internalseq_costmetric ๐. GCC tries to pick a sensible default using theBRANCH_COSTtarget macro ๐ฏ.max-crossjump-edgesโ the max number of incoming edges to consider for cross-jumping ๐ฆ. Heads up, the algorithm behind-fcrossjumpingis O(N^2) in the number of incoming edges to each block ๐ญ. Cranking this up means more aggressive optimization, but compile times go up for probably a small win in executable size ๐ข.min-crossjump-insnsโ the minimum number of instructions that have to match at the end of two blocks before cross-jumping happens on them ๐. This value gets ignored when every instruction in the block being cross-jumped from is already matched โจ.max-grow-copy-bb-insnsโ the max code size expansion factor when copying basic blocks instead of jumping ๐งฉ. The expansion is measured relative to a jump instruction ๐ฆ.max-goto-duplication-insnsโ the max number of instructions that can be duplicated into a block that jumps to a computed goto ๐. To dodge O(N^2) behaviour in a bunch of passes, GCC factors computed gotos early on and unfactors them as late as possible ๐ซ . Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsget unfactored ๐.max-delay-slot-insn-searchโ the max number of instructions to look at when hunting for something to fill a delay slot ๐. Past this arbitrary number, the time saved by filling the slot is basically nothing, so GCC stops searching ๐. Higher values mean more aggressive optimization and longer compile times, for probably a small gain in execution time ๐โโ๏ธ.max-delay-slot-live-searchโ when filling delay slots, the max number of instructions to check while searching for a block with valid live register information ๐. Raising this arbitrarily chosen number means more aggressive optimization but slower compiles ๐. This param should get removed once the delay slot code is rewritten to maintain the control-flow graph ๐ง.max-gcse-memoryโ the approximate max amount of memory, in "kB", that can be allocated for the global common subexpression elimination optimization ๐ง . If the optimization would need more memory than this, it just doesn't happen ๐ โโ๏ธ.max-gcse-insertion-ratioโ if the ratio of expression insertions to deletions goes above this value for any expression, RTL PRE inserts or removes the expression instead ๐. The catch is that it leaves partially redundant computations sitting in the instruction stream ๐ฅฒ.max-pending-list-lengthโ the max number of pending dependencies the scheduler allows before it flushes the current state and starts fresh ๐งน. Big functions with few branches or calls can build up huge lists that eat memory and resources for no reason ๐ซง.max-modulo-backtrack-attemptsโ the max number of backtrack attempts the scheduler makes when modulo scheduling a loop ๐. Bigger values can blow up compilation time exponentially ๐๐.max-inline-functions-called-once-loop-depthโ the max loop depth of a call that the inline heuristics will still consider, for the heuristics that try to inline every function called once ๐.max-inline-functions-called-once-insnsโ the max estimated size of functions produced while inlining functions called once ๐.max-inline-insns-singleโ a bunch of params control GCC's tree inliner, and this one sets the max number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will consider for inlining ๐ซ. It only affects functions declaredinlineand methods implemented in a class declaration (C++) ๐.max-inline-insns-autoโ when you use-finline-functions(which is included in-O3), a whole lot of functions that wouldn't normally get considered for inlining get checked out anyway ๐. For those functions, a different, more restrictive limit applies than for functions declaredinline๐. You can set it with--param max-inline-insns-autoโจ.max-inline-insns-smallโ the bound applied to calls that count as relevant under-finline-small-functions๐ฆ.max-inline-insns-sizeโ the bound applied to calls that are optimized for size ๐ฆ. A little growth can be worth it, since it can expose optimization opportunities that inlining unlocks ๐ฑ.uninlined-function-insnsโ the number of instructions the inliner counts as function overhead, like the function prologue and epilogue ๐งฎ.uninlined-function-timeโ the extra time the inliner counts as function overhead, like the time it takes to run the prologue and epilogue โฑ๏ธ.inline-heuristics-hint-percentโ the scale, in percent, applied toinline-insns-single,inline-insns-single-O2, andinline-insns-autowhen the inline heuristics hint that inlining is super profitable (it'll enable later optimizations) ๐ ๐ฅ.uninlined-thunk-insns,uninlined-thunk-timeโ same as--param uninlined-function-insnsand--param uninlined-function-time, but these apply to function thunks ๐งต.inline-min-speedupโ when the estimated performance improvement of caller + callee runtime goes over this threshold (in percent), the function can be inlined no matter what the limits on--param max-inline-insns-singleand--param max-inline-insns-autosay ๐๐.large-function-insnsโ the limit that defines really large functions ๐. For functions bigger than this after inlining, inlining gets constrained by--param large-function-growth๐. This param mainly exists to avoid extreme compile times caused by the non-linear algorithms the back end uses ๐ซ .large-function-growthโ the max growth of large functions caused by inlining, in percent ๐. For example, a value of100limits large function growth to 2.0 times the original size โ๏ธ.large-unit-insnsโ the limit that defines a large translation unit ๐๏ธ. Growth from inlining into units bigger than this is limited by--param inline-unit-growth๐งฑ. For small units that might be too tight ๐ฅบ. Here's the example: a unit with function A (inline) and B, which just calls A three times. If B is small compared to A, the unit growth is 300% and yet that inlining is totally sane ๐ . But for really big units full of small inlineable functions, the overall unit growth limit is needed to stop exponential code size explosions ๐ฅ. So for smaller units, the size gets bumped up to--param large-unit-insnsbefore--param inline-unit-growthis applied ๐ช.lazy-modulesโ the max number of C++ module files that can be open at once when lazy loading ๐.inline-unit-growthโ the max overall growth of the compilation unit caused by inlining ๐ฟ. For example, a value of20limits unit growth to 1.2 times the original size ๐ซง. Cold functions (marked cold with an attribute, or by profile feedback) don't count toward the unit size ๐ฅถ.ipa-cp-unit-growthโ the max overall growth of the compilation unit caused by interprocedural constant propagation ๐ง. For example, a value of10limits unit growth to 1.1 times the original size ๐.ipa-cp-large-unit-insnsโ the size of a translation unit that the IPA-CP pass considers large ๐.large-stack-frameโ the limit that defines large stack frames ๐ฅ. While inlining, the algorithm tries not to grow past this limit too much ๐.large-stack-frame-growthโ the max growth of large stack frames caused by inlining, in percent ๐๏ธ. For example, a value of1000limits large stack frame growth to 11 times the original size ๐คฏ.max-inline-insns-recursive,max-inline-insns-recursive-autoโ the max number of instructions an out-of-line copy of a self-recursive inline function can grow into by doing recursive inlining ๐๐ธ.
--param max-inline-insns-recursive applies to functions declared inline. For functions not declared inline, recursive inlining only happens when -finline-functions (included in -O3) is enabled, and then --param max-inline-insns-recursive-auto applies instead ๐.
max-inline-recursive-depth,max-inline-recursive-depth-autoโ the max recursion depth used for recursive inlining ๐ชโจ.
Okay so --param max-inline-recursive-depth only handles functions you've marked inline ๐
. For functions that aren't declared inline, recursive inlining only kicks in when -finline-functions is on (it's part of -O3) โจ. In that case, --param max-inline-recursive-depth-auto takes over instead ๐ฆ.
min-inline-recursive-probabilityโ Recursive inlining is only worth it for functions that recurse deeply on average ๐ธ. For functions with shallow recursion, it can backfire by bloating the prologue or making the function body harder for other optimizers to handle ๐. When profile feedback is available (see-fprofile-generate), the real recursion depth can be guessed from how likely a function is to recurse through a given call expression. This parameter only allows inlining for call expressions whose probability is above the threshold, in percents.early-inlining-insnsโ Controls how much growth the early inliner is allowed to cause. Basically, it lets the early inliner do more inlining for code with a large abstraction penalty ๐ฅ.max-early-inliner-iterationsโ Caps how many iterations the early inliner runs. This bounds how many nested indirect calls it can resolve, and deeper chains get handled by late inlining instead ๐.comdat-sharing-probabilityโ The probability (in percent) that C++ inline functions with comdat visibility get shared across multiple compilation units โจ.modref-max-bases,modref-max-refs,modref-max-accessesโ The maximum number of base pointers, references and accesses that mod/ref analysis stores for a single function ๐.modref-max-testsโ The maximum number of tests the alias oracle can run to tell memory locations apart using mod/ref information. This should be bigger than--param modref-max-basesand--param modref-max-refs๐ง.modref-max-depthโ The maximum depth of the DFS walk used by modref escape analysis. Set it to0and the analysis is switched off completely ๐.modref-max-escape-pointsโ The maximum number of escape points modref tracks per SSA-name ๐.modref-max-adjustmentsโ The maximum amount the access range can be enlarged during modref dataflow analysis ๐.profile-func-internal-idโ Controls whether the function's internal id is used when looking things up in the profile database. If the value is0, the compiler uses an id based on the function's assembler name and filename instead. That makes old profile data more forgiving of source changes, like function reordering ๐ซถ.min-vect-loop-boundโ The minimum number of iterations below which loops are not vectorized when-ftree-vectorizeis used. The number of iterations after vectorization has to be greater than this value for vectorization to happen ๐.gcse-cost-distance-ratioโ A scaling factor for the maximum distance an expression can travel during GCSE optimizations. It's only supported in the code hoisting pass ๐ฆ. The bigger the ratio, the more aggressively simple expressions (ones costing less thangcse-unrestricted-cost) get hoisted. Setting it to0disables hoisting of simple expressions ๐ โโ๏ธ.gcse-unrestricted-costโ The cost, roughly measured as a single typical machine instruction, at which GCSE stops constraining how far an expression can travel. This is also only supported in the code hoisting pass ๐ . The lower the cost, the more aggressive the hoisting. Setting it to0lets every expression travel unrestricted distances โจ.max-hoist-depthโ The depth of search in the dominator tree for expressions to hoist. This keeps the hoisting algorithm from going quadratic. A value of0means no limit on the search, but it may slow down compilation of huge functions ๐ข.max-tail-merge-comparisonsโ The maximum number of similar bbs a bb gets compared with. This keeps tree tail merging from going quadratic ๐ธ.max-tail-merge-iterationsโ The maximum number of iterations of the pass over the function. It's there to limit compilation time in tree tail merging โฑ๏ธ.store-merging-allow-unalignedโ Lets the store merging pass introduce unaligned stores, but only if that's legal to do ๐.max-stores-to-mergeโ The maximum number of stores the store merging pass will try to merge into wider stores ๐ง.max-store-chains-to-trackโ The maximum number of store chains tracked at the same time while trying to merge them into wider stores in the store merging pass ๐ฆ.max-stores-to-trackโ The maximum number of stores tracked at the same time while trying to merge them into wider stores in the store merging pass ๐.max-unrolled-insnsโ The maximum number of instructions a loop can have and still be unrolled. If a loop does get unrolled, this parameter also decides how many times the loop code is unrolled ๐.max-average-unrolled-insnsโ The maximum number of instructions, biased by how likely they are to execute, that a loop can have and still be unrolled. If it gets unrolled, this parameter also decides how many times the loop code is unrolled ๐.max-unroll-timesโ The maximum number of unrollings of a single loop ๐ข.max-peeled-insnsโ The maximum number of instructions a loop can have and still be peeled. If a loop is peeled, this parameter also decides how many times the loop code is peeled ๐.max-peel-timesโ The maximum number of peelings of a single loop ๐.max-peel-branchesโ The maximum number of branches on the hot path through the peeled sequence ๐ฅ.max-completely-peeled-insnsโ The maximum number of insns in a completely peeled loop โจ.max-completely-peel-timesโ The maximum number of iterations a loop can have and still be suitable for complete peeling ๐ง.max-completely-peel-loop-nest-depthโ The maximum depth of a loop nest suitable for complete peeling ๐ช.max-unswitch-insnsโ The maximum number of insns in an unswitched loop ๐.max-unswitch-depthโ The maximum depth of a loop nest that can be unswitched ๐.lim-expensiveโ The minimum cost for an expression to count as expensive during loop invariant motion ๐ธ.min-loop-cond-split-probโ When FDO profile information is available, this specifies the minimum probability a semi-invariant condition statement needs before it triggers a loop split ๐ช.iv-consider-all-candidates-boundโ The bound on the number of candidates for induction variables. Below this number, every candidate is considered for each use in induction variable optimizations. Above it, only the most relevant ones get considered, so the time complexity doesn't go quadratic ๐งฎ.iv-max-considered-usesโ Induction variable optimizations give up on any loop that has more induction variable uses than this ๐.iv-always-prune-cand-set-boundโ If the candidate set has fewer members than this value, the compiler always tries to remove unnecessary ivs from the set whenever it adds a new one ๐งน.avg-loop-niterโ The average number of iterations of a loop ๐.dse-max-object-sizeโ The maximum size (in bytes) of objects that dead store elimination tracks bytewise. Bigger values can mean bigger compilation times ๐.dse-max-alias-queries-per-storeโ The maximum number of queries into the alias oracle per store. Bigger values mean longer compilation times, but they may remove more dead stores ๐๏ธ.scev-max-expr-sizeโ The bound on the size of expressions used in the scalar evolutions analyzer. Large expressions slow the analyzer down ๐.scev-max-expr-complexityโ The bound on how complex the expressions in the scalar evolutions analyzer can be. Complex expressions slow the analyzer down too ๐คฏ.max-tree-if-conversion-phi-argsโ The maximum number of arguments a PHI can have and still be supported by TREE if conversion, unless the loop is marked with a simd pragma ๐.vect-max-layout-candidatesโ The maximum number of possible vector layouts (such as permutations) to consider when optimizing code that is going to be vectorized ๐งฉ.vect-max-version-for-alignment-checksโ The maximum number of run-time checks that can be done when the vectorizer does loop versioning for alignment ๐.vect-max-version-for-alias-checksโ The maximum number of run-time checks that can be done when the vectorizer does loop versioning for alias ๐.vect-max-peeling-for-alignmentโ The maximum number of loop peels the vectorizer can use to improve access alignment. A value of-1means there's no limit ๐ซง.max-iterations-to-trackโ The maximum number of loop iterations the brute-force algorithm for analyzing a loop's iteration count will try to evaluate ๐ต๏ธโโ๏ธ.hot-bb-count-fractionโ The denominatornof the fraction1/nof the maximal execution count of a basic block in the entire program. A basic block needs at least that much execution to be considered hot. The default is10000, which means a basic block counts as hot if its execution count is greater than1/10000of the maximal execution count. A value of0means it's never considered hot. Used in non-LTO mode ๐ฅ.hot-bb-count-ws-permilleโ The number of most-executed permilles, ranging from0to1000, of the profiled execution of the entire program. A basic block's execution count has to be part of that slice to count as hot. The default is990, which means a basic block is hot if its execution count contributes to the upper 990 permilles, or 99.0%, of the profiled execution of the entire program. A value of0means it's never considered hot. Used in LTO mode ๐.hot-bb-frequency-fractionโ This one is the denominator n of the fraction 1/n of the entry block's execution frequency that a basic block in a function needs to reach before it counts as hot ๐ฅ. The default is1000, so a basic block is hot if it runs more often than 1/1000 of the entry block's frequency. Setting it to0means nothing is ever considered hot ๐ง.unlikely-bb-count-fractionโ Here the denominator n is for the fraction 1/n of the total profiled runs of the whole program. If a basic block's execution count falls below that, it's considered unlikely to run ๐. The default is20, which means a block is unlikely if it runs in fewer than 1/20 (that's 5%) of the program's runs. Setting it to0means every block is always considered unlikely.max-predicted-iterationsโ The most loop iterations GCC will predict statically โจ. This comes in clutch when a function has one loop with a known bound and another with an unknown bound. The known count gets predicted correctly, but the unknown one averages out to roughly 10, so the unbounded loop looks artificially cold next to the other one ๐ฅถ.builtin-expect-probabilityโ Controls how likely the expression is to have the specified value ๐ฏ. It takes a percentage, so anywhere from0to100.builtin-string-cmp-inline-lengthโ The maximum length of a constant string for a builtin string comparison call that's eligible to be inlined ๐งต.align-thresholdโ Picks a fraction of the maximum execution frequency of a basic block within a function, and uses it to decide whether that block gets aligned ๐.align-loop-iterationsโ Any loop that's expected to iterate at least this many times gets aligned ๐.tracer-dynamic-coverage,tracer-dynamic-coverage-feedbackโ These cap superblock formation once a given percentage of the executed instructions is covered ๐ง. It stops the code from bloating for no reason. The-feedbackversion only matters when profile feedback is available. Real profiles are way less balanced than statically estimated ones, so that threshold can be a bit higher ๐ .tracer-max-code-growthโ Tail duplication stops once code growth hits this percentage ๐. It's kind of an artificial limit, since most duplicates get cleaned up later in cross jumping, so you can set it much higher than the growth you actually want ๐คทโโ๏ธ.tracer-min-branch-ratioโ Reverse growth stops when the reverse probability of the best edge drops below this threshold, given as a percentage ๐.tracer-min-branch-probability,tracer-min-branch-probability-feedbackโ Forward growth stops if the best edge's probability is lower than this threshold ๐ฆ. Same deal as the dynamic coverage pair:tracer-min-branch-probability-feedbackis for compiling with profile feedback, andtracer-min-branch-probabilityis for compiling without it. The feedback one needs to be more conservative (higher) so the tracer actually does its thing ๐.stack-clash-protection-guard-sizeโ Sets the size of the operating system's stack guard, written as 2 raised to num bytes ๐ก๏ธ. Bigger values can mean fewer explicit probes.
โ ๏ธ If this value is larger than the operating system's guard, your code is left open to stack clash style attacks. Yikes ๐ญ.
stack-clash-protection-probe-intervalโ Stack clash protection probes the stack as space gets allocated ๐. This param controls the maximum distance between those probes, written as 2 raised to num bytes. Bigger values can cut down on explicit probes too.
โ ๏ธ Same warning here: if the value is larger than the operating system's guard, the code stays vulnerable to stack clash style attacks ๐.
max-cse-path-lengthโ The maximum number of basic blocks on a path that CSE looks at ๐ค๏ธ.max-cse-insnsโ The maximum number of instructions CSE processes before it flushes ๐ฟ.ggc-min-expandโ GCC has its own garbage collector for managing memory ๐๏ธ. This sets the minimum percentage the collector's heap can grow between collections. Tuning it might speed up compilation, but it has zero effect on code generation ๐.
The default is 30% + 70% * (RAM/1GB), with an upper bound of 100% when RAM is at least 1GB. If "getrlimit" is available, "RAM" means the smaller of actual RAM and RLIMIT_DATA or RLIMIT_AS. If GCC can't work out RAM on a platform, it falls back to the lower bound of 30%. Setting this and ggc-min-heapsize both to zero forces a full collection every single chance it gets. That's extremely slow, but it can be useful for debugging ๐ข.
ggc-min-heapsizeโ The minimum heap size the garbage collector lets build up before it starts collecting ๐งน. The first collection happens once the heap grows byggc-min-expand%pastggc-min-heapsize. Again, this can speed up compilation but doesn't touch code generation.
The default is the smaller of RAM/8, RLIMIT_RSS, or a limit meant to keep RLIMIT_DATA or RLIMIT_AS from being exceeded. The lower bound is 4096 (four megabytes) and the upper bound is 131072 (128 megabytes). If GCC can't calculate RAM on a platform, the lower bound gets used. Setting this super large effectively turns garbage collection off ๐ซ. Setting it and ggc-min-expand to zero triggers a full collection at every opportunity.
max-reload-search-insnsโ How far back reload looks for an equivalent register, counted in instructions ๐. Higher values mean more aggressive optimization, and compilation takes longer for probably slightly better performance ๐โโ๏ธ.max-cselib-memory-locationsโ The maximum number of memory locations cselib considers ๐ง . Higher values mean more aggressive optimization, which slows compilation down for probably slightly better performance ๐.max-sched-ready-insnsโ The maximum number of ready-to-issue instructions the scheduler looks at any given time during the first scheduling pass ๐. Higher values mean more thorough searches, which makes compilation slower for probably very little benefit ๐.max-sched-region-blocksโ The maximum number of blocks in a region that can be considered for interblock scheduling ๐งฉ.max-pipeline-region-blocksโ The maximum number of blocks in a region that can be considered for pipelining in the selective scheduler ๐ข.max-sched-region-insnsโ The maximum number of insns in a region that can be considered for interblock scheduling ๐ง.max-pipeline-region-insnsโ The maximum number of insns in a region that can be considered for pipelining in the selective scheduler ๐.min-spec-probโ The minimum probability, in percent, of reaching a source block for interblock speculative scheduling ๐ฒ.max-sched-extend-regions-itersโ The maximum number of trips through the CFG when extending regions ๐. Setting this to0disables region extensions ๐ โโ๏ธ.max-sched-insn-conflict-delayโ The maximum conflict delay an insn can have and still be considered for speculative motion ๐ฐ๏ธ.sched-spec-prob-cutoffโ The minimum probability of speculation success, in percent, needed before speculative insns get scheduled ๐ฏ.sched-state-edge-prob-cutoffโ The minimum probability an edge needs to have before the scheduler saves its state across it ๐พ.sched-mem-true-dep-costโ The minimum distance, in CPU cycles, between a store and a load that target the same memory locations ๐ง โฑ๏ธ.selsched-max-lookaheadโ The maximum size of the lookahead window in selective scheduling ๐. It's the depth of the search for available instructions.selsched-max-sched-timesโ The maximum number of times an instruction gets scheduled during selective scheduling ๐. This caps how many iterations the instruction can be pipelined through.selsched-insns-to-renameโ The maximum number of best instructions in the ready list that get considered for renaming in the selective scheduler โ๏ธ.sms-min-scโ The minimum stage count that the swing modulo scheduler generates ๐ก.max-last-value-rtlโ The maximum size, measured in RTLs, that the combiner can record in an expression as the last known value of a pseudo register ๐.max-combine-insnsโ The maximum number of instructions the RTL combiner tries to combine ๐งท.max-combine-search-insnsโ The maximum number of instructions the RTL combiner searches to find the next use of a given register definition ๐. If it hits this limit without finding a use, the combiner stops trying to optimize that definition ๐.
Right now this limit only kicks in after certain successful combination attempts, but it could get extended to other cases in the future ๐ฎ.
integer-share-limitโ Small integer constants can use a shared data structure, which saves memory and speeds things up ๐๏ธ. This sets the maximum value of a shared integer constant.ssp-buffer-sizeโ The minimum size of buffers (arrays, basically) that get stack smashing protection when-fstack-protectoris used ๐ก๏ธ.
Before Ubuntu 10.10 this default was "8". Currently it's "4", so more functions get protected by the stack protector ๐.
min-size-for-stack-sharingโ ๐ง The smallest size a variable needs to be before it can join in on stack slot sharing when you're not optimizing. Tiny variables are left out. ๐ธmax-jump-thread-duplication-stmtsโ ๐ The max number of statements a block can have when it needs to get duplicated during jump threading. Any bigger and it's a no from the compiler. ๐ โโ๏ธmax-jump-thread-pathsโ ๐ฆ The max number of paths the compiler will check while hunting for jump threading chances. When it reaches a block, it only looks at incoming edges if (paths searched so far) ร (incoming edges) doesn't blow past this limit. Not every edge gets a turn, bestie. ๐max-fields-for-field-sensitiveโ โจ The max number of fields in a structure that get treated in a field sensitive way during pointer analysis. ๐ซถprefetch-latencyโ โฐ An estimate of how many instructions run on average before a prefetch finishes. The distance the prefetch reaches ahead is proportional to this number. Crank it up and you may end up with fewer streams getting prefetched (seesimultaneous-prefetches). ๐ฅsimultaneous-prefetchesโ ๐โโ๏ธ The max number of prefetches that can run at the same time. ๐l1-cache-line-sizeโ ๐ How big one cache line is in the L1 data cache, in bytes. ๐l1-cache-sizeโ ๐ How big the L1 data cache is, in kilobytes. ๐งl2-cache-sizeโ ๐ How big the L2 data cache is, in kilobytes. ๐prefetch-dynamic-stridesโ ๐ธ Decides whether the loop array prefetch pass should slap on software prefetch hints for strides that aren't constant. Sometimes that's a total win, but a non-constant stride makes it hard to tell when the hints are actually worth it, so it's a bit of a gamble. ๐ฒ
Set it to 1 if you want prefetch hints issued for non-constant strides. Set it to 0 if you only want hints for strides that are known to be constant and below prefetch-minimum-stride. ๐ซถ
prefetch-minimum-strideโ ๐ฆ The smallest constant stride, in bytes, where prefetch hints start kicking in. If the stride is below this threshold, no prefetch hints get issued. ๐
This one is a big deal for processors with hardware prefetchers, since the hardware and software prefetchers can end up fighting each other. If the hardware prefetchers have a max stride they can handle, put that number here so the software prefetchers don't step on their toes. ๐
A value of -1 means there's no threshold at all, so prefetch hints can be issued for any constant stride. โจ
Heads up: this setting only matters for strides that are known and constant. ๐ง
destructive-interference-size,constructive-interference-sizeโ ๐ These are the values behind the C++17 variablesstd::hardware_destructive_interference_sizeandstd::hardware_constructive_interference_size. ๐คฏ
The destructive interference size is the minimum recommended offset between two independent objects that get accessed concurrently. The constructive interference size is the maximum recommended size of contiguous memory that gets accessed together. Usually both match the size of an L1 cache line for the target, in bytes. For a generic target that covers a whole range of L1 cache line sizes, the constructive size is typically the small end of the range and the destructive size is the large end. ๐
The destructive interference size is meant for layout, so it has ABI impact. Its default isn't expected to stay stable, and on some targets it changes with -mtune. So using it somewhere ABI stability really matters, like a library's public interface, is strongly discouraged. If you do use it there anyway, you can lock the value in with this option. ๐จ
The constructive interference size is way less sensitive, since it's usually only used in a static_assert to make sure a type fits inside a cache line. ๐
See also -Winterference-size. ๐
loop-interchange-max-num-stmtsโ ๐ The max number of statements a loop can have and still get interchanged. ๐ธloop-interchange-stride-ratioโ ๐ The minimum ratio between the strides of two loops for interchange to be worth it. ๐min-insn-to-prefetch-ratioโ ๐งฎ The minimum ratio between the number of instructions and the number of prefetches needed to turn prefetching on in a loop. ๐ฆprefetch-min-insn-to-mem-ratioโ ๐งฎ The minimum ratio between the number of instructions and the number of memory references needed to turn prefetching on in a loop. ๐use-canonical-typesโ ๐ง Decides whether the compiler uses the "canonical" type system. This should always be1, since it's a much more efficient internal way to compare types in C++ and Objective-C++. ๐
But if bugs in the canonical type system are breaking your compilation, set it to 0 to turn canonical types off. ๐
switch-conversion-max-branch-ratioโ ๐ Switch initialization conversion won't build arrays bigger thanswitch-conversion-max-branch-ratiotimes the number of branches in the switch. Too big and it just says no. ๐ โโ๏ธswitch-lower-slow-alg-max-casesโ ๐ข The max number of cases that the slow switch lowering algorithms are allowed to handle. ๐ซmax-partial-antic-lengthโ ๐ The max length of the partial antic set computed during tree partial redundancy elimination (-ftree-pre) when you're optimizing at-O3and up. For some kinds of source code, the enhanced partial redundancy elimination can totally run away and eat all the memory on the host machine. This param caps the length of those sets so it can't go wild. ๐
Setting it to 0 lets the set length be unlimited, so no cap at all. ๐
rpo-vn-max-loop-depthโ ๐ช The max loop depth that gets value-numbered optimistically. When the limit gets hit, the innermostrpo-vn-max-loop-depthloops and the outermost loop in the loop nest get value-numbered optimistically, and the remaining ones don't. โจsccvn-max-alias-queries-per-accessโ ๐ The max number of alias-oracle queries the compiler will run while hunting for redundancies in loads and stores. If the limit gets hit, the search is aborted and that load or store doesn't count as redundant. The number of queries is algorithmically capped at the number of stores on all paths from the load to the function entry. ๐งตira-max-loops-numโ ๐ IRA uses regional register allocation by default. If a function has more loops than this number, only the given number of the most frequently executed loops end up forming regions for regional register allocation. ๐ira-max-conflict-table-sizeโ ๐๏ธ IRA has a fancy algorithm for compressing the conflict table, but huge functions can still need a ton of memory for it. If the conflict table for a function could be bigger than this many MB, the register allocator switches to a faster, simpler, and lower-quality algorithm that doesn't build a pseudo-register conflict table at all. ๐ฅฒira-loop-reserved-regsโ ๐งบ IRA can estimate register pressure more accurately inside loops, which helps when deciding whether to move loop invariants (see-O3). This param sets how many available registers are reserved for other purposes. The default is the best value found from loads of experiments. ๐งชira-consider-dup-in-all-altsโ ๐ฏ Tells IRA to really weigh a matching constraint (a duplicated operand number) across every available alternative for the preferred register class. If it's set to zero, IRA only respects the matching constraint when it's the only available alternative with a suitable register class. Otherwise, IRA checks every available alternative for the preferred register class, even after it's found one that works, and still respects the qualified matching constraint it found. ๐งฉira-simple-lra-insn-thresholdโ ๐ The approximate number of function insns, in units of 1K, that triggers simple local RA. โlra-inheritance-ebb-probability-cutoffโ ๐งฌ LRA tries to reuse values that were reloaded into registers in later insns. This is called inheritance, and it uses the EBB as the region for the optimization. This param sets the minimum fall-through edge probability, as a percentage, for adding a BB to an inheritance EBB in LRA. The default was picked from loads of SPEC2000 runs on x86-64. ๐๏ธโโ๏ธloop-invariant-max-bbs-in-loopโ ๐๏ธ Loop invariant motion can get super expensive, both in compile time and in compile-time memory, when loops are huge. Any loop with more basic blocks than this param won't get loop invariant motion done on it. ๐ซloop-max-datarefs-for-datadepsโ ๐ Building data dependencies is expensive for really big loops. This param limits how many data references in a loop get considered for data dependence analysis. Loops that are too large for that aren't handled by the optimizations that use loop data dependencies. ๐ โโ๏ธmax-vartrack-sizeโ ๐ต๏ธโโ๏ธ Sets the max number of hash table slots that can be used during variable tracking dataflow analysis for any function. If that limit gets exceeded while variable tracking at assignments is enabled, the analysis for that function gets retried without it, after all debug insns are removed from the function. If it's still too big even without debug insns, var tracking analysis is completely disabled for that function. Setting this to zero makes it unlimited. ๐
โ ๏ธ Heads up: the destructive interference size's default can shift between targets and with -mtune, so don't lean on it for ABI-sensitive stuff. Pin it down with the option instead. ๐
max-vartrack-expr-depthโ ๐ okay so this one sets how many recursion levels the compiler can dig through when it tries to map variable names or debug temporaries to value expressions. It's a trade: more compile time for more complete debug info โจ. Set it too low and value expressions that could've made it into the debug info just get skipped ๐ญ. Set it higher and the compiler can find fancier debug expressions, but compile time and memory use may grow ๐ซ .max-debug-marker-countโ ๐ this is a cap on how many debug markers (like begin stmt markers) you're allowed to have, so things don't blow up during inlining or expansion to RTL ๐. If a function has more of these gimple stmts than the limit, they get dropped from the inlined copy of the function and from its RTL expansion. Main character energy, but make it reasonable ๐ .min-nondebug-insn-uidโ ๐ง uids start counting from this number for nondebug insns. Everything below it is reserved exclusively for debug insns created by-fvar-tracking-assignments. BUT if that reserved range runs out, debug insns can still get (non-overlapping) uids above the line ๐.ipa-sra-deref-prob-thresholdโ ๐ฆ IPA-SRA only swaps a pointer that's known not to be NULL for one or more new parameters when the probability of it being dereferenced is higher than this value. The probability is in percent, relative to function entry ๐.ipa-sra-ptr-growth-factorโ ๐ธ IPA-SRA only replaces a pointer to an aggregate with one or more new parameters when their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter. No bloating allowed, bestie ๐ โโ๏ธ.ipa-sra-ptrwrap-growth-factorโ ๐ this is the extra growth allowed on top of that, for total size of the new parameters. It applies when IPA-SRA replaces a pointer to an aggregate that points to a local variable the caller only writes to and passes along as an argument to other functions ๐ซถ.ipa-sra-max-replacementsโ ๐ the max number of pieces of an aggregate that IPA-SRA tracks. Because of that, it's also the max number of replacements of a formal parameter โจ.sra-max-scalarization-size-Ospeed,sra-max-scalarization-size-Osizeโ ๐ฅ so the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) are obsessed with swapping scalar parts of aggregates for uses of independent scalar variables. These two params control the max size, in storage units, of an aggregate that's even considered for replacement. The first one is for when you're compiling for speed, the second is for when you're compiling for size ๐.sra-max-propagationsโ ๐ the max number of artificial accesses that Scalar Replacement of Aggregates (SRA) will track per local variable, so it can do copy propagation ๐ง .tm-max-aggregate-sizeโ ๐ท when copying thread-local variables inside a transaction, this sets the size in bytes after which variables get saved with the logging functions instead of save/restore code sequence pairs. This only matters when using-fgnu-tm๐.graphite-max-nb-scop-paramsโ ๐ง to avoid exponential effects in the Graphite loop transforms, the number of parameters in a Static Control Part (SCoP) is bounded. Set it to0if you want to lift the bound ๐. A variable whose value is unknown at compile time and defined outside a SCoP counts as a parameter of the SCoP โจ.hardcfr-max-blocksโ ๐ก๏ธ this one turns off-fharden-control-flow-redundancyfor functions with more blocks than the value you set.0removes any limit at all ๐ซก.hardcfr-max-inline-blocksโ โก this forces-fharden-control-flow-redundancyto use out-of-line checking for functions with more basic blocks than the value you set ๐ธ.loop-block-tile-sizeโ ๐ญ loop blocking or strip mining transforms (enabled with-floop-blockor-floop-strip-mine) strip mine each loop in the loop nest by a given number of iterations. You can change that strip length using this parameter ๐ .ipa-jump-function-lookupsโ ๐ this specifies the number of statements visited during jump function offset discovery. Very detective behavior ๐ต๏ธโโ๏ธ.ipa-cp-value-list-sizeโ ๐ IPA-CP tries to track every possible value and type passed to a function's parameter so it can propagate them and perform devirtualization. This is the max number of values and types it stores per one formal parameter of a function ๐.ipa-cp-eval-thresholdโ ๐งฎ IPA-CP calculates its own score for cloning profitability heuristics, then performs the cloning opportunities whose scores exceedipa-cp-eval-threshold๐ฏ.ipa-cp-max-recursive-depthโ ๐ the max depth of recursive cloning for a self-recursive function. Don't spiral ๐.ipa-cp-min-recursive-probabilityโ ๐ฒ recursive cloning only happens when the probability of the call being executed exceeds this parameter ๐ซง.ipa-cp-profile-count-baseโ ๐ when you use-fprofile-use, IPA-CP looks at the measured execution count of a call graph edge at this percentage position in its histogram, and uses that as the basis for its heuristics calculation ๐ฐ.ipa-cp-recursive-freq-factorโ ๐ the number of times interprocedural copy propagation expects recursive functions to call themselves. Iconic self-reference behavior ๐.ipa-cp-recursion-penaltyโ ๐ค a percentage penalty that recursive functions get when they're evaluated for cloning. Not it ๐.ipa-cp-single-call-penaltyโ ๐ a percentage penalty for functions containing a single call to another function, applied when they're evaluated for cloning ๐ซ .ipa-max-agg-itemsโ ๐ IPA-CP can also propagate a number of scalar values passed in an aggregate. This one controls the max number of those values per one parameter ๐.ipa-cp-loop-hint-bonusโ ๐ when IPA-CP figures out that a cloning candidate would make the number of loop iterations known, it adds a bonus ofipa-cp-loop-hint-bonusto that candidate's profitability score ๐.ipa-max-loop-predicatesโ ๐ฎ the max number of different predicates IPA uses to describe when loops in a function have known properties โจ.ipa-max-aa-stepsโ ๐งญ while analyzing function bodies, IPA-CP uses alias analysis to track values pointed to by function parameters. So it doesn't spend forever on huge functions, it gives up and treats all memory as clobbered after examiningipa-max-aa-stepsstatements that modify memory ๐ฅฑ.ipa-max-switch-predicate-boundsโ ๐ the max number of boundary endpoints of case ranges in a switch statement. For a switch that goes over this limit, IPA-CP won't build the cloning cost predicate used to estimate cloning benefit for the switch's default case ๐ โโ๏ธ.ipa-max-param-expr-opsโ ๐งฉ IPA-CP analyzes conditional statements that reference a function parameter to estimate cloning benefit for a certain constant value. But if a parameter expression has more operations thanipa-max-param-expr-ops, it's considered too complicated and isn't handled by IPA analysis ๐ตโ๐ซ.lto-partitionsโ ๐งฑ the desired number of partitions produced during WHOPR compilation. The number of partitions should be more than the number of CPUs used for compilation ๐ฅ๏ธ.lto-min-partitionโ ๐ชถ the size of the minimal partition for WHOPR (in estimated instructions). This keeps you from splitting very small programs into way too many partitions ๐.lto-max-partitionโ ๐ฐ the size of the max partition for WHOPR (in estimated instructions), giving an upper bound for the individual size of a partition. It's only meant for use with balanced partitioning โ๏ธ.lto-partition-locality-frequency-cutoffโ โ๏ธ the denominator n of the fraction 1/n of the execution frequency of a callee to be cloned for a particular caller. The special value0means always clone, no cut-off ๐ซถ.lto-partition-locality-size-cutoffโ ๐ the size cut-off for a callee, including inlined calls, to be cloned for a particular caller ๐ .lto-max-locality-partitionโ ๐บ๏ธ the maximal size of a locality partition for LTO (in estimated instructions). A value of0means the default value gets used ๐ท.lto-max-streaming-parallelismโ ๐ the maximal number of parallel processes used for LTO streaming. Teamwork makes the dream work ๐ฏโโ๏ธ.cxx-max-namespaces-for-diagnostic-helpโ ๐ the max number of namespaces to check for suggestions when C++ name lookup fails for an identifier. Helpful but please don't overdo it ๐.sink-frequency-thresholdโ ๐ the max relative execution frequency (in percent) of the target block, compared to a statement's original block, that still allows that statement to be sunk. Bigger numbers mean more aggressive statement sinking. Statements with memory operands get a small positive adjustment, because they're even more profitable to sink ๐ฐ.max-stores-to-sinkโ ๐ the max number of conditional store pairs that can be sunk. Set it to0if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is disabled ๐ซ.case-values-thresholdโ ๐ช the smallest number of different values for which it's best to use a jump-table instead of a tree of conditional branches. If the value is0, the default for the machine is used ๐ฏ.jump-table-max-growth-ratio-for-sizeโ ๐ฆ the max code size growth ratio when expanding into a jump table (in percent). This param is used when optimizing for size ๐ค.jump-table-max-growth-ratio-for-speedโ ๐๏ธ the max code size growth ratio when expanding into a jump table (in percent). This param is used when optimizing for speed ๐จ.tree-reassoc-widthโ ๐ถ sets the max number of instructions executed in parallel in a reassociated tree. If it has a non-zero value, this overrides the target-dependent heuristics that are used by default โจ.sched-pressure-algorithm: okay so this one lets you pick between the two versions of-fsched-pressure๐ Algorithm 1 is the OG and is the more likely to stop instructions from getting reordered ๐ Algorithm 2 was built as a compromise between algorithm 1's pretty cautious energy and the rather aggressive default scheduler ๐ฅ It leans harder on having a regular register file and accurate register pressure classes โจ See haifa-sched.cc in the GCC sources for the full tea. The default choice depends on the target ๐max-slsr-cand-scan: caps how many existing candidates get checked when hunting for a basis for a new straight-line strength reduction candidate ๐งasan-globals: turns on buffer overflow detection for global objects ๐ธ This is on by default when you use-fsanitize=address. To turn off global objects protection, use--param asan-globals=0.asan-stack: buffer overflow detection for stack objects, and it's on by default with-fsanitize=address๐ To disable stack protection, use--param asan-stack=0option.asan-instrument-reads: buffer overflow detection for memory reads ๐ Also on by default with-fsanitize=address. To turn off memory reads protection, use--param asan-instrument-reads=0.asan-instrument-writes: buffer overflow detection for memory writes โ๏ธ On by default with-fsanitize=address. To turn off memory writes protection, use--param asan-instrument-writes=0option.asan-memintrin: detection for built-in functions ๐ฆ On by default with-fsanitize=address. To turn off built-in functions protection, use--param asan-memintrin=0.asan-use-after-return: detection of use-after-return ๐ซถ On by default with the-fsanitize=addressoption. To turn it off, use--param asan-use-after-return=0.
Note: By default the check is disabled at run time ๐ญ To turn it on, add"detect_stack_use_after_return=1"to theASAN_OPTIONSenvironment variable.
asan-instrumentation-with-call-threshold: if the number of memory accesses in the function being instrumented is greater than or equal to this number, ASan uses callbacks instead of inline checks ๐ E.g. to skip the inline code entirely, use--param asan-instrumentation-with-call-threshold=0.asan-kernel-mem-intrinsic-prefix: if nonzero, calls to "memcpy", "memset" and "memmove" get prefixed with__asan_or__hwasan_for-fsanitize=kernel-addressor-fsanitize=kernel-hwaddress, respectively ๐งhwasan-instrument-stack: hwasan instrumentation for statically sized stack-allocated variables โจ It's on by default with-fsanitize=hwaddressand off by default with-fsanitize=kernel-hwaddress. To turn it off, use--param hwasan-instrument-stack=0, and to turn it on, use--param hwasan-instrument-stack=1.hwasan-random-frame-tag: when you're using stack instrumentation, tags for stack variables come from a deterministic sequence that starts at a random tag for each frame ๐ With this unset, the tags use the same sequence but start from 1. It's enabled by default for-fsanitize=hwaddressand unavailable for-fsanitize=kernel-hwaddress. To disable it, use--param hwasan-random-frame-tag=0.hwasan-instrument-allocas: hwasan instrumentation for dynamically sized stack-allocated variables ๐ It's on by default with-fsanitize=hwaddressand off by default with-fsanitize=kernel-hwaddress. To turn it off, use--param hwasan-instrument-allocas=0, and to turn it on, use--param hwasan-instrument-allocas=1.hwasan-instrument-reads: hwasan checks on memory reads ๐ Enabled by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To stop checking memory reads, use--param hwasan-instrument-reads=0.hwasan-instrument-writes: hwasan checks on memory writes โจ Enabled by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To stop checking memory writes, use--param hwasan-instrument-writes=0.hwasan-instrument-mem-intrinsics: hwasan instrumentation for builtin functions ๐ Enabled by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To turn off instrumentation of builtin functions, use--param hwasan-instrument-mem-intrinsics=0.use-after-scope-direct-emission-threshold: if a local variable's size in bytes is smaller than or equal to this number, shadow memory gets poisoned (or unpoisoned) directly instead of going through run-time callbacks ๐tsan-distinguish-volatile: emits special instrumentation for accesses to volatiles ๐ฅtsan-instrument-func-entry-exit: emits instrumentation calls to__tsan_func_entry()and__tsan_func_exit()๐ฆmax-fsm-thread-path-insns: the maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path ๐threader-debug:threader-debug=[none|all]turns on verbose dumping of the threader solver ๐งparloops-chunk-size: chunk size of the omp schedule for loops parallelized by parloops ๐ธparloops-schedule: schedule type of the omp schedule for loops parallelized by parloops, which can be static, dynamic, guided, auto, or runtime ๐parloops-min-per-thread: the minimum number of iterations per thread of an innermost parallelized loop where the parallel version beats the single-threaded one ๐ง Heads up that for a parallelized loop nest, the minimum number of iterations of the outermost loop per thread is two.max-ssa-name-query-depth: the maximum recursion depth when querying properties of SSA names in things like fold routines ๐ One level of recursion means following one use-def chain.max-speculative-devirt-maydefs: the maximum number of may-defs we analyze while looking for a must-def that specifies the dynamic type of an object invoking a virtual call we might be able to speculatively devirtualize ๐ranger-debug: sets the type of debug output issued for ranges ๐ซถunroll-jam-min-percent: the minimum percentage of memory references that must be optimized away for unroll-and-jam to count as profitable โจunroll-jam-max-unroll: the maximum number of times the outer loop gets unrolled by unroll-and-jam ๐max-rtl-if-conversion-unpredictable-cost: the maximum permissible cost for the sequence the RTL if-conversion pass would generate for a branch that's considered unpredictable ๐max-variable-expansions-in-unroller: if-fvariable-expansion-in-unrolleris used, this is the maximum number of times an individual variable gets expanded during loop unrolling ๐partial-inlining-entry-probability: the maximum probability of the entry BB of a split region (as a percent relative to the function's entry BB) that still lets partial inlining happen ๐max-tracked-strlens: the maximum number of strings the strlen optimization pass will track string lengths for ๐งgcse-after-reload-partial-fraction: the threshold ratio for performing partial redundancy elimination after reload ๐ฅgcse-after-reload-critical-fraction: the threshold ratio of critical edges' execution count that allows redundancy elimination after reload ๐max-loop-header-insns: the maximum number of insns in a loop header duplicated by the copy loop headers pass ๐vect-epilogues-nomask: enables loop epilogue vectorization using a smaller vector size ๐ฆvect-partial-vector-usage: controls when the loop vectorizer considers partial vector loads and stores as an alternative to falling back to scalar code ๐ The parameter only has an effect on targets that support partial vector loads and stores. The values mean:0: the vectorizer never uses partial vector loads and stores โ1: partial vector loads and stores are allowed if vectorization removes the need for the code to iterate โจ2: partial vector loads and stores are allowed in all loops ๐ธ
vect-inner-loop-cost-factor: the maximum factor the loop vectorizer applies to the cost of statements in an inner loop, relative to the loop being vectorized ๐ง The factor applied is the maximum of the estimated number of iterations of the inner loop and this parameter. The default value of this parameter is50.vect-induction-float: enables loop vectorization of floating point inductions ๐vect-force-slp: forces the use of SLP when vectorizing, and fails if that isn't possible ๐ฅvrp-block-limit: the maximum number of basic blocks before VRP switches to a lower-memory algorithm ๐งvrp-sparse-threshold: the maximum number of basic blocks before VRP uses a sparse bitmap cache ๐ซถvrp-switch-limit: the maximum number of outgoing edges in a switch before VRP won't process it ๐vrp-vector-threshold: the maximum number of basic blocks for VRP to use a basic cache vector ๐avoid-fma-max-bits: the maximum number of bits for which we avoid creating FMAs ๐
Okay so bestie, we're picking up right where the --param list was getting spicy ๐ถ๏ธโจ
fully-pipelined-fmaโ ๐ฆ This is a target setting that says whether the chip fully pipelines FMA instructions. If it's non-zero, reassociation weighs the perks of splitting FMA's multiplication part and addition part apart, assuming FMUL and FMA share the same units that can also handle FADD. Main character energy ๐sms-loop-average-count-thresholdโ ๐ธ A threshold on the average loop count that the swing modulo scheduler looks at.sms-dfa-historyโ ๐ The number of cycles the swing modulo scheduler peeks at when it checks for conflicts using DFA.graphite-allow-codegen-errorsโ ๐ Decides whether codegen errors should be ICEs when-fcheckingis on. ICE alert ๐งsms-max-ii-factorโ โจ A factor for tuning the upper bound the swing modulo scheduler uses when it schedules a loop.lra-max-considered-reload-pseudosโ ๐ The max number of reload pseudos that get considered while spilling a non-reload pseudo. So many pseudos, so little time ๐max-pow-sqrt-depthโ ๐ง The maximum depth of sqrt chains allowed when synthesizing exponentiation by a real constant.max-dse-active-local-storesโ ๐ The maximum number of active local stores in RTL dead store elimination. Bye bye, useless stores ๐asan-instrument-allocasโ ๐ก๏ธ Turns on asan protection for allocas and VLAs. Stay safe, bestie ๐ซถmax-iterations-computation-costโ ๐ The bound on how costly an expression can be when computing the number of iterations.max-isl-operationsโ ๐ The maximum number of isl operations.0means unlimited, which is giving no limits energy ๐ฅgraphite-max-arrays-per-scopโ ๐ฆ The maximum number of arrays per scop.max-vartrack-reverse-op-sizeโ โญ The max size of a loc list for which reverse ops should be added.fsm-scale-path-stmtsโ ๐ A scale factor applied to the number of statements in a threading path that crosses a loop backedge, when it gets compared against--param=max-jump-thread-duplication-stmts. Math-heavy but iconic ๐งฎuninit-control-dep-attemptsโ ๐ธ The maximum number of nested calls used to hunt for control dependencies during uninitialized variable analysis.uninit-max-chain-lenโ ๐ The maximum number of predicates anded together for each predicate ored in the normalized predicate chain.uninit-max-num-chainsโ โจ The maximum number of predicates ored together in the normalized predicate chain.uninit-max-prune-workโ ๐ The maximum amount of work spent pruning paths where the variable is always initialized. Don't overdo it, queen ๐sched-autopref-queue-depthโ ๐ง A control flag for the hardware autoprefetcher scheduler model. It's the number of lookahead cycles the model peeks into. At' ', it only enables the instruction sorting heuristic ๐loop-versioning-max-inner-insnsโ ๐ The maximum number of instructions an inner loop can have before the loop versioning pass says "nope, too big to copy" ๐ โโ๏ธloop-versioning-max-outer-insnsโ ๐ฆ The maximum number of instructions an outer loop can have before the loop versioning pass calls it too big to copy. Any instructions in inner loops that directly benefit from versioning get discounted, so they don't count against it โจssa-name-def-chain-limitโ โญ The maximum number of SSA_NAME assignments to follow when figuring out a property of a variable, like its value. This caps how many iterations or recursive calls GCC makes while optimizing certain statements or checking whether they're valid before it issues diagnostics. Boundaries are self-care ๐store-merging-max-sizeโ ๐ The maximum size of a single store merging region, in bytes.store-forwarding-max-distanceโ ๐ธ The maximum instruction distance that a small store forwarded to a larger load may stall. Setting'0'disables the cost checks for the avoid-store-forwarding pass ๐hash-table-verification-limitโ ๐ The number of elements that get hash table verification for each searched element.max-find-base-term-valuesโ ๐ง The maximum number of VALUEs handled during a singlefind_base_termcall.analyzer-max-enodes-per-program-pointโ ๐ฅ The maximum number of exploded nodes per program point within the analyzer. Once that's hit, analysis of that point wraps up ๐analyzer-max-constraintsโ ๐ The maximum number of constraints per state.analyzer-min-snodes-for-call-summaryโ ๐ The minimum number of supernodes within a function before the analyzer even considers summarizing its effects at call sites.analyzer-max-enodes-for-full-dumpโ ๐ The maximum depth of exploded nodes that should show up in a dot dump before it switches to a less verbose format ๐analyzer-max-recursion-depthโ ๐ฆ The maximum number of times a callsite can show up in a call stack within the analyzer. Once that's reached, analysis of a call that would recurse deeper gets terminated. Not today, recursion ๐analyzer-max-svalue-depthโ โจ The maximum depth of a symbolic value. Past that, the value gets approximated as unknown ๐คทโโ๏ธanalyzer-max-infeasible-edgesโ โญ The maximum number of infeasible edges to reject before a diagnostic gets declared infeasible.gimple-fe-computed-hot-bb-thresholdโ ๐ The number of executions a basic block needs before it counts as hot. This parameter is only used in the GIMPLE FE ๐งชanalyzer-bb-explosion-factorโ ๐ The maximum number ofafter supernodeexploded nodes within the analyzer per supernode, before analysis terminates ๐ฅanalyzer-text-art-string-ellipsis-thresholdโ ๐ The number of bytes at which string literals get ellipsized in analyzer text art diagrams ๐จanalyzer-text-art-ideal-canvas-widthโ ๐ธ The ideal width, in characters, of text art diagrams generated by the analyzer ๐analyzer-text-art-string-ellipsis-head-lenโ ๐ง The number of literal bytes shown at the head of a string literal in text art when it gets ellipsized โ๏ธanalyzer-text-art-string-ellipsis-tail-lenโ ๐ The number of literal bytes shown at the tail of a string literal in text art when it gets ellipsized โ๏ธranger-logical-depthโ ๐ The maximum depth of logical expression evaluation that ranger looks through when it evaluates outgoing edge ranges ๐งranger-recompute-depthโ ๐ฆ The maximum depth of instruction chains to consider for recomputation in the outgoing range calculator โป๏ธrelation-block-limitโ โญ The maximum number of relations the oracle will register in a basic block ๐งทtransitive-relations-work-boundโ ๐ A work bound for when transitive relations get discovered from existing relations ๐min-pagesizeโ ๐ฅ The minimum page size used for warning and early break vectorization purposes ๐openacc-kernelsโ ๐งช Specifies the mode for handling OpenACCkernelsconstructs. With--param=openacc-kernels=decompose, OpenACCkernelsconstructs get broken into parts, a sequence of compute constructs, and each part gets handled on its own. This one's still work in progress ๐ง With--param=openacc-kernels=parloops, OpenACCkernelsconstructs are handled en bloc by the parloops pass. This is the current default โopenacc-privatizationโ ๐ Controls whether the-fopt-info-omp-noteand applicable-fdump-tree-*-detailsoptions emit OpenACC privatization diagnostics. With--param=openacc-privatization=quiet, nothing gets diagnosed. This is the current default. With--param=openacc-privatization=noisy, diagnostics do get emitted ๐ฃcycle-accurate-modelโ ๐ฏ Says whether GCC should assume the scheduling description is mostly a cycle-accurate model of the target processor the code is meant to run on, when there are no cache misses. Nonzero means the selected scheduling model is accurate and probably describes an in-order processor, and scheduling should aggressively spill to fill any pipeline bubbles. This is the current default. Zero means the scheduling description might be unavailable or inaccurate, or maybe not applicable at all, like for modern out-of-order processors ๐
The following choices of name are available on AArch64 targets:
aarch64-vect-compare-costsโ ๐งฎ When vectorizing, GCC can try several different approaches and let the cost model pick the cheapest one. That includes:- Trying both SVE and Advanced SIMD, when SVE is available.
- Trying to use 64-bit Advanced SIMD vectors for the smallest data elements, rather than using 128-bit vectors for everything.
- Trying to use "unpacked" SVE vectors for smaller elements. This includes storing smaller elements in larger containers and accessing elements with extending loads and truncating stores.
aarch64-float-recp-precisionโ ๐ฆ The number of Newton iterations for calculating the reciprocal for thefloattype. The precision of division is proportional to this param when division approximation is enabled. The default value is1โจaarch64-double-recp-precisionโ ๐ The number of Newton iterations for calculating the reciprocal for thedoubletype. The precision of division is proportional to this param when division approximation is enabled. The default value is2๐aarch64-autovec-preferenceโ ๐ Forces an ISA selection strategy for auto-vectorization. The choices are:defaultโ uses the default heuristics.asimd-onlyโ uses only Advanced SIMD for auto-vectorization.sve-onlyโ uses only SVE for auto-vectorization.prefer-asimdโ uses both Advanced SIMD and SVE, but prefers Advanced SIMD when the costs are deemed equal.prefer-sveโ uses both Advanced SIMD and SVE, but prefers SVE when the costs are deemed equal.
aarch64-ldp-policyโ ๐ A fine-grained policy for load pairs. With--param=aarch64-ldp-policy=default, the policy of the tuning structure gets used. This is the current default. With--param=aarch64-ldp-policy=always,ldpgets emitted regardless of alignment. With--param=aarch64-ldp-policy=never,ldpis not emitted. With--param=aarch64-ldp-policy=aligned,ldponly gets emitted if the source pointer is aligned to at least double the alignment of the type ๐ซถ
aarch64-stp-policy is the fine-grained knob for store pairs ๐
. With --param=aarch64-stp-policy=default, you get whatever the tuning structure says, which is also the current default โจ. With --param=aarch64-stp-policy=always, GCC emits stp no matter what the alignment looks like ๐ฅ. With --param=aarch64-stp-policy=never, GCC does not emit stp at all ๐. With --param=aarch64-stp-policy=aligned, GCC only emits stp if the source pointer is aligned to at least double the alignment of the type ๐.
aarch64-ldp-alias-check-limitโ this caps how many alias checks the AArch64 load/store pair fusion pass does when it tries to form anldp/stp๐ฆ. Higher numbers make the pass more aggressive about re-ordering loads over stores, but compile time goes up to pay for it ๐ฅฒ.aarch64-ldp-writebackโ this controls which writeback opportunities the AArch64 load/store pair fusion pass bothers with ๐ธ. A value of0turns writeback handling off completely ๐ซ. A value of1means it tries to form pairs that involve one or more existing individual writeback accesses wherever it can ๐ซถ. A value of2means it also goes out of its way to opportunistically create writeback opportunities by folding in trailing destructive updates of the base register used by a pair ๐.aarch64-loop-vect-issue-rate-nitersโ some AArch64 CPUs tuning tries to weigh both latencies and issue rates when deciding whether a loop should be vectorized with SVE, vectorized with Advanced SIMD, or not vectorized at all ๐ง . If you set this ton, GCC skips that heuristic for loops that are known to run in fewer thannAdvanced SIMD iterations โญ.aarch64-vect-unroll-limitโ the vectorizer checks the available tuning info to decide whether unrolling the main vectorized loop would help, and by how much ๐. This param sets the upper bound on how much it's allowed to unroll that main loop ๐. The default value is four ๐.
The following choices of name are available on GCN targets ๐ง:
gcn-preferred-vectorization-factorโ the preferred vectorization factor ๐. Your options aredefault,32, or64โจ.
The following choices of name are available on i386 and x86_64 targets ๐ :
x86-stlf-window-ninsnsโ the number of instructions above which the STFL stall penalty can be compensated ๐ซง.x86-stv-max-visitsโ the maximum number of use and def visits allowed while discovering a STV chain before the discovery gets aborted ๐.
๐ฆ Program Instrumentation Options ๐ฆ
okay so GCC has a whole bunch of command-line options that bolt run-time instrumentation onto the code it normally generates ๐. Instrumentation can be for collecting profiling stats so you can find your program's hot spots, doing code coverage analysis, or running profile-guided optimizations ๐. Another class is adding run-time checks that catch programming errors like invalid pointer dereferences or out-of-bounds array accesses, plus sneaky deliberate attacks like stack smashing or C++ vtable hijacking ๐ก๏ธ. And there's also a general hook you can use to implement other kinds of tracing or function-level instrumentation for debugging or program analysis ๐.
-p,-pgโ these generate extra code that writes profile information for the analysis programprof(with-p) orgprof(with-pg) ๐. You have to use this option when compiling the source files you want data about, and you have to use it when linking too, no skipping ๐ โโ๏ธ.
You can use the function attribute "no_instrument_function" to stop profiling of individual functions when you're compiling with these options ๐.
-fprofile-arcsโ this adds code so program flow arcs get instrumented ๐. While the program runs, it records how many times each branch and call is executed, and how many times each one is taken or returns ๐. On targets that support constructors with priority support, profiling handles constructors, destructors, and C++ constructors (and destructors) of classes used as the type of a global variable properly ๐.
When the compiled program exits, it saves this data to a file called auxname.gcda for each source file ๐พ. That data can be used for profile-directed optimizations (-fbranch-probabilities) or for test coverage analysis (-ftest-coverage) ๐. Each object file's auxname comes from the name of the output file if you explicitly specified one and it isn't the final executable; otherwise it's the basename of the source file ๐ง. Either way, any suffix gets removed. So foo.gcda is made for input file dir/foo.c, or dir/foo.gcda for an output file specified as -o dir/foo.o ๐ฆ.
Heads up bestie: if a command line directly links source files, the matching.gcdafiles get prefixed with the unsuffixed name of the output file ๐ซถ. For example,gcc a.c b.c -o binarywould generatebinary-a.gcdaandbinary-b.gcdafiles ๐.
-fcondition-coverageโ this adds code so program conditions get instrumented ๐. While the program runs, it records which terms in a conditional contribute to a decision ๐งฉ. That lets you check that all terms in a Boolean function are tested and have an independent effect on the outcome of a decision โ . You can read the result with"gcov --conditions"๐.-fpath-coverageโ this adds code so the paths taken get tracked ๐ค๏ธ. While the program runs, it records the prime paths taken ๐. The number of paths grows super fast with complexity, so to avoid exploding compile times, GCC gives up on instrumentation if the approximate number of paths goes over the limit set by-fpath-coverage-limit๐ญ. You can read the result with"gcov --prime-paths --prime-paths-lines --prime-paths-source",๐ .-fpath-coverage-limit=limitโ this is the threshold where-fpath-coveragethrows in the towel on instrumenting a function ๐ณ๏ธ. The limit is approximate and conservative, since GCC uses a pessimistic heuristic that slightly overcounts the running number of paths, and it gives up if the threshold is hit before all the paths are found ๐ค. This option is not for fine-grained control over which functions get instrumented; it's there to limit the effect of path explosion and keep compile times reasonable โฑ๏ธ. The default is250000๐.--coverageโ this is the one-stop shop for compiling and linking code instrumented for coverage analysis ๐. It's a synonym for-fprofile-arcs-ftest-coverage(when compiling) and-lgcov(when linking) โจ. Check the docs for those options if you want the deets ๐.
Here's the full routine, step by step:
- Compile the source files with
-fprofile-arcsplus your optimization and code generation options. For test coverage analysis, add the extra-ftest-coverageoption too. You don't need to profile every single source file in a program ๐. - Compile the source files additionally with
-fprofile-abs-pathso it creates absolute path names in the.gcnofiles. That letsgcovfind the correct sources in projects where compilations happen from 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 handled correctly without double counting ๐ด.
Also, an object file can be recompiled multiple times, and the corresponding .gcda file merges as long as the source file and the compiler options stay 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 info from the.gcnoand.gcdafiles ๐. Check the gcov documentation for more deets ๐.
With -fprofile-arcs, for each function of your program GCC creates a program flow graph and then finds a spanning tree for that graph ๐ณ. Only the arcs that are not on the spanning tree have to be instrumented: the compiler adds code to count how many times those arcs get executed ๐งฎ. When an arc is the only exit or the only entrance to a block, the instrumentation code can go into the block; otherwise, a new basic block has to 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 set by -fpath-coverage-limit ๐ค๏ธ. If the limit is exceeded, the function is not instrumented, just as if -fpath-coverage wasn't used ๐. A prime path is the longest sequence of unique blocks, except possibly the first and last, that is not a subpath of any other path ๐.
-ftest-coverageโ this produces a notes file that thegcovcode-coverage utility can use to show program coverage ๐. Each source file's note file is calledauxname.gcno๐๏ธ. Check the-fprofile-arcsdescription above for whatauxnamemeans and how to generate test coverage data ๐. Coverage data matches the source files more closely if you don't optimize ๐.-fprofile-abs-pathโ this automatically converts relative source file names to absolute path names in the.gcnofiles ๐บ๏ธ. That letsgcovfind the correct sources in projects where compilations happen from different working directories ๐ซถ.-fprofile-dir=pathโ okay so this one tells GCC where to hunt for profile data files ๐๏ธโจ It only affects profile data made by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and is used by-fprofile-use,-fbranch-probabilities, and their related options. Absolute and relative paths both work ๐
By default GCC uses the current directory as path, so the profile data file lands in the same directory as the object file. To stop file names from clashing, if the object file name isn't an absolute path, GCC mangles the absolute path of the sourcename.gcda file and uses that as the name of the .gcda file. Check -fprofile-arcs for the full details on file naming, and see the similar -fprofile-note option ๐ฆ
When your executable runs in a massive parallel environment, it's recommended to save profiles to different folders ๐ธ You can do that with variables inside path that get exported at run-time:
%pโ the process ID ๐%q{VAR}โ the value of the environment variableVAR๐-fprofile-generate,-fprofile-generate=pathโ this one turns on the stuff you usually need for instrumenting an app so it spits out a profile that's useful for recompiling later with profile feedback based optimization ๐ฅ You have to use-fprofile-generateboth when compiling AND when linking, no skipping either one ๐ซถ
Turning it on also enables -fprofile-arcs, -fprofile-values, -finline-functions, and -fipa-bit-cp โจ If you give it a path, GCC looks there for the profile feedback data files. See -fprofile-dir for that ๐ง
When you're ready to actually optimize using all that collected profile info, use -fprofile-use ๐
-fprofile-info-section,-fprofile-info-section=nameโ this registers the profile information in a specific section instead of using a constructor/destructor ๐ The section is callednameif you give one, otherwise it defaults to".gcov_info". A pointer to the profile information generated by-fprofile-arcsgets placed in that section for each translation unit. This option turns off the profile registration through a constructor AND turns off profile processing through a destructor ๐
Heads up: this is NOT meant for hosted environments like GNU/Linux ๐ It targets freestanding environments (think embedded systems) with limited resources that don't support constructors/destructors or C library file I/O.
The linker can collect the input sections into one continuous memory block and define start and end symbols. 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 = .);
}
Your program can then dump the profiling information registered in that linker set, for example 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;
}
The merge-stream subcommand of gcov-tool can deserialize the data stream generated by the "__gcov_filename_to_gcfn" and "__gcov_info_to_gcda" functions and merge that profile information into .gcda files on the host filesystem ๐ง ๐
-fprofile-note=pathโ if you give it apath, GCC saves the.gcnofile into that location ๐ Heads up: 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 all object files in the built project, which is NOT ideal if the directory you built the instrumented binary in differs from the one you used for the optimized build, because then the profile data won't be found ๐ฅฒ Setting-fprofile-prefix-path=pathwithpathpointing at the base build directory strips the irrelevant part of the path and keeps every file name relative to the main build directory ๐ซถ-fprofile-prefix-map=old=newโ when compiling files living in directoryold, GCC records profiling information (with--coverage) describing them as if they lived in directorynewinstead ๐บ๏ธ See also-ffile-prefix-mapand-fcanon-prefix-map๐-fprofile-update=methodโ this changes the update method for an app instrumented for profile feedback based optimization โก Themethodargument should be one ofsingle,atomic, orprefer-atomic. The first is great for single-threaded apps, while the second keeps your profile from getting corrupted by emitting thread-safe code ๐งต
Warning: if an application doesn't properly join all threads (or creates a detached thread), a profile file can still get corrupted. Yikes ๐
Using prefer-atomic becomes either atomic, when the target supports it, or single otherwise ๐คทโโ๏ธ The GCC driver automatically selects prefer-atomic when -pthread is on the command line; otherwise the default method is single โจ
If atomic is selected, the profile information gets updated using atomic operations on a best-effort basis ๐ Ideally those atomic operations happen in hardware. If the target platform doesn't support the required atomic operations in hardware, but libatomic is available, the profile information gets updated through calls to libatomic ๐ If the target platform supports neither the hardware atomics nor libatomic, the profile information is NOT atomically updated 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 for the profiling information and the target only supports 32-bit atomic operations in hardware, the performance-critical profiling updates are done using two 32-bit atomic operations for each counter update ๐๏ธ If a signal interrupts those two operations while updating a counter, the profiling information may end up in an inconsistent state ๐
-fprofile-filter-files=regexโ instruments only functions from files whose name matches any of the regular expressions (separated by semi-colons) ๐
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โ instruments only functions from files whose name does NOT match any of the regular expressions (separated by semi-colons) ๐ซ
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 the level of reproducibility of the profile gathered by"-fprofile-generate"๐ฏ It makes it possible to rebuild a program with the same outcome, which is super useful for things like distribution packages ๐ฆ
With -fprofile-reproducible=serial, the profile gathered by -fprofile-generate is reproducible, provided the trained program behaves the same at each invocation of the train run, it is not multi-threaded, and profile data streaming is always done in the same order ๐ซง Note that profile streaming happens at the end of the program run but also before the "fork" function is invoked ๐
It's pretty common for execution counts of some parts of programs to depend on things like the length of temporary file names or memory space randomization (which can affect hash-table collision rates) ๐ฅด That non-reproducible part of a program can be annotated with the "no_instrument_function" function attribute ๐ท๏ธ You can use gcov-dump with -l to dump the gathered data and verify that it really is reproducible ๐
With -fprofile-reproducible=parallel-runs, the collected profile stays reproducible regardless of the order in which data gets streamed into gcda files ๐ฏ This setting lets you run multiple instances of the instrumented program in parallel (such as with "make -j") โก The catch is that it reduces the quality of the gathered data, particularly for indirect call profiling ๐ญ
โจ OPTIONS โจ (continued) ๐
-fsanitize=addressโ okay bestie, this one is AddressSanitizer ๐, a super fast memory error detector ๐ . The compiler instruments memory access instructions so it can catch out-of-bounds and use-after-free bugs ๐ญ. This option also turns on-fsanitize-address-use-after-scope. More details live at<https://github.com/google/sanitizers/wiki/AddressSanitizer>๐ธ. You can tweak the run-time behavior with theASAN_OPTIONSenvironment variable ๐. If you sethelp=1in it, the instrumented program prints its available options when it starts up โจ. The full list of supported flags is at<https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags>๐ฆ. Heads up: this one cannot be combined with-fsanitize=threador-fsanitize=hwaddress๐ โโ๏ธ. Also,-fsanitize=hwaddressis currently only supported on x86-64 (only with-mlam=u48or-mlam=u57) and AArch64, and in both cases only in ABIs with 64-bit pointers ๐.
When you compile with -fsanitize=address, you should also throw in -g ๐ง so the output is way more meaningful. Want more accurate stack traces? Use -O0, -O1, or -Og ๐, which (for instance) stop most function inlining. You can also add -fno-optimize-sibling-calls ๐, which stops sibling and tail recursive calls from being optimized; this option is implicit for -O0, -O1, or -Og. Or try -fno-ipa-icf ๐
, which turns off Identical Code Folding for functions. -fno-omit-frame-pointer helps your stack traces look better too ๐ฅ. Since multiple runs can give backtraces with different addresses thanks to ASLR (Address Space Layout Randomization) ๐, you might want to turn ASLR off. On Linux, that's done with setarch uname -m -R ./prog ๐.
-fsanitize=kernel-addressโ Enable AddressSanitizer for the Linux kernel ๐งโจ. More details are at<https://github.com/google/kernel-sanitizers>๐ซถ.-fsanitize=hwaddressโ This is Hardware-assisted AddressSanitizer ๐ง , which uses a hardware trick where the top byte of a pointer gets ignored ๐ช. That lets it catch memory errors with very low memory overhead, which is so efficient ๐ญ. Memory access instructions are instrumented to detect out-of-bounds and use-after-free bugs ๐. It enables-fsanitize-address-use-after-scopetoo. Check<https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html>for more details ๐ธ. The run-time behavior is controlled by theHWASAN_OPTIONSenvironment variable, andhelp=1shows the available options at startup ๐. It can't be combined with-fsanitize=threador-fsanitize=address, and it's currently only available on AArch64 ๐ฆ.-fsanitize=kernel-hwaddressโ Enable Hardware-assisted AddressSanitizer for compiling the Linux kernel ๐. It's similar to-fsanitize=kernel-addressbut uses an alternate instrumentation method, and similar to-fsanitize=hwaddressbut with instrumentation differences needed for the kernel ๐ง. Those differences 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 and alloca calls is not on by default, but you can still turn it on with the command-line options--param hwasan-instrument-stack=1and--param hwasan-instrument-allocas=1respectively ๐ . Using a random frame tag is not implemented for kernel instrumentation ๐.
-fsanitize=pointer-compareโ Instruments comparison operations (<,<=,>,>=) with pointer operands ๐. This option must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it cannot be combined with-fsanitize=thread๐ โโ๏ธ. Note: by default this check is disabled at run time ๐. To turn it on, adddetect_invalid_pointer_pairs=2to theASAN_OPTIONSenvironment variable โจ. Usingdetect_invalid_pointer_pairs=1only detects invalid operations when both pointers are non-null ๐ธ.-fsanitize=pointer-subtractโ Instruments subtraction with pointer operands ๐ฆ. It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it cannot be combined with-fsanitize=thread๐. Same deal as above: the check is disabled at run time by default ๐ญ. Adddetect_invalid_pointer_pairs=2toASAN_OPTIONSto enable it ๐. Withdetect_invalid_pointer_pairs=1, invalid operations only get caught when both pointers are non-null ๐.-fsanitize=shadow-call-stackโ Enable ShadowCallStack ๐ก๏ธ, a security enhancement 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 this only supports the aarch64 platform ๐. It's specifically designed for Linux kernels that enable the CONFIG_SHADOW_CALL_STACK option ๐ง. For user space programs, runtime support isn't currently provided in libc and libgcc, so if you want this in user space you'll need to bring your own runtime support ๐ซ . It should be noted that this may cause the ABI rules to be broken โ ๏ธ.
On aarch64, the instrumentation uses the platform register x18 ๐. That generally means any code that might run on the same thread as code compiled with ShadowCallStack must be compiled with -ffixed-x18. Otherwise, functions compiled without -ffixed-x18 might clobber x18 and corrupt the shadow stack pointer ๐.
Also, because there's no userspace runtime support, code compiled with ShadowCallStack can't use exception handling ๐
โโ๏ธ. Use -fno-exceptions to turn exceptions off. More details at <https://clang.llvm.org/docs/ShadowCallStack.html> ๐ธ.
-fsanitize=threadโ Enable ThreadSanitizer, a fast data race detector ๐โโ๏ธ๐จ. Memory access instructions are instrumented to detect data race bugs ๐ฅ. See<https://github.com/google/sanitizers/wiki#threadsanitizer>for more details ๐ฆ. The run-time behavior can be influenced with theTSAN_OPTIONSenvironment variable, and you can find the list of supported options at<https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags>๐. This option cannot be combined with-fsanitize=addressor-fsanitize=leak๐ โโ๏ธ.
When you compile with -fsanitize=thread, you should also use -g for 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 when linking executables ๐. The executable gets linked against a library that overridesmallocand other allocator functions ๐ช. See<https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer>for more details ๐ธ. The run-time behavior can be influenced with theLSAN_OPTIONSenvironment variable ๐. This option cannot be combined with-fsanitize=thread๐ โโ๏ธ.-fsanitize=undefinedโ Enable UndefinedBehaviorSanitizer, a fast undefined behavior detector ๐ต๏ธโโ๏ธ. Various computations get instrumented to catch undefined behavior at runtime ๐ . See<https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html>for more details ๐ฆ. The run-time behavior can be influenced with theUBSAN_OPTIONSenvironment variable ๐. Here are the current suboptions ๐:-fsanitize=shiftโ Checks that the result of a shift operation isn't undefined ๐ซจ. What counts as undefined differs slightly between C and C++, and also 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 isn't 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, this checks that the result of the shift isn't undefined ๐ง. Again, what 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 the__builtin_unreachablecall is reached, the behavior is undefined ๐.-fsanitize=vla-boundโ Tells the compiler to check that the size of a variable length array is positive ๐.-fsanitize=nullโ Enables pointer checking ๐. Apps built with this on will throw an error message when they try to dereference a NULL pointer, when a reference (possibly an rvalue reference) gets 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 on will throw 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-doesn't overflow in signed arithmetic ๐งฎ. This also detectsINT_MIN / -1signed division ๐ฅ. Heads up: integer promotion rules must be taken into account ๐ง . For example, the following is not an overflow ๐:
signed char a = SCHAR_MAX;
a++;
Okay so the sanitizer options are where things get spicy ๐ถ๏ธ bestie, pay attention ๐
-fsanitize=boundsโ ๐ Turns on array bounds instrumentation so a bunch of sneaky out-of-bounds accesses get caught. 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, if-fstrict-flex-arraysor-fstrict-flex-arrays=or thestrict_flex_arrayattribute says they shouldn't be treated that way. ๐-fsanitize=bounds-strictโ ๐ The strict version. Most out-of-bounds accesses get detected, including flexible-array-member-like arrays. Initializers of variables with static storage still aren't instrumented, so don't come for them ๐ญ-fsanitize=alignmentโ ๐งญ Checks that pointers are aligned when they get dereferenced, when a reference gets bound to an insufficiently aligned target, or when a method or constructor gets invoked on an insufficiently aligned object. Misaligned vibes get flagged โจ-fsanitize=object-sizeโ ๐ฏ Instruments memory references using the__builtin_dynamic_object_sizefunction. Various out-of-bounds pointer accesses get detected, iconic behavior ๐-fsanitize=float-divide-by-zeroโ โ Detects floating-point division by zero. Unlike other similar options, this one is not enabled by-fsanitize=undefined, because dividing floats by zero can be a totally legit way to get infinities and NaNs. Not everything is a bug, babe ๐ฆ-fsanitize=float-cast-overflowโ ๐ Enables checking of floating-point to integer conversions. It checks that the result of the conversion doesn't overflow. Also unlike other similar options, this one is not enabled by-fsanitize=undefined. Heads up: it doesn't play nicely withFE_INVALIDexceptions enabled ๐-fsanitize=nonnull-attributeโ ๐ซ Instruments calls to check that null values aren't passed to arguments marked as requiring a non-null value by thenonnullfunction attribute. No nulls at the party ๐-fsanitize=returns-nonnull-attributeโ ๐ Instruments return statements in functions marked with thereturns_nonnullfunction attribute, so returning a null value from one of those functions gets detected ๐ธ-fsanitize=boolโ ๐ Instruments loads frombool. If a value other than 0/1 gets loaded, a run-time error is issued. Bools are supposed to be 0 or 1, not vibes ๐-fsanitize=enumโ ๐ข Instruments loads from an enum type. If a value outside the range of values for that enum type gets loaded, a run-time error is issued ๐ง-fsanitize=vptrโ ๐งฌ Instruments C++ member function calls, member accesses, and some conversions between pointers to base and derived classes. It verifies that the referenced object has the correct dynamic type, so nobody's lying about their identity ๐-fsanitize=pointer-overflowโ โ Instruments pointer arithmetic. If the pointer arithmetic overflows, a run-time error is issued ๐-fsanitize=builtinโ ๐ ๏ธ Instruments arguments to selected builtin functions. If an invalid value gets passed to one of those arguments, a run-time error is issued. For example, passing 0 as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior, and this option diagnoses it ๐ฅ
Note that sanitizers tend to bump up the rate of false positive warnings, most notably the ones around -Wmaybe-uninitialized. We recommend against combining -Werror and [the use of] sanitizers. Not the move ๐ญ
While -ftrapv causes traps for signed overflows to be emitted, -fsanitize=undefined gives a diagnostic message instead. This currently works only for the C family of languages ๐
-fno-sanitize=allโ ๐งน Disables all previously enabled sanitizers.-fsanitize=allis not allowed, though, because some sanitizers can't be used together, so don't even try it ๐ โโ๏ธ-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, very mad scientist of you ๐งโ๐ฌ-fsanitize-sections=s1,s2,...โ ๐๏ธ Sanitizes global variables in selected user-defined sections. Thesipart may contain wildcards ๐ฆ-fsanitize-recover[=opts]โ ๐-fsanitize-recover=controls the error recovery mode for the sanitizers listed in the comma-separated list ofopts. When it's enabled for a sanitizer, that sanitizer tries to keep running the program as if no error happened. So multiple runtime errors can get reported in one run, and the exit code might say success even after errors were reported ๐ณ The-fno-sanitize-recover=option changes this: only the first detected error gets reported, and then the program exits with a non-zero exit code ๐
Right now this 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 it's still experimental ๐งช -fsanitize-recover=all and -fno-sanitize-recover=all are also accepted. The former enables recovery for every sanitizer that supports it, and the latter disables recovery for every sanitizer that supports it ๐
Even if recovery mode is turned on 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 to catch use-after-scope bugs. This option sets-fstack-reusetononeโจ-fsanitize-trap[=opts]โ ๐ชค Tells the compiler to report undefined behavior for the sanitizers in the comma-separated list ofoptsusing__builtin_trapinstead of alibubsanlibrary routine. If this is enabled for a certain sanitizer, it takes precedence over the-fsanitizer-recover=for that sanitizer.__builtin_trapgets emitted and is fatal regardless of whether recovery is enabled or disabled through-fsanitize-recover=๐ฅ
The advantage? The libubsan library isn't needed and doesn't get linked in, so this works even in freestanding environments ๐ง
Right now this 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 and is an equivalent of-fsanitize-trap=all. Retire it, bestie ๐-fsanitize-coverage=trace-pcโ ๐ต๏ธ Enables coverage-guided fuzzing code instrumentation. Inserts a call to__sanitizer_cov_trace_pcinto every basic block ๐-fsanitize-coverage=trace-cmpโ ๐งฒ Enables dataflow-guided fuzzing code instrumentation. Inserts a call to__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4, or__sanitizer_cov_trace_cmp8for integral comparisons where both operands are variables. For integral comparisons with one constant operand, it uses__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4, or__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โ ๐ก๏ธ Enables code instrumentation to boost program security by checking that the 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 similar call/jmp-oriented programming (COP/JOP) ๐
The -fcf-protection= keywords work like this:
- The value
branchtells the compiler to check validity of control-flow transfers at indirect branch instructions, i.e.call/jmpinstructions ๐ - The value
returnchecks validity at the point of returning from a function ๐ - The value
fullis an alias for specifying bothbranchandreturn๐ - The value
checkis used for the final link with link-time optimization (LTO). An error is issued if LTO object files were compiled with different-fcf-protectionvalues. Thecheckvalue is ignored at compile time ๐ง - The value
noneturns instrumentation off ๐ โโ๏ธ
-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 value branch, 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 ๐ซถ
Okay so picking up right where we left off, bestie ๐ โจ The x86 GNU/Linux target has a CET (Intel Control-flow Enforcement Technology) setup that works on i686 processors and newer ๐ฆ
๐ NOTE: In Ubuntu 19.10 and later,-fcf-protectionis turned on by default for C, C++, ObjC, and ObjC++, as long as you haven't used-fno-cf-protectionor any-fcf-protection=*flag. Ubuntu is being very protective of us ๐ซถ
-fharden-comparesโ okay this one is lowkey sneaky ๐ For every logical test that survives gimple optimizations and isn't the condition in a conditional branch (think conditions for conditional moves, or ones stored in boolean variables), GCC emits extra code that computes and checks the reversed condition. If the two results don't match, it calls__builtin_trap. Pair it with-fharden-conditional-branchesto cover every conditional โจ-fharden-conditional-branchesโ for every non-vectorized conditional branch that survives gimple optimizations, GCC adds extra code that computes and verifies the reversed condition, and calls__builtin_trapif the result is unexpected. Use it with-fharden-comparesto cover all conditionals ๐-fharden-control-flow-redundancyโ this one is giving bodyguard energy ๐ก๏ธ GCC emits extra code that sets booleans when entering basic blocks, then at function exits it verifies them and traps if the booleans don't form an execution path that matches the control flow graph ๐ฅ
Verification happens before returns, before mandatory tail calls (more on those 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. There are also tuning options, --param hardcfr-max-blocks and --param hardcfr-max-inline-blocks, if you want to fine-tune things ๐
Tail call optimization happens too late to affect control flow redundancy. Calls that language front-ends mark as mandatory tail calls, and any calls marked early enough as potential tail calls, would also get verification before the call. Honestly though, these cases are merely theoretical, because the conditions can only be met when you use custom compiler plugins ๐
-fhardcfr-skip-leafโ disables-fharden-control-flow-redundancyin leaf functions ๐-fhardcfr-check-exceptionsโ when-fharden-control-flow-redundancyis active, the recorded execution path gets checked against the control flow graph at exception escape points. It's like wrapping the function body in a cleanup handler that does the check and then reraises ๐ง This option is enabled by default. If you want it gone, use-fno-hardcfr-check-exceptions๐-fhardcfr-check-returning-callsโ when-fharden-control-flow-redundancyis active, the recorded path is checked before any function call that's immediately followed by a return of its result (if there is one). This way it doesn't block tail-call optimization, whether or not the call actually ends up becoming a tail call ๐ฆ
This option is enabled by default whenever sibling call optimizations are on (see -foptimize-sibling-calls). But you can turn it on or off explicitly, using its negated form, no matter what the optimizations are doing ๐ธ
-fhardcfr-check-noreturn-calls=[always|no-xthrow|nothrow|never]โ when-fharden-control-flow-redundancyis active, the recorded path gets checked against the control flow graph before "noreturn" calls. You pick which ones:alwayschecks before all of themno-xthrowchecks before those not expected to return control to the caller through an exception. This is the default ๐nothrowchecks before those that may not return control to the caller through an exception eitherneverchecks before none of them
Heads up ๐ checking before a "noreturn" function that may return control through an exception can happen more than once, if the caller catches the exception (with a handler or a cleanup). If -fhardcfr-check-exceptions is also on, the compiler skips associating a "noreturn" call with the implicit cleanup handler, since that would be redundant with the check already done before the call. Other handlers or cleanups in the function will still modify the recorded path and check it again when another checkpoint gets hit. That checkpoint could even be another "noreturn" call, so checking might end up running multiple times ๐ญ
Various optimizers can mark calls as "noreturn" and/or "nothrow" even without the matching attributes. That can change where checks go and which implicit cleanup handlers get added. Because of this unpredictability, and because raising and reraising exceptions often amounts to implicitly calling "noreturn" functions, no-xthrow is the default. It only excludes internal functions used to (re)raise exceptions from the "noreturn" treatment, and those aren't affected by these optimizations โจ
-fhardenedโ the big hardening bundle ๐ฅ It enables a set of flags for C and C++ that make the generated code more secure without changing its ABI. The exact flags 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 whole list with --help=hardened ๐
When 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 shipping it ๐
โ ๏ธ Right now -fhardened is only supported on GNU/Linux targets.
Also, -fhardened only turns on a particular option if it wasn't already specified anywhere on the command line. For example, -fhardened -fstack-protector will only enable -fstack-protector, and not -fstack-protector-strong ๐
-fstack-protectorโ emits extra code to check for buffer overflows, like stack smashing attacks ๐ก๏ธ It works by adding a guard variable to functions with vulnerable objects. That includes functions that callalloca, and functions with buffers larger than or equal to 8 bytes. The guards get initialized when the function is entered and checked when it exits. If a guard check fails, an error message gets printed and the program exits. Only variables that are actually allocated on the stack count, so optimized-away variables or ones living in registers don't matter ๐ง-fstack-protector-allโ like-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. Same deal as before, only variables actually allocated on the stack are considered ๐
๐ 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-ffreestandingshow up.
-fstack-protector-explicitโ like-fstack-protector, but only protects the functions that have thestack_protectattribute ๐-fstack-checkโ generates code to verify you don't go beyond the boundary of the stack ๐ฅน You should specify this if you're running in an environment with multiple threads. In a single-threaded environment you rarely need it, since stack overflow is automatically detected on nearly all systems when there's only one stack.
Heads up though: this switch doesn't actually do the checking. The operating system or the language runtime has to do that. The switch just generates code that makes sure they see the stack being extended ๐ซถ
You can also give it a string parameter:
nomeans no checkinggenericforces the use of old-style checkingspecificuses the best checking method, and is equivalent to bare-fstack-check
Old-style checking is a generic mechanism. It doesn't need any specific target support in the compiler, but it comes with these drawbacks ๐ญ
- Modified allocation strategy for large objects: they're always allocated dynamically if their size goes over a fixed threshold. This may change the semantics of some code.
- Fixed limit on the size of the static frame of functions: when it's topped by a particular function, stack checking isn't reliable and the compiler issues a warning.
- Inefficiency: because of both the modified allocation strategy and the generic implementation, code performance takes a hit.
Old-style stack checking is also the fallback for specific if the compiler has no target support added for it.
-fstack-check= is designed for Ada's needs, to detect infinite recursion and stack overflows. specific is an excellent choice when compiling Ada code. It's not generally enough to protect against stack-clash attacks, though. To protect against those, you want -fstack-clash-protection ๐
-fstack-clash-protectionโ generates code to prevent stack clash style attacks ๐ฅ When this is on, the compiler only allocates one page of stack space at a time, and each page gets accessed right after it's allocated. That way allocations can't jump over any stack guard page the operating system provides ๐ฆ
Most targets don't fully support stack clash protection. On those that do, -fstack-clash-protection 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-protectionis enabled by default for C, C++, ObjC, and ObjC++, unless-fno-stack-clash-protectionis found.
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ generates code to make sure the stack doesn't grow beyond a certain value. That value is either the value of a register (reg) or the address of a symbol (sym) ๐ธ If a larger stack is required, a signal gets raised at run time. On most targets the signal is raised before the stack overruns the boundary, so you can catch it without taking any special precautions ๐ง
okay so picture this ๐ง if the stack starts at absolute address 0x80000000 and grows downwards, you can use the flags -fstack-limit-symbol=__stack_limit and -Wl,--defsym,__stack_limit=0x7ffe0000 to enforce a stack limit of 128KB ๐
ngl this may only work with the GNU linker, so keep that in mind ๐
you can also locally override stack limit checking with the "no_stack_limit" function attribute โจ
-fsplit-stackโ okay this one is so iconic ๐ญ it generates code that automatically splits the stack before it overflows. the resulting program has a discontiguous stack, which can only overflow if the program can't allocate any more memory. it's most useful for threaded programs, because you no longer have to figure out a good stack size for every single thread ๐งต this is currently only implemented for x86 targets running GNU/Linux ๐ง
When code compiled with -fsplit-stack calls code compiled without it, there might not be much stack space left for that latter code to run in ๐ฅบ 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 it always gets a large stack ๐ซถ support for this is in the gold linker in GNU binutils release 2.21 and later ๐
-fstrub=disableโ disable stack scrubbing entirely, ignoring any "strub" attributes ๐ โโ๏ธ See-fstrub=strictโ functions default to "strub" mode "disabled" and the rules are strict ๐ only functions tied to "strub"-"callable" modes ("at-calls", "callable" and "always_inline" "internal") are allowed to be "callable" by functions with "strub"-enabled modes ("at-calls" and "internal") ๐-fstrub=relaxedโ bring back the default stack scrub ("strub") setting ๐ธ which means "strub" only turns on when it's required by "strub" attributes on functions and data types. "Relaxed" just means strub contexts can't call functions explicitly tied to "strub" mode "disabled" ๐ฆ this option is only useful for overriding other-fstrub=*options that come before it on the command line ๐-fstrub=at-callsโ enable "at-calls" "strub" mode wherever it's viable โจ the main use is testing, since it exercises the "strub" machinery in scenarios that stay strictly local to a translation unit. this mode changes function interfaces, so any function visible to other translation units, or any function whose address is taken, won't be affected by this option ๐ โโ๏ธ optimization options can also affect viability. check the "strub" attribute documentation for the details on viability and eligibility requirements ๐-fstrub=internalโ enable "internal" "strub" mode wherever it's viable ๐งช mainly for testing, to thoroughly exercise the parts of the "strub" machinery that implement the less efficient but interface-preserving "strub" mode ๐ functions that wouldn't be affected by this option are pretty uncommon ๐-fstrub=allโ enable some "strub" mode wherever it's viable ๐ฅ when both strub modes are viable, "at-calls" wins ๐-fdump-ipa-strubmadds function attributes that tell you which mode was picked for each function ๐ต๏ธโโ๏ธ the main use is testing, to thoroughly exercise the "strub" machinery ๐ง-fvtable-verify=[std|preinit|none]โ okay this is C++ only ๐ it turns on (or off, if you use-fvtable-verify=none) the security feature that checks at run time, for every virtual call, that the vtable pointer the call goes through is valid for the type of the object and hasn't been corrupted or overwritten ๐ if an invalid vtable pointer shows up at run time, an error gets reported and the program halts immediately ๐
This option builds run-time data structures at program startup, and those are what get used to verify the vtable pointers ๐ซง the std and preinit values control when those data structures get built. in both cases 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 shared libraries have been loaded and initialized โฐ
if this option shows up multiple times on the command line with different values, none takes the highest priority over both std and preinit, and preinit takes priority over std ๐
-fvtv-debugโ used together with-fvtable-verify=stdor-fvtable-verify=preinit, this makes the compiler call debug versions of the runtime functions for the vtable verification feature ๐ it also logs info about which vtable pointers it finds for each class ๐ that info gets written to a file namedvtv_set_ptr_data.login the directory named by the environment variableVTV_LOGS_DIRif that's defined, or the current working directory otherwise ๐
Note: this feature appends data to the log file. if you want a fresh log file, be sure to delete any existing one ๐
-fvtv-countsโ this is a debugging flag ๐ used together with-fvtable-verify=stdor-fvtable-verify=preinit, it makes the compiler keep track of the total number of virtual calls it runs into and the number of verifications it inserts ๐ it also counts how many calls it inserts to certain run-time library functions and logs that info for each compilation unit ๐งพ the compiler writes all of this to a file namedvtv_count_data.login the directory named byVTV_LOGS_DIRif that's defined, or the current working directory otherwise ๐ it also counts the size of the vtable pointer sets for each class and writes that tovtv_class_set_sizes.login the same directory ๐ธ
Note: this feature appends data to the log files. to get fresh log files, be sure to delete any existing ones ๐
-finstrument-functionsโ generates instrumentation calls for function entry and exit ๐ฆ just after a function is entered and just before it exits, the following profiling functions get called with the address of the current function and its call site ๐ (on some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site info might not be available to the profiling functions otherwise ๐ฅฒ)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
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 inside other functions ๐งฉ the profiling calls show where, conceptually, the inline function is entered and exited. that means addressable versions of those functions must be available ๐ซถ if all your uses of a function get expanded inline, this might mean extra code size ๐ if you use extern inline in your C code, an addressable version of those functions must be provided too (this is normally the case anyway, but if you get lucky and the optimizer always expands them inline, you might have gotten away without static copies ๐)
a function can be given the attribute no_instrument_function, and then this instrumentation isn't done for it ๐
โโ๏ธ that's useful for things like the profiling functions above, high-priority interrupt routines, and any functions the profiling functions can't safely be called from (maybe signal handlers, if the profiling routines generate output or allocate memory ๐ฅ)
-finstrument-functions-onceโ this is similar to-finstrument-functions, except the profiling functions only get called once per instrumented function ๐ฏ the first profiling function is called after the first entry into the instrumented function, and the second one is 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 the implementation 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, meaning 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 the description of-finstrument-functions) ๐ซ if the file that contains a function definition matches one of thefileentries, then that function doesn't get instrumented ๐ the match is done on substrings, so if thefileparameter 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 the sym entries, write ,, instead ๐ง for example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quotes surrounding the option) ๐
-finstrument-functions-exclude-function-list=sym,sym,...โ this is similar to-finstrument-functions-exclude-file-list, but this one sets the list of function names to exclude from instrumentation ๐ the name that gets matched is the user-visible name, like "vector<int> blah(const vector<int> &)", not the internal mangled name (like_Z4blahRSt6vectorIiSaIiEE) ๐ง the match is done on substrings too: if thesymparameter is a substring of the function name, it counts as a match ๐ for C99 and C++ extended identifiers, the function name must be given in UTF-8, not using universal character names ๐
๐ OPTIONS (continued) ๐
-fpatchable-function-entry=N[,M]โ okay bestie, this one is so cute ๐ฆ It makes GCC dropNNOPs right at the start of every function, and the function's entry point sits just before theMth NOP. If you leaveMout, it defaults to0, so the entry point lands right on the first NOP. Those NOPs are basically reserved extra space you can patch with whatever instrumentation you want at run time, but only if the code segment is writable ๐ You control how much space you get by changing the number of NOPs. The NOP used is whatever the internal GCC back-end hookgen_nopemits. This is target-specific and might also depend on the architecture variant and/or other compilation options, so it's not the same everywhere โจ
For run-time identification, the starting addresses of these areas (their function entries minus M) also get collected into the "__patchable_function_entries" section of the final binary ๐ง
Also, __attribute__ ((patchable_function_entry (N,M))) beats -fpatchable-function-entry=N,M on the command line ๐ so you can make a single function's area bigger or remove it entirely. If N=0, no pad location gets recorded ๐
The NOPs go in 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 that same function entry address by default. Check out -msplit-patch-nops if you want to change that ๐ธ
Heads up: the maximum value of N and M is 65535. On PowerPC with the ELFv2 ABI, for dual-entry-point functions, the supported values for M are 0, 2, 6 and 14 when you are not using -msplit-patch-nops ๐ซถ
๐ธ Options Controlling the Preprocessor ๐ธ
These options control the C preprocessor, which runs on every C source file before the actual compilation happens. It's giving prep work ๐
If you use -E, nothing happens except preprocessing. A few of these options only make sense alongside -E, because they make the preprocessor output unsuitable for actual compilation ๐
Besides the options listed here, there are a bunch more for controlling include-file search paths, documented in Directory Options. And diagnostics options for the preprocessor are listed in Warning Options ๐ฆ
-D nameโ predefinenameas a macro, with the definition1โจ-D name=definitionโ the contents ofdefinitionget tokenized and processed as if they showed up during translation phase three in a#definedirective. Quick note: the definition gets chopped off at any embedded newline characters ๐
If you're calling the preprocessor from a shell (or something shell-like), you might need the shell's quoting syntax to protect characters like spaces that mean something in shell syntax ๐ซถ
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 quote the whole option. With sh and csh, -D'name(args...)=definition' works ๐ฅ
-D and -U options are processed in the order you typed them on the command line. All -imacros file and -include file options get processed after all the -D and -U ones ๐
-U nameโ cancels any previous definition ofname, whether it was built in or came from a-Doption ๐ญ-include fileโ processesfileas if#include "file"showed up as the very first line of the primary source file. The big difference is that the first directory searched forfileis the preprocessor's working directory, not the directory with the main source file. If it's not found there, the search continues through the rest of the#include "..."search chain as normal ๐ง
If you give multiple -include options, the files get included in the order they appear on the command line ๐
-imacros fileโ exactly like-include, except any output made by scanningfilegets thrown away. The macros it defines stay defined though. This is the move if you want all the macros from a header without also processing its declarations ๐
Every file given with -imacros gets processed before every file given with -include ๐
-undefโ doesn't predefine any system-specific or GCC-specific macros. The standard predefined macros still stay defined ๐-pthreadโ defines the extra macros you need to use the POSIX threads library. 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โ instead of outputting the preprocessed result, this spits out a rule suitable formakethat describes the dependencies of the main source file โจ The preprocessor writes one make rule with the object file name for that source file, a colon, and the names of all the included files, including the ones coming from-includeor-imacroscommand-line options ๐ฆ
Unless you set it explicitly (with -MT or -MQ), the object file name is the source file name with its suffix swapped for the object file suffix, and with any leading directory parts removed. If there are lots of included files, the rule gets split across several lines using \-newline. The rule has no commands ๐
This option does not suppress the preprocessor's debug output, like -dM. To keep that debug output from mixing with your dependency rules, explicitly specify the dependency output file with -MF, or use an environment variable like DEPENDENCIES_OUTPUT. Debug output still goes to the regular output stream as normal ๐
Passing -M to the driver implies -E, and suppresses warnings with an implicit -w ๐ซถ
-MMโ like-M, but it doesn't mention header files found in system header directories, or header files that are included (directly or indirectly) from such a header ๐ธ
This means the choice of angle brackets or double quotes in an #include directive doesn't, on its own, decide whether that header shows up in -MM dependency output ๐
-MF fileโ when used with-Mor-MM, this picks a file to write the dependencies to. If you don't give-MF, the preprocessor sends the rules to the same place it would send preprocessed output โจ
When used with the driver options -MD or -MMD, -MF overrides the default dependency output file ๐ง
If file is -, the dependencies get written to stdout ๐ฆ
-MGโ used alongside something like-Mthat asks for dependency generation,-MGassumes missing header files are generated files and adds them to the dependency list without raising an error ๐ญ The dependency filename is taken straight from the#includedirective, with no path prepended.-MGalso suppresses preprocessed output, since a missing header makes that useless ๐
This feature is used for automatically updating makefiles ๐
-Mno-modulesโ disables dependency generation for compiled module interfaces ๐-MPโ tells CPP to add a phony target for each dependency other than the main file, so that each one depends on nothing. These dummy rules work around errorsmakegives when 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 made by dependency generation. By default, CPP takes the name of the main input file, deletes any directory components and file suffix (like.c), and appends the platform's usual object suffix. That result is the target ๐
An -MT option sets the target to be exactly the string you give it ๐
If you want multiple targets, you can put them in a single argument to -MT, or use multiple -MT options ๐ธ
For example, -MT '$(objpfx)foo.o' might give:
$(objpfx)foo.o: foo.c
-MQ targetโ same as-MT, but it quotes any characters that are special to Make ๐ฅ-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
The default target is automatically quoted, as if it had been given with -MQ ๐
-MDโ-MDis equivalent to-M -MF file, except that-Eis not implied ๐ง The driver figures outfilebased on whether an-ooption is given. If it is, the driver uses that argument with a suffix of.d. Otherwise, it takes the name of the input file, removes any directory components and suffix, and slaps on a.dsuffix ๐ฆ
If -MD is used together with -E, any -o switch is understood to name the dependency output file. But if -MD is used without -E, each -o is understood to name a target object file ๐
Since -E isn't implied, -MD can generate a dependency output file as a side effect of the compilation process ๐
-MMDโ like-MD, but only mentions user header files, not system header files โจ-fpreprocessedโ tells the preprocessor the input file has already been preprocessed ๐ This suppresses stuff 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 any problems ๐ซถ In this mode, the integrated preprocessor is basically just a tokenizer for the front ends ๐ธ
-fpreprocessed is implicit if the input file has one of the extensions .i, .ii or .mi. Those are the extensions GCC uses for preprocessed files made by -save-temps ๐
-fdirectives-onlyโ when preprocessing, handles directives but does not expand macros ๐ How it behaves depends on-Eand-fpreprocessed:
With -E, preprocessing is limited to handling directives like "#define", "#ifdef", and "#error". Other preprocessor operations, like macro expansion and trigraph conversion, aren't performed. The -dD option is also implicitly enabled ๐
With -fpreprocessed, predefinition of command-line macros and most builtin macros is disabled. Macros like "__LINE__", which depend on context, are still handled normally. This lets you compile files that were previously preprocessed with "-E -fdirectives-only" โจ
With both -E and -fpreprocessed, the rules for -fpreprocessed take precedence. This enables full preprocessing of files that were previously preprocessed with "-E -fdirectives-only" ๐
-fdollars-in-identifiers๐ฒ โ okay so this one lets$sneak into your identifier names. Accepted, no drama.-fextended-identifiers๐ โ accepts universal character names and extended characters in identifiers. It's already on by default for C99 (and later C standards) and C++, so you're probably already vibing with it. ๐-fno-canonical-system-headers๐ โโ๏ธ โ when preprocessing, this stops GCC from shortening system header paths with canonicalization. No shortcuts, bestie.-fmax-include-depth=depth๐ช โ sets the max depth of nested#includes. The default is200, which is plenty, honestly.-fsearch-include-path[=kind]๐ โ tells GCC to look for input files on the#includepath, not just in the current directory. This is especially clutch with C++20 modules, where 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 searches the #include "..." path. You can also explicitly ask for system to search the #include <...> path. โจ
-ftabstop=width๐ โ sets the distance between tab stops. This helps the preprocessor report correct column numbers in warnings or errors, even when tabs show up on the line. If the value is less than1or greater than100, the option gets ignored. The default is8.-ftrack-macro-expansion[=level]๐ โ tracks token locations across macro expansions, so the compiler can show you the current macro expansion stack when an error pops up inside a macro. The catch? The preprocessor and compiler eat more memory with this on. ๐ฝ๏ธ Thelevelparameter lets you pick how precisely tokens get tracked, so you can save memory if you need to:- Level
0turns this option off. - Level
1tracks tokens in a degraded mode for minimal memory overhead. In this mode, every token from expanding a function-like macro's argument shares the same location. - Level
2tracks token locations completely. This is the most memory-hungry option, so it's the main character of the RAM budget. ๐
- Level
If you give the option with no argument, the default parameter value is 2.
Note that -ftrack-macro-expansion=2 is activated by default. ๐
-fmacro-prefix-map=old=new๐บ๏ธ โ when preprocessing files living in directoryold, this expands the__FILE__and__BASE_FILE__macros as if the files lived in directorynewinstead. Using.fornewcan turn an absolute path into a relative one, which can lead to more reproducible, location-independent builds. This option 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 supported by the system'siconvlibrary routine.-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 used for code generation. Just like-fexec-charset,charsetcan be any encoding supported by the system'siconvlibrary routine. Heads up though: you'll run into problems with encodings that don't fit exactly inwchar_t. ๐ฅฒ-finput-charset=charset๐ฅ โ sets the input character set, which is used to translate from the input file's character set into the source character set GCC uses. If the locale doesn't specify one, or GCC can't get that info from the locale, the default isUTF-8. The locale or this command-line option can override that, but if they conflict, the command-line option wins.charsetcan be any encoding supported by the system'siconvlibrary routine.-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, since those aren't consulted when a precompiled header is in use.-fpch-preprocess๐งฉ โ this lets you use a precompiled header together with-E. It drops a special#pragmainto the output,#pragma GCC pch_preprocess "filename", to mark where the precompiled header was found and what its filename is. When-fpreprocessedis in use, GCC recognizes this#pragmaand loads the PCH.
This option is off by default, because the preprocessed output is only really suitable as input to GCC. It gets switched on by -save-temps. ๐ซถ
You should never write this #pragma in your own code. It's safe to edit the filename, though, if the PCH file lives in a different location. The filename can be absolute or relative to GCC's current directory.
-fworking-directory๐ โ enables generating linemarkers in the preprocessor output that let the compiler know the working directory at the time of preprocessing. With this on, after the initial linemarker, the preprocessor emits a second linemarker with the current working directory followed by two slashes. GCC uses that directory, when it's in the preprocessed input, as the current working directory in some debugging information formats. This option is implicitly enabled when debugging info 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. ๐-A predicate=answer๐ โ makes an assertion with the predicatepredicateand the answeranswer. This form is preferred over the older-A predicate(answer)form, which is still supported, because it doesn't use shell special characters.-A -predicate=answer๐ซ โ cancels an assertion with the predicatepredicateand the answeranswer.-C๐ฌ โ do not discard comments. All comments get passed through to the output file, except for comments in processed directives, which are deleted along with the directive.
โ ๏ธ Be prepared for side effects when using-C. It makes the preprocessor treat comments as tokens in their own right. For example, a comment at the start of what would be a directive line turns that line into an ordinary source line, since the first token on the line is no longer a#.
-CC๐ฌโจ โ do not discard comments, including during macro expansion. This is like-C, except comments inside macros also get passed through to the output file wherever the macro is expanded.
On top of the side effects of -C, -CC converts all C++-style comments inside a macro into C-style comments. That way, later use of the macro can't accidentally comment out the rest of the source line. ๐ก๏ธ
The -CC option is generally used to support lint comments.
-P๐ซ๐ โ inhibits generating linemarkers in the preprocessor output. This might be handy when you're running the preprocessor on something that isn't C code and will be sent to a program that could get confused by the linemarkers.-traditional,-traditional-cpp๐ฐ๏ธ โ tries to imitate pre-standard C preprocessors, instead of ISO C preprocessors. See the GNU CPP manual for details.
Note that GCC doesn't otherwise try to emulate a pre-standard C compiler, and these options only work with the -E switch, or when you invoke CPP explicitly.
-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 allow really short file names, such as MS-DOS.-H๐ณ โ prints the name of each header file used, along with the other normal activities. Each name is indented to show how deep it sits in the#includestack. Precompiled header files get printed too, even when they turn out to be invalid. An invalid precompiled header gets printed with...x, and a valid one with...!.-dletters๐งช โ makes debugging dumps during compilation, as specified byletters. 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 get silently ignored. If you specify letters whose behaviors conflict, the result is undefined. ๐-dM๐ โ instead of the normal output, generates a list of#definedirectives for all the macros defined during preprocessing, including predefined macros. This is a great way to find out what's predefined in your version of the preprocessor. Assuming you have no filefoo.h, this command:
touch foo.h; cpp -dM foo.h
shows all the predefined macros.
If you use -dM without the -E option, -dM is interpreted as a synonym for -fdump-rtl-mach. ๐ค
-dD๐ โ like-dM, except it outputs both the#definedirectives and the result of preprocessing. Both kinds of output go to the standard output file.-dNโ๏ธ โ like-dD, but only emits the macro names, not their expansions.-dI๐ โ outputs#includedirectives in addition to the result of preprocessing.-dUโณ โ like-dD, except only macros that get expanded, or whose definedness is tested in preprocessor directives, are output. The output is delayed until the macro is used or tested.#undefdirectives are also output for macros that get tested but are undefined at that time. ๐ฆ
๐ Preprocessor and Assembler Passthrough ๐
-fdebug-cpp๐ โ This one is only useful if you're debugging GCC itself. When it's used from CPP or alongside-E, it dumps debugging info about location maps, and every token in the output gets the dump of whichever map its location belongs to. ๐
When you use it from GCC without -E, it does absolutely nothing. ๐
-Wp,option๐ง โ This lets you skip the compiler driver and sendoptionstraight to the preprocessor. Ifoptionhas commas in it, it gets split into multiple options at each comma. ๐ช
Heads up, though: a lot of options get modified, translated, or interpreted by the driver before they reach the preprocessor, and -Wp forcibly skips that step. The preprocessor's direct interface is undocumented and can change at any time, so whenever you can, let the driver handle your options and avoid -Wp. ๐
โโ๏ธ
-Xpreprocessor option๐ธ โ Passesoptionalong to the preprocessor. This is your go-to for system-specific preprocessor options that GCC doesn't recognize. โจ
If the option you want takes an argument, you need to use -Xpreprocessor twice: once for the option itself and once for the argument. ๐
-no-integrated-cpp๐ฆ โ Runs preprocessing as its own separate pass before compilation. By default, GCC does preprocessing as part of input tokenization and parsing, all integrated and cute. ๐ซถ
With this option, the right language front end (cc1 for C, cc1plus for C++, or cc1obj for Objective-C) gets invoked twice instead: once for preprocessing only, and once for actually compiling the preprocessed input. ๐ This can be super handy alongside -B or -wrapper if you want an alternate preprocessor or extra processing of your source between the normal preprocessing and compilation. ๐ฅ
๐ Passing Options to the Assembler ๐
Okay so you can pass options to the assembler too. ๐ง
-Wa,option๐ โ Passesoptionalong as an option to the assembler. Ifoptionhas commas, it gets split into multiple options at those commas. ๐ช-Xassembler optionโจ โ Also passesoptionto the assembler. Use this for system-specific assembler options that GCC doesn't recognize. ๐ฆ
If you want to pass an option that takes an argument, you have to use -Xassembler twice, one time for the option and one time for the argument. ๐
๐ท 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 waste your energy on them then. ๐ญ
object-file-name๐ โ Any file name that doesn't end in a special recognized suffix is treated as an object file or library. The linker tells objects and libraries apart by looking at the file contents. If linking happens, these files get fed into the linker as input. ๐ง-c,-S,-E๐ โ If you use any of these, the linker doesn't run at all, so you shouldn't pass object file names as arguments. ๐ โโ๏ธ-flinker-output=type๐ง โ This controls code generation for the link-time optimizer. By default, the linker plugin figures out the linker output type automatically. But if you're debugging the compiler, or you want incremental linking with a non-LTO object file, it can be useful to set the type yourself. ๐ง
Here's what each type does:
execmakes code generation produce a static binary. In this case,-fpicand-fpieare both disabled. ๐งdynmakes code generation produce a shared library. Here-fpicor-fPICgets preserved, but it isn't turned on automatically. This lets you build shared libraries without position-independent code on architectures where that's possible, which means x86. ๐ซpiemakes code generation produce an-fpieexecutable. You get similar optimizations toexec, except-fpiedoesn't get disabled if you specified it at compilation time. ๐reltells the compiler to assume incremental linking is happening. The sections holding intermediate code for link-time optimization get merged, pre-optimized, and output to the resulting object file. If you also specify-ffat-lto-objects, binary code gets 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 that static library, as long as most of the objects in the library actually get used. ๐ธnolto-relconfigures the compiler 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 result is better optimized than with link-time optimizations disabled (cross-module inlining happens, yay), but most of the benefits of whole program optimizations are lost. ๐ค
During the incremental link (by -r), the linker plugin defaults to rel. Right now, with the current interfaces to GNU Binutils, it's not possible 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 warns you and uses nolto-rel. To keep whole program optimization, it's recommended to link those objects into a static library instead. Alternatively, you can use H.J. Lu's binutils, which supports mixed objects. ๐ฅน
โ ๏ธ Mixing LTO and non-LTO objects in an incremental link isn't possible with the current GNU Binutils interfaces. The plugin will warn you and fall back to nolto-rel, so static library is the safer move if you want whole program optimization. ๐
-fuse-ld=bfd๐ฃ โ Uses the bfd linker instead of the default one. ๐-fuse-ld=gold๐ โ Uses the gold linker instead of the default one. โจ-fuse-ld=lld๐ โ Uses the LLVM lld linker instead of the default one. ๐ฆ-fuse-ld=mold๐ โ Uses the Modern Linker (mold) instead of the default one. ๐ฅ-llibrary,-l library๐ โ Searches the library namedlibrarywhen linking. The second version, with the library as a separate argument, only exists for POSIX compliance, and honestly you shouldn't use it. ๐
GCC passes -l straight through to the linker, so check your linker's 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. That includes several standard system directories, plus anything you add with -L. ๐บ๏ธ
Static libraries are archives of object files, and they have names like liblibrary.a. Some targets also support shared libraries, which usually look like liblibrary.so. If both kinds are found, the linker prefers the shared library, unless you use the -static option. ๐
Where you put this option in the command actually matters, because 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 foo.o but before bar.o. If bar.o refers to functions in z, those functions might not get loaded. ๐ญ
-lobjc๐ โ You need this special case of-lto 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 up linkage of the system libraries, like-static-libgccor-shared-libgcc, get ignored. The standard startup files are still used normally, unless-nostartfilesis used. ๐งธ
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These are usually resolved by entries in libc. When you use this option, those 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'll still link with the startup files, libgcc, and any toolchain-provided language support libraries such aslibgnat,libgfortran, orlibstdc++, unless options preventing their inclusion are used as well. This typically removes-lcfrom the link command line, along with system libraries that normally go with it and become meaningless when you're assuming there's no C library, like-lpthreador-lmin some configurations. This is meant for bare-board targets where there genuinely is no C library available. ๐ค-nostdlib๐ช โ Don't use the standard system startup files or libraries when linking. No startup files get used, and only the libraries you specify get passed to the linker. Options specifying linkage of the system libraries, like-static-libgccor-shared-libgcc, get ignored. ๐ซ
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These are usually resolved by entries in libc, so when this option is specified, those entry points need to be supplied some other way. ๐ฅบ
One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a. It's a library of internal subroutines that GCC uses to get around shortcomings of particular machines, or special needs of some languages. ๐งฉ
Honestly, you usually still need libgcc.a even when you want to avoid the other standard libraries. So when you specify -nostdlib or -nodefaultlibs, you should usually add -lgcc as well. That way you won't end up with 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 the standard C++ libraries. ๐ซถ-e entry,--entry=entry๐ฏ โ Sets the program entry point toentry. The linker interprets the argument, and the GNU linker accepts either a symbol name or an address. ๐-pie๐ โ Produces a dynamically linked position independent executable on targets that support it. For predictable results, you also have to specify the same set of options you used for compilation (-fpie,-fPIE, or model suboptions) when you use this linker option. ๐-no-pie๐ โโ๏ธ โ Doesn't produce a dynamically linked position independent executable. ๐ค-static-pieโ โจ Makes a static position independent executable on targets that support it. It's like a regular static executable, except it can be loaded at any address without a dynamic linker ๐ง. For predictable results, you also need to use the same options you used for compilation (-fpie,-fPIE, or model suboptions) when you pass this linker option ๐ .-pthreadโ ๐งต Links with the POSIX threads library. This works on GNU/Linux targets, most other Unix derivatives, and x86 Cygwin and MinGW targets. On some targets it also sets flags for the preprocessor, so use it consistently for both compiling and linking ๐ซถ.-rโ ๐งฉ Produces a relocatable object as output. This is also called partial linking.-rdynamicโ ๐ Passes the flag-export-dynamicto the ELF linker, on targets that support it. The linker then adds all symbols to the dynamic symbol table, not just the ones that get used ๐. This option is needed for some uses ofdlopen, or if you want backtraces from inside a program ๐ฅ.-sโ ๐ซง Strips all symbol table and relocation information out of the executable.-staticโ ๐ง On systems that support dynamic linking, this overrides-pieand stops linking with shared libraries. On other systems it does nothing ๐.-sharedโ ๐ฆ Produces a shared object that can be linked with other objects to form an executable. Not every system supports this one ๐. For predictable results, you also need the same options used for compilation (-fpic,-fPIC, or model suboptions) when you pass this linker option[1] โจ.-shared-libgcc,-static-libgccโ ๐ On systems that ship libgcc as a shared library, these force the shared or static version, respectively. If no shared version of libgcc got 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 use the shared libgcc ๐ญ.
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable, since C++ programs usually use exceptions. That's the right move, periodt ๐
.
If you use the GCC driver to make shared libraries instead, they might not always get linked with the shared libgcc ๐ค. If GCC figures 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 takes advantage of the linker and skips linking with the shared libgcc, so it links with the static version by default. This lets exceptions propagate through those shared libraries without paying relocation costs at library load time โญ.
โ ๏ธ However, if a library or main executable is supposed to throw or catch exceptions, you have to link it using the G++ driver, or use the option -shared-libgcc, so it gets linked with the shared libgcc. Don't skip this one bestie ๐ญ.
-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 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 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 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 a shared library and-staticisn't used, it links the shared version, which is usually fine ๐. But sometimes you want to freeze the libstdc++ version 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โ ๐ Binds references to global symbols when building a shared object. It 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 ๐ฅน.-T scriptโ ๐ Uses script as the linker script. Most systems using the GNU linker support this. On some targets, like bare-board targets with no operating system,-Tmay be needed when linking to avoid references to undefined symbols ๐ซ.-Xlinker optionโ ๐ Passes option along to the linker as an option. Handy for system-specific linker options that GCC doesn't recognize ๐ง .
If you want to pass an option that takes a separate argument, you need 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 sends the whole string as one argument, and the linker doesn't want that ๐
โโ๏ธ.
With the GNU linker it's usually easier to pass arguments using the option=value syntax instead of 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โ ๐ Also passes option to the linker. If option has commas in it, it gets split into multiple options at each comma. You can use this syntax to pass an argument to an option. For example,-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, for LDFLAGS, the option-Wl,-z,relrois used. To turn that off, use-Wl,-z,norelro๐.
-u symbolโ ๐ฃ Pretends the symbol symbol is undefined, which forces the linking of library modules that define it. You can use-umultiple times with different symbols to force loading of more library modules ๐งฒ.-z keywordโ โ๏ธ-zgets passed straight to the linker along with the keyword. Check the documentation for your linker to see the permitted values and what they mean ๐.
โจ Options for Directory Search โจ
These options tell GCC which directories to search for header files, libraries, and parts of the compiler ๐๏ธ:
-I dir-iquote dir-isystem dir-idirafter dirโ ๐ Adds the directory dir to the list of directories searched for header files during preprocessing. If dir starts with=or$SYSROOT, that=or$SYSROOTgets swapped out for the sysroot prefix. See--sysrootand-isysrootfor more on that ๐ธ.
Directories given with -iquote only apply to the quote form of the directive, "#include "file"". Directories given with -I, -isystem, or -idirafter apply to lookups for both "#include "file"" and "#include <file>" ๐.
You can mix and match any number of these options on the command line to search for headers in lots of places at once ๐ฆ. The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file gets searched first.
- For the quote form, the directories from
-iquoteoptions get searched left to right, in the order they show up on the command line. - Directories from
-Ioptions get scanned left to right. - Directories from
-isystemoptions get scanned left to right. - Standard system directories get scanned.
- Directories from
-idirafteroptions get scanned left to right.
You can use -I to override a system header file and swap in your own version, since those directories get searched before the standard system header directories ๐ซข. Just don't use this option to add directories full of vendor-supplied system headers. Use -isystem for that ๐ซ.
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 given with -isystem, is also given with -I, the -I option gets ignored. The directory still gets searched, but as a system directory in its normal spot in the system include chain. This keeps GCC's fix-up for buggy system headers and the ordering for the #include_next directive from getting messed up by accident ๐ญ. If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options ๐ง.
-I-โ Splitting the include path, ya know? โ๏ธ This one is deprecated, so please don't reach for it. Use-iquotefor any-Idirectories that come before the-I-, and then drop the-I-altogether. ๐ โโ๏ธ
Any -I directories placed before -I- only get searched for headers pulled in with #include "file". They're skipped for #include <file>. Any -I directories placed after the -I- get searched for every #include directive. ๐บ๏ธ
On top of that, -I- stops the directory of the current file from being used as the first place to look for #include "file". And there's no way to undo that effect of -I-, so choose wisely, bestie. ๐
-iprefix prefixโ Sets prefix as the prefix that later-iwithprefixoptions will use. ๐ If the prefix is a directory, make sure you end it with a final/. ๐-iwithprefix dir,-iwithprefixbefore dirโ Tacks dir onto the prefix you set earlier with-iprefix, then adds the result to the include search path. โจ
-iwithprefixbefore slots it in the same spot -I would. -iwithprefix puts it where -idirafter would. ๐ง
-isysroot dirโ Basically the same vibe as--sysroot, but it only applies to header files. ๐ The exception is Darwin targets, where it covers both header files and libraries. ๐ Check out the--sysrootoption for the full tea. โ-imultilib dirโ Uses dir as a subdirectory of the directory that holds the target-specific C++ headers. ๐ธ-nostdincโ Tells the compiler to skip the standard system directories when hunting for header files. ๐ Only the directories you explicitly give with-I,-iquote,-isystem, and/or-idirafterget searched (plus the directory of the current file, if that makes sense for the situation). ๐-nostdinc++โ Skips the C++-specific standard directories when searching for headers, but still checks the other standard directories. ๐ซถ (This one is used when building the C++ library, so it's giving behind-the-scenes energy. ๐ฅ)--embed-dir=dirโ Adds the dir directory to the list of places searched by the#embedpreprocessing directive or the__has_embedmacro. ๐ฆ There are no default directories for#embed, so you gotta add your own. ๐ญ
If dir starts with = or $SYSROOT, that = or $SYSROOT gets swapped out for the sysroot prefix. Peep --sysroot and -isysroot for more on that. ๐
-iplugindir=dirโ Sets the directory where plugins are searched for when they're passed with-fplugin=nameinstead of-fplugin=path/name.so. ๐ This one isn't really meant for you to use directly. It's only passed along by the driver, so let the driver handle it. ๐ค-Ldirโ Adds the directory dir to the list of directories searched for-llibraries. ๐ฆ-Bprefixโ This is where you tell the compiler where to find its own executables, libraries, include files, and data files. ๐๏ธ
The compiler driver runs one or more of these subprograms: cpp, cc1, as, and ld. ๐ ๏ธ For each one it runs, it tries prefix as a prefix, both with and without machine/version/ for the matching target machine and compiler version. ๐
For each subprogram, the driver checks the -B prefix first (if you gave one). If that doesn't turn anything up, or if -B wasn't specified, it tries two standard prefixes: /usr/lib/gcc/ and /usr/local/lib/gcc/. ๐ If none of those produce a file that actually exists, the plain program name gets searched for using the directories listed in your PATH environment variable. ๐ซ
The compiler checks whether the path you passed to -B is a directory. If it is, the compiler adds a directory separator character at the end if it's needed. ๐
-B prefixes that act like directory names also apply to libraries in the linker, because the compiler turns those options into -L options for the linker. ๐ They also apply to include files in the preprocessor, because the compiler turns 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's not found there, only the two standard prefixes above get tried, and that's the whole list. ๐ If it's still missing after all that, it gets left out of the link. ๐
Another way to set a prefix that works like the -B prefix is the environment variable GCC_EXEC_PREFIX. ๐ท
Okay, here's the lowkey kludge ๐งธ: if the path given to -B is [dir/]stageN/, where N is a number from 0 to 9, it gets replaced with [dir/]include. This is there to help with bootstrapping the compiler. ๐ฅพ
-no-canonical-prefixesโ Don't expand any symbolic links, don't resolve references to/../or/./, and don't make the path absolute when generating a relative prefix. ๐งญ--sysroot=dirโ Makes dir the logical root directory for headers and libraries. ๐ณ For example, if the compiler normally looks for headers in/usr/includeand libraries in/usr/lib, it'll look indir/usr/includeanddir/usr/libinstead. ๐ช
If you use this option and the -isysroot option, then --sysroot applies to libraries, while -isysroot applies to header files. ๐ค
The GNU linker (starting with version 2.16) has the support needed for this option. If your linker doesn't support it, the header file part of --sysroot still works, but the library part doesn't. ๐ค
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory set with--sysroot, depending on what other options you used. So headers might get found indir/suffix/usr/includeinstead ofdir/usr/include. ๐งฉ This option turns off adding that suffix. ๐ซ
โจ Options for Code Generation Conventions โจ
These machine-independent options control the interface conventions the compiler uses during code generation. ๐ง
Most of them come in positive and negative forms. The negative form of -ffoo is -fno-foo. ๐ In the list below, only one form is shown, the one that is not the default. You can work out the other one by either removing no- or adding it. ๐ช
-fstack-reuse=reuse-levelโ This option controls stack space reuse for user-declared local/auto variables and compiler-generated temporaries. ๐ฅ reuse_level can beall,named_vars, ornone.allturns on stack reuse for every local variable and temporary.named_varsonly turns on reuse for user-defined local variables that have names.noneturns stack reuse off completely. The default isall. ๐
You'd need this option when a program stretches the lifetime of a scoped local variable or a compiler-generated temporary past the end point the language defines. โณ When a variable's lifetime ends and it 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 stretches local lifetimes 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:
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?
}
The C++ standard clearly defines the lifetime of a compiler-generated temporary. ๐ When that lifetime ends and the temporary lives in memory, the optimizing compiler can reuse its stack space for other temporaries or scoped local variables whose live range doesn't overlap. ๐ช๏ธ But some legacy code depends on older compilers, where temporaries' stack space was never reused, so the aggressive reuse can lead to runtime errors. ๐ฑ This option is what lets you control that temporary stack reuse optimization. ๐๏ธ
-ftrapvโ Generates traps for signed overflow on addition, subtraction, and multiplication operations. ๐จ The options-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line means-fwrapvis the one that's effective. ๐ซ Only active options override, though, so-ftrapv -fwrapv -fno-wrapvon the command line means-ftrapvis the one that's effective. ๐คฏ-fwrapvโ Tells the compiler to assume that signed arithmetic overflow from addition, subtraction, and multiplication wraps around using two's-complement representation. ๐ This flag enables some optimizations and disables others. ๐ญ The options-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line means-fwrapvis effective. ๐ Only active options override, so-ftrapv -fwrapv -fno-wrapvon the command line means-ftrapvis effective. โจ-fwrapv-pointerโ Tells the compiler to assume that pointer arithmetic overflow on addition and subtraction wraps around using two's-complement representation. ๐ This flag disables some optimizations that assume pointer overflow is invalid. ๐ โโ๏ธ-fstrict-overflowโ This option implies-fno-wrapv -fno-wrapv-pointer, and when it's negated, it implies-fwrapv -fwrapv-pointer. ๐ฆ-fexceptionsโ okay so this turns on exception handling ๐ It generates the extra code needed to propagate exceptions. On some targets it also makes GCC emit frame unwind info for every function, which can bloat your data size a lot (it doesn't slow anything down though ๐ซถ). If you don't say anything, GCC turns it on for languages like C++ that normally need it and leaves it off for languages like C that don't. Still, you might need to flip it on when your C code has to play nicely with exception handlers written in C++ ๐ And if you're compiling older C++ programs that never use exception handling, you may want to switch it off. โจ-fnon-call-exceptionsโ this one lets trapping instructions throw exceptions ๐ฅ Heads up, it needs platform-specific runtime support that doesn't exist everywhere, so check before you get attached. It only lets trapping instructions (memory references or floating-point instructions) throw. It does not let exceptions come out of arbitrary signal handlers like"SIGALRM"๐ Also, it turns on-fexceptionsautomatically.-fdelete-dead-exceptionsโ this basically says instructions that might throw but don't actually contribute to the program's execution can get optimized away ๐งน It doesn't touch calls to functions, except the ones marked with the"pure"or"const"attributes. It's on by default for the Ada and C++ compilers, since the language specs allow it. Which optimization passes actually remove dead exceptions depends on the optimization level, and each pass is enabled on its own schedule. ๐-funwind-tablesโ similar to-fexceptions, except it only generates the static data that's needed and leaves the actual generated code alone ๐ฆ You usually don't have to turn this on yourself, because any language processor that needs this handling switches it on for you. Bestie, you're covered. ๐ซถ-fasynchronous-unwind-tablesโ generates an unwind table in DWARF format, as long as the target machine supports it โจ The table is exact at every instruction boundary, which means it can be used for stack unwinding during asynchronous events, like when a debugger or a garbage collector shows up mid-run ๐-fno-gnu-uniqueโ okay this one is a little dramatic ๐ญ On systems with a recent GNU assembler and C library, the C++ compiler uses the"STB_GNU_UNIQUE"binding so that template static data members and static local variables in inline functions stay unique, even with"RTLD_LOCAL"in the mix. That matters because otherwise a library used by two different"RTLD_LOCAL"plugins could end up disagreeing about what a symbol binds to. The catch is that this makesdlcloseget ignored for the affected DSOs. If your program relies on reinitializing a DSO throughdlcloseanddlopen, reach for-fno-gnu-unique๐ธ-fpcc-struct-returnโ returns"short""struct"and"union"values in memory, just like the longer ones, instead of in registers ๐งบ It's less efficient, but it lets code compiled by GCC play nicely with files compiled by other compilers, especially the Portable C Compiler (pcc) ๐ซถ
The exact convention for returning structures in memory depends on the target configuration macros, so it's not one-size-fits-all.
Short structures and unions are the ones whose size and alignment match some integer type. Cute and specific, iykyk. ๐
Warning: code compiled with-fpcc-struct-returnis not binary compatible with code compiled with-freg-struct-return. Only use it when you need to conform to a non-default application binary interface. ๐
-freg-struct-returnโ returns"struct"and"union"values in registers whenever it's possible ๐ For small structures this is more efficient than-fpcc-struct-return.
If you don't specify either -fpcc-struct-return or -freg-struct-return, GCC just goes with whatever convention is standard for the target. If there's no standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases, GCC gets to pick the standard, and it picked the more efficient register return option. Main character energy ๐
Warning: code compiled with-freg-struct-returnis not binary compatible with code compiled with-fpcc-struct-return. Only use it when you need to conform to a non-default application binary interface. ๐
-fshort-enumsโ gives an"enum"type only as many bytes as it needs to hold its declared range of possible values ๐ To be precise, the"enum"type becomes the smallest integer type with enough room. This does nothing for an enumeration type that has a fixed underlying type.
Warning: -fshort-enums makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface. โ ๏ธ
-fshort-wcharโ overrides the underlying type of"wchar_t"so it's"short unsigned int"instead of the target's default ๐ This one is handy for building programs that run under WINE.
Warning: -fshort-wchar makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface. ๐
-fcommonโ in C code, this option controls where global variables defined without an initializer get placed. Those are called tentative definitions in the C standard ๐ง They're different from declarations of a variable with the"extern"keyword, which don't allocate any storage.
The default is -fno-common, which means the compiler puts uninitialized global variables in the BSS section of the object file. This stops the linker from merging tentative definitions, so you'll get a multiple-definition error if the same variable is accidentally defined in more than one compilation unit. Honestly, that error is saving you. ๐ซถ
-fcommon puts uninitialized global variables in a common block instead. That lets the linker resolve all the tentative definitions of the same variable across different compilation units to the same object, or to a non-tentative definition. The downside: this behavior is inconsistent with C++, and on many targets it costs some speed and code size on global variable references. It's mainly useful for getting legacy code to link without errors ๐ฅฒ
-fno-identโ tells GCC to ignore the#identdirective ๐-finhibit-size-directiveโ don't output a.sizeassembler directive, or anything else that would cause trouble if the function gets split in the middle with the two halves placed far apart in memory ๐ This is used when compilingcrtstuff.c. You shouldn't need it for anything else, bestie.-fverbose-asmโ puts extra commentary into the generated assembly so it's easier to read ๐ This is really only useful for people who actually need to read the generated assembly, like when they're debugging the compiler itself ๐ค
-fno-verbose-asm, which is the default, leaves that extra info out. That's the one you want when you're 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, - hints on which high-level expressions correspond to the various assembly instruction operands.
Here's an example. Say you have this C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
Compiling it to (x86_64) assembly with -S, and sending the result straight to stdout with -o -:
gcc -S test.c -fverbose-asm -Os -o -
gives output similar to 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 meant for humans rather than machines, so the precise format is subject to change. Don't build your life on it ๐ฆ
-frecord-gcc-switchesโ this records the command line you used to invoke the compiler into the object file being created ๐ผ It's only implemented on some targets, and the exact format depends on the target and binary file format. Usually it takes the form of a section containing ASCII text. This one is related to-fverbose-asm, but that switch only puts info into the assembler output as comments, so it never makes it into the object file. If you want another way to store compiler options in the object file, check out-grecord-gcc-switchesโจ-fpicโ ๐ Generates position-independent code (PIC) that's ready for a shared library, as long as your target machine supports it. All constant addresses get accessed through a global offset table (GOT), and the dynamic loader fills in those GOT entries when the program starts. (The dynamic loader isn't part of GCC, it's part of the operating system, so don't blame GCC for it ๐.) If the GOT for your linked executable goes over a machine-specific maximum, the linker throws an error saying-fpicdoesn't work, and then you should recompile with-fPICinstead. The maximums are 8k on the SPARC, 28k on AArch64, and 32k on the m68k and RS/6000. The x86 has no such limit ๐ฆ.
PIC needs special support, so it only works 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 your target machine supports it, this emits position-independent code that's suitable for dynamic linking and doesn't have any limit on the size of the global offset table. It makes a real difference on AArch64, m68k, PowerPC and SPARC.
PIC needs special support, so it only works on certain machines ๐ .
When this flag is set, the macros __pic__ and __PIC__ are defined to 2 ๐.
-fpie,-fPIEโ ๐ง These are basically the same vibe as-fpicand-fPIC, except the position-independent code they generate can only be linked into executables. Usually you'd use them to compile code that's going to get linked with the-pieGCC option ๐.
-fpie and -fPIE both define the macros __pie__ and __PIE__. Those macros have the value 1 for -fpie and 2 for -fPIE โจ.
-fno-pltโ ๐ Don't use the PLT for external function calls in position-independent code. Instead, the callee address gets loaded at the call sites from the GOT, and then the code branches to it. This is more efficient because it gets rid of PLT stubs and exposes GOT loads to optimizations ๐ฅ. On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in one specific register, this gives the compiler more register allocation freedom ๐. Heads up: lazy binding needs the PLT, so with-fno-plt, all external symbols get resolved at load time โญ.
If you only want to skip the PLT for specific external functions, use the function attribute noplt instead ๐ซถ.
In position-dependent code, a few targets will also turn calls to functions marked to not use the PLT into calls through the GOT instead ๐.
-fno-jump-tablesโ ๐ Don't use jump tables forswitchstatements, even when they'd be more efficient than other code generation strategies. This is handy alongside-fpicor-fPICwhen you're building code that's part of a dynamic linker and can't reference the address of a jump table ๐ง. On some targets, jump tables don't need a GOT, so you don't need this option there ๐ .-fno-bit-testsโ ๐ Don't use bit tests forswitchstatements, even if they'd be more efficient than other code generation strategies โจ.-ffixed-regโ ๐ Treat the register namedregas a fixed register. The generated code should never touch it (unless it's maybe being used as a stack pointer, frame pointer, or some other fixed role) ๐.
reg has to be an actual register name. The names you can use depend on the machine, and they're defined in the REGISTER_NAMES macro in the machine description macro file ๐ค.
This flag doesn't have a negative form, because it's a three-way choice ๐ซ.
-fcall-used-regโ ๐ฆ Treat the register namedregas an allocable register that gets clobbered by function calls. It can be allocated for temporaries or for variables that don't live across a call. Functions compiled this way do not save and restore the registerreg๐ญ.
It's an error to use this flag with the frame pointer or stack pointer ๐ซ. Using it on other registers with fixed, pervasive roles in the machine's execution model gives disastrous results ๐.
This flag doesn't have a negative form either, since it's a three-way choice ๐ .
-fcall-saved-regโ ๐ก๏ธ Treat the register namedregas an allocable register that's saved by functions. It can be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restoreregif they use it ๐ซถ.
Same deal as before: it's an error to use this with the frame pointer or stack pointer โ. Using it on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results ๐ฑ.
A different kind of disaster happens if you use this flag on a register where function values get returned ๐.
Again, no negative form, because it's a three-way choice โจ.
-fpack-struct[=n]โ ๐ฆ With no value, this packs all structure members together with no holes. When you give it a value, which has to be a small power of two, structure members get packed according to that value, which represents the maximum alignment. Objects whose default alignment requirements are bigger than this get output potentially unaligned at the next fitting location ๐ธ.
โ ๏ธ Warning: -fpack-struct makes GCC generate code that is not binary compatible with code generated without that switch. It also makes the code suboptimal ๐. Only use it to conform to a non-default application binary interface ๐.
-fleading-underscoreโ ๐ This one and its counterpart,-fno-leading-underscore, forcibly change how C symbols are represented in the object file. One use for it is linking with legacy assembly code ๐งธ.
โ ๏ธ Warning: -fleading-underscore makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface. Also, not every target fully supports this switch ๐ฌ.
-ftls-model=modelโ ๐งต Changes the thread-local storage model. Themodelargument should be one ofglobal-dynamic,local-dynamic,initial-execorlocal-exec. The choice is subject to optimization, though: the compiler might pick a more efficient model for symbols that aren't visible outside the translation unit, or if-fpicisn't given on the command line โจ.
Without -fpic, the default is initial-exec. With -fpic, the default is global-dynamic ๐.
-ftrampolinesโ ๐ช For targets that normally need trampolines for nested functions, this always generates them instead of using descriptors. For targets that don't need them, like HP-PA or IA-64, it does nothing ๐.
A trampoline is a tiny bit of code created at run time on the stack when the address of a nested function is taken. It gets used to call the nested function indirectly. Because of that, the stack has to be made executable for the program to work properly ๐.
-fno-trampolines is enabled by default on a language-by-language basis, so the compiler can avoid generating trampolines when it works out that it's safe, and replace them with descriptors instead ๐ง . Descriptors are made up of data only, but the generated code has to be ready to deal with them. As of this writing, -fno-trampolines is enabled by default only for Ada ๐.
Heads up: 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 program-wide, and you need to handle it with extreme care ๐ซฃ.
For languages other than Ada, the -ftrampolines and -fno-trampolines options currently have no effect, and trampolines are always generated on platforms that need them for nested functions ๐
.
-ftrampoline-impl=[stack|heap]โ ๐ By default, trampolines are generated on the stack. But some platforms, like the Apple M1, don't allow an executable stack ๐ . Compiling with-ftrampoline-impl=heapmakes GCC generate calls to__gcc_nested_func_ptr_createdand__gcc_nested_func_ptr_deletedso that trampoline space gets allocated and deallocated on the executable heap. These functions are implemented in libgcc, and they'll only be provided on specific targets: x86_64 Darwin, and 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]โ ๐ Sets the default ELF image symbol visibility to the option you specify. Every symbol gets marked with this unless it's overridden within the code. This can really improve linking and load times for shared object libraries, produce more optimized code, give you near-perfect API export, and prevent symbol clashes. It's strongly recommended that you use 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, meaning every symbol is public ๐.
For a good explanation of why ELF symbols should have the correct visibility, check out "How To Write Shared Libraries" by Ulrich Drepper, which you can find at <https://www.akkadia.org/drepper/> ๐. But here's the superior move this option makes possible: instead of marking things hidden when the default is public, make the default hidden and mark things public. This is the norm with DLLs on Windows. With -fvisibility=hidden and __attribute__ ((visibility("default"))) in place of __declspec(dllexport), you get almost identical semantics with identical syntax. This is a huge win for anyone working on cross-platform projects ๐โจ.
For those adding visibility support to existing code, #pragma GCC visibility is a total lifesaver ๐ซถ. You wrap the declarations you want to style with something like #pragma GCC visibility push(hidden), and then close it with #pragma GCC visibility pop. โจ Now, bestie, symbol visibility is part of the API interface contract, so all new code should always spell out visibility whenever it isn't the default. Declarations that are only used inside the local DSO should be marked hidden explicitly, so you skip the PLT indirection overhead ๐
. Being this clear also makes the code easier to read and basically documents itself ๐๐. One thing to know: because of ISO C++ spec requirements, operator new and operator delete must always have default visibility ๐ซ.
Be careful with headers from outside your project, like system headers and headers from any other library you use ๐. They may not expect to be compiled with anything other than the default visibility. You might need to say #pragma GCC visibility push(default) before including them.
extern declarations aren't affected by -fvisibility, so a ton of code can be recompiled with -fvisibility=hidden with zero changes ๐ฆ. The catch is that calls to extern functions with no explicit visibility go through the PLT. So it's way 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 gets thrown between DSOs must be explicitly marked with default visibility, so the type_info nodes get unified between the DSOs ๐ญ.
If you want an overview of these techniques, what they do for you, and how to use them, check out <https://gcc.gnu.org/wiki/Visibility> ๐ธ.
โจ -fstrict-volatile-bitfields โจ
-fstrict-volatile-bitfieldsโ Use this when accesses to volatile bit-fields (or other structure fields, though the compiler usually respects those types anyway) should be a single access at the width of the field's type, aligned to natural alignment if possible ๐. For example, targets with memory-mapped peripheral registers might need every access to be 16 bits wide. With this flag, you can declare all the peripheral bit-fields asunsigned short(assumingshortis 16 bits on those targets) to force GCC to use 16-bit accesses instead of a potentially more efficient 32-bit access ๐.
If this option is disabled, the compiler goes for whatever is most efficient ๐๏ธ. In the example above, that could be a 32-bit load, even though it touches bytes that don't contain any part of the bit-field, or memory-mapped registers unrelated to the one being updated ๐ฌ.
In some cases, like when the packed attribute is applied to a structure field, it might not be possible to access the field with one correctly aligned read or write for the target machine ๐ฅบ. When that happens, GCC falls back to generating multiple accesses, instead of code that would fault or truncate the result at run time. Honestly, that's the responsible move ๐ซถ.
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 โจ
-fsync-libcallsโ This controls whether any out-of-line instance of the__syncfamily of functions may be used to implement the C++11__atomicfamily of functions ๐.
The default is enabled, so the only useful form of this option is -fno-sync-libcalls ๐
. This option is used in the implementation of the libatomic runtime library ๐.
โจ -fzero-init-padding-bits=value โจ
-fzero-init-padding-bits=valueโ This guarantees zero initialization of padding bits in automatic variable initializers ๐งธ. Some languages promise zero-initialized padding bits in certain cases. For example, C23 does this when you use empty initializers ({}), and C++ does it with zero-initialization. Also, C guarantees 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 matching standard does. Here's an example, bestie ๐:
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 guarantees zero initialization of padding bits in unions, on top of what the standards already guarantee ๐. This happens if the initializer of a union is empty (then all bits of the union are zero initialized), or if the initialized member of the union is smaller than the size of the union (then padding bits outside the initialized member are guaranteed to be zero initialized). 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 also guarantees zero initialization of padding bits in other aggregates ๐ธ. That covers the padding in between b.a and b.b (if there is any), and the tail padding in the structure (if there is any) โจ.
NOTE: In Ubuntu 25.10 and later versions,-fzero-init-padding-bits=allis enabled by default for C, C++, ObjC, and ObjC++, unless-fzero-init-padding-bits=standardis found ๐จ.
โจ GCC Developer Options โจ
This section covers command-line options that are mainly for GCC developers ๐งโ๐ป. That includes options for compiler testing, digging into compiler bugs, and looking at compile-time performance problems ๐. It also covers options that produce 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'll rarely need any of these for ordinary compiling and linking ๐.
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 =filename is left out, GCC builds a default dump file name by concatenating the base dump file name, a pass number, a phase letter, and the pass name ๐งฉ. The base dump file name is the name of the output file 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 are registered with the compiler's pass manager ๐ข. That's usually the same as the execution order, 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) ๐ค. The files get created in the directory of the output file ๐.
-fcallgraph-info,-fcallgraph-info=MARKERSโ This makes the compiler output callgraph information for your program, one per object file ๐ธ๏ธ. The info is generated in the common VCG format. You can decorate it with extra per-node and/or per-edge information by passing a comma-separated list of markers. If thesumarker is included, the callgraph gets stack usage info, which is the same as-fstack-usage. If thedamarker is included, the callgraph gets info about dynamically allocated objects ๐ง .
When you compile with -flto, no callgraph info gets output along with the object file ๐
. At LTO link time, -fcallgraph-info may generate multiple callgraph info files next to the intermediate LTO output files ๐.
-dletters,-fdump-rtl-pass,-fdump-rtl-pass=filenameโ This tells GCC to make debugging dumps during compilation at the times specified by the letters ๐. It's used for debugging the RTL-based passes of the compiler ๐ ๏ธ.
Some -dletters switches mean something different when -E is used for preprocessing ๐ง.
Debug dumps can be enabled with a -fdump-rtl switch or with some -d option letters ๐ก. Here are the possible letters you can use in pass and letters, and what they mean ๐:
-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 โณ.
Okay so bestie, we're picking up right where the RTL dump flags leave off ๐ โจ
-fdump-rtl-dce1,-fdump-rtl-dce2โ ๐งน these two turn on dumping after the two dead store elimination passes. Dead stores get yeeted, and you get to see the receipts.-fdump-rtl-ehโ ๐ก๏ธ dumps after the finalization of the EH handling code.-fdump-rtl-eh_rangesโ ๐บ๏ธ dumps after the conversion of the EH handling range regions.-fdump-rtl-expandโ ๐ฑ dumps after RTL generation.-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ โก๏ธ turn on dumping after the two forward propagation passes.-fdump-rtl-gcse1,-fdump-rtl-gcse2โ ๐ turn on dumping after global common subexpression elimination. No more doing the same math twice, periodt.-fdump-rtl-init-regsโ ๐ฌ dumps after the registers get initialized.-fdump-rtl-initvalsโ ๐งฎ dumps after the initial value sets are computed.-fdump-rtl-into_cfglayoutโ ๐งฑ dumps right 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โ ๐ turns on dumping after the RTL loop optimization passes.-fdump-rtl-machโ ๐ง dumps after the machine dependent reorganization pass, if that pass actually exists on your target.-fdump-rtl-mode_swโ ๐ dumps after redundant mode switches are removed.-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 the post-reload optimizations.-fdump-rtl-pro_and_epilogueโ ๐ dumps after the function prologues and epilogues get generated.-fdump-rtl-sched1,-fdump-rtl-sched2โ ๐ turn on 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 branches get shortened.-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ โ๏ธ these enable dumping after five rounds of instruction splitting. Five whole rounds, bestie ๐ญ-fdump-rtl-smsโ ๐ dumps after modulo scheduling. Heads up: this pass only runs on some architectures, so it might not show up for you.-fdump-rtl-stackโ ๐ฅ dumps after GCC's "flat register file" registers get converted into the x87's stack-like registers. This pass only runs on x86 variants, so it's x86-only energy.-fdump-rtl-subreg1,-fdump-rtl-subreg2โ ๐งฌ turn on dumping after the two subreg expansion passes.-fdump-rtl-vartrackโ ๐ dumps after variable tracking.-fdump-rtl-vregsโ ๐ dumps after virtual registers get converted 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 dumps are defined but they always produce empty files. Not a bug, just vibes with nothing in them.-da,-fdump-rtl-allโ ๐ produce all the dumps listed above. Everything, all at once, no cap.-dAโ ๐ท๏ธ annotates the assembler output with miscellaneous debugging information.-dDโ ๐ dumps all macro definitions at the end of preprocessing, on top of the normal output.-dHโ ๐ produces a core dump whenever an error occurs. Dramatic, but it works.-dpโ ๐ฌ annotates the assembler output with a comment showing which pattern and alternative got used. The length and cost of each instruction get printed too.-dPโ ๐ dumps the RTL in the assembler output as a comment before each instruction. It also turns on-dpannotation, so it's a whole package deal.-dxโ ๐งช just generates RTL for a function instead of compiling it. Usually paired 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. Early bird gets the debug info.-fdump-noaddrโ ๐ when doing debugging dumps, this suppresses address output. That makes it way easier todiffdumps from compiler invocations using different compiler binaries and/or different text / bss / data / heap / stack / dso start locations.-freport-bugโ ๐จ collects and dumps debug information into a temporary file if an internal compiler error (ICE) occurs. Oops moment, but make it useful.-fdump-unnumberedโ ๐ข when doing debugging dumps, this suppresses instruction numbers and address output. Super handy fordiff-ing dumps from invocations with different options, especially with and without-g.-fdump-unnumbered-linksโ ๐ when doing debugging dumps (see the-doption above), this suppresses instruction numbers for the links to the previous and next instructions in a sequence.-fdump-ipa-switch,-fdump-ipa-switch-optionsโ ๐งญ control the dumping at various stages of inter-procedural analysis language tree to a file. The file name is generated by appending a switch specific suffix to the source file name, and the file gets created in the same directory as the output file. Here are the dumps you can ask for: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.
Also, you can tack on -optimized, -missed, -note, and -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 callsites that were inlined, along with callsites that were not inlined. Main character energy ๐
By default, the dump includes messages about successful optimizations (same as -optimized) together with low-level details about the analysis. ๐
-fdump-ipa-clonesโ ๐ creates a dump file with info about call graph node clones being created, and call graph nodes being removed, during inter-procedural optimizations and transformations. Its main purpose is so tools that make live-patches can figure out which functions need to be live-patched to fully replace a particular function (see-flive-patching). The file name is made by appending the suffixipa-clonesto the source file name, and it lives in the same directory as the output file. Each entry sits on its own line with semicolon separated fields.
For call graph clone creation, the fields are:
- String
"Callgraph clone". - Name of the function being cloned, as the assembler sees it.
- A number that uniquely identifies the function being cloned in the call graph. 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 is located.
- The column where the function definition is located.
- Name of the new function clone, as the assembler sees it.
- A number that uniquely identifies 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 says the reason for cloning.
For call graph clone removal, the fields are:
- String
"Callgraph removal". - Name of the function being removed, as it would be presented to the assembler.
- A number that uniquely identifies the function being cloned in the call graph. Again, unique only within a compilation unit or whole-program analysis, and likely different in 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โ ๐ฃ๏ธ dumps language-specific info. The file name is made by appending.langto the source file name.-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ ๐๏ธ control the dumping of language-specific info. The options and filename parts work the same way they do for-fdump-tree. These switch values are accepted:allโ ๐ธ enables all language-specific dumps.classโ ๐๏ธ dumps class hierarchy info. Virtual table info gets emitted unlessslimis specified. This one is C++ only.moduleโ ๐ฆ dumps module info. The optionslineno(locations),graph(reachability),blocks(clusters),uid(serialization),alias(mergeable),asmname(Elrond),eh(mapper) &vops(macros) may add extra info. This one is C++ only too.rawโ ๐งพ dumps the raw internal tree data. C++ only, bestie.
-fdump-passesโ ๐จ๏ธ prints on stderr the list of optimization passes that are turned on and off by your current command-line options. Perfect for checking what's actually running โจ
โจ OPTIONS โจ (continued) ๐
-fdump-statistics-option ๐ โ okay so this one turns on pass statistics dumping and lets you control it, and the stats land in their own file! ๐ง The file name is your source file name with a suffix ending in .statistics stuck on the end, and it gets created in the same directory as your output file ๐. If you use the -option form, -stats sums the counters over the whole compilation unit, while -details dumps every single event as the passes generate them ๐. With no option at all, it just sums the counters for each function compiled. Simple and iconic ๐
-fdump-tree-all, -fdump-tree-switch, -fdump-tree-switch-options, -fdump-tree-switch-options=filename ๐ณ โ these are your tree dump switches! They control dumping at the various stages where GCC processes the intermediate language tree, into a file. If you use the -options form, options is a list of - separated options that tune the details of the dump. Not every option works with every dump, so the ones that don't make sense just get ignored, no drama ๐ Here's the lineup:
address๐ โ prints the address of each node. Usually this isn't very meaningful since it changes depending on the environment and source file, but its main use is tying a dump file to a debug environment.asmname๐ท๏ธ โ ifDECL_ASSEMBLER_NAMEhas been set for a given decl, this uses that in the dump instead ofDECL_NAME. The main perk is working backward from mangled names in the assembly file, which is so helpful ๐ซถslim๐ฅ โ when dumping front-end intermediate representations, this stops members of a scope or a function body from being dumped just because that scope was reached. Only items directly reachable by some other path get dumped. When dumping pretty-printed trees, it skips the bodies of control structures. 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, so this is the un-glammed version.details๐ โ enables more detailed dumps (not honored by every dump option) and also includes info from the optimization passes.stats๐ โ enables dumping various statistics about the pass (again, not honored by every dump option).blocks๐งฑ โ shows basic block boundaries. This one is disabled in raw dumps, so no sneaking it in there!graph๐ธ๏ธ โ for each of the other indicated dump files (-fdump-rtl-pass), this dumps a representation of the control flow graph tofile.passid.pass.dot, suitable for viewing with GraphViz. Each function in the file is pretty-printed as a subgraph, so GraphViz can render them all in one single plot. This only works for RTL dumps, and the RTL is always dumped in slim form.vops๐ฏ โ shows virtual operands for every statement.lineno๐ข โ shows line numbers for statements.uid๐ โ shows the unique ID (DECL_UID) for each variable.verbose๐ฃ๏ธ โ shows the tree dump for each statement.eh๐ โ shows the EH region number holding each statement.scev๐งฎ โ shows scalar evolution analysis details.optimizedโก โ shows optimization information (only available in certain passes).missed๐ โ shows missed optimization information (only available in certain passes).note๐ โ shows other detailed optimization information (only available in certain passes).all๐ โ turns on all options exceptraw,slim,verboseandlineno. Not everything, bestie, be picky!optall๐ โ turns on all the optimization options, which meansoptimized,missed, andnote.
Wondering what tree dumps are available or how to find the dump for a specific pass? Follow these steps, it's giving treasure hunt ๐บ๏ธโจ
- Invoke GCC with
-fdump-passesand look in the stderr output for a code that matches the pass you care about. For example, the codestree-evrp,tree-vrp1, andtree-vrp2correspond to the three Value Range Propagation passes. The number at the end tells apart different invocations of the same pass. - To turn on the creation of the dump file, tack the pass code onto the
-fdump-option prefix and invoke GCC with it. For example, to get the dump from the Early Value Range Propagation pass, invoke GCC with the-fdump-tree-evrpoption. You can optionally name the dump file too. 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: the numeric codes are not stable and may change from one version of GCC to another ๐
-fopt-info, -fopt-info-options, -fopt-info-options=filename ๐ก โ these control optimization dumps from the various optimization passes. If you use the -options form, options is a list of - separated option keywords that pick the dump details and optimizations.
The options split into three groups: ๐งฉ
- options describing what kinds of messages should be emitted,
- options describing how verbose the dump is, and
- options describing which optimizations should be included.
You can freely mix options from each group since they don't overlap. If there's ever a conflict, the later option wins over the earlier one on the command line ๐
These options control which kinds of messages get emitted:
optimizedโ โ prints info when an optimization is successfully applied. It's up to each pass to decide what's relevant. For example, the vectorizer passes print the source location of loops that get successfully vectorized.missedโ โ prints info about missed optimizations. Individual passes decide what goes in 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.
This option controls the dump verbosity:
internals๐ฌ โ by default, only "high-level" messages are emitted. This turns on extra, more detailed messages, which are mostly only useful to GCC developers, so it's giving nerd ๐ค
These keywords let you pick a whole group of optimizations at once:
ipa๐งโ๐คโ๐ง โ enables dumps from all interprocedural optimizations.loop๐ โ enables dumps from all loop optimizations.inline๐ฆ โ enables dumps from all inlining optimizations.omp๐งต โ enables dumps from all OMP (Offloading and Multi Processing) optimizations.vec๐ โ enables dumps from all vectorization optimizations.optall๐ โ enables dumps from all optimizations. This is a superset of the optimization groups listed above.
If options is left out, it defaults to optimized-optall, which means dumping messages about successful optimizations from all the passes, skipping anything treated as "internals" ๐
If you give a filename, the dumps from all the applicable optimizations get concatenated into that file. Otherwise the dump goes to stderr. You can use multiple -fopt-info options, but only one of them can include a filename. If other filenames show up, all but the first such option get ignored, so choose wisely ๐ซ
Heads up: the output filename gets overwritten when there are multiple translation units. If you want a combined output from multiple translation units, use stderr instead! ๐จ
Check out these examples. The first sends the optimization info to stderr:
gcc -O3 -fopt-info
This one outputs 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 optimization opportunities from the vectorization passes on stderr. Bonus tea: -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec, and the order of the optimization group names and message types after -fopt-info doesn't matter ๐
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, consider this one ๐:
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Here, the two output filenames vec.miss and loop.opt clash, since only one output file is allowed. In this case only the first option takes effect and the rest get ignored. So only vec.miss gets produced, and it contains the dumps from the vectorizer about missed opportunities ๐ญ
-fsave-optimization-record ๐พ โ writes a SRCFILE.opt-record.json.gz file detailing which optimizations were performed, for the optimizations that support -fopt-info.
Warning: this option is experimental, and the format of the data inside the compressed JSON file is subject to change. Don't build your whole life on it yet! ๐งช
It's roughly equivalent to a machine-readable version of -fopt-info-all, as a collection of messages with source file, line number and column number. Each message also comes with the following extra data: โจ
- the execution count of the code being optimized, along with metadata about whether it came from actual profile data or just an estimate, so consumers can prioritize messages by code hotness ๐ฅ,
- the function name of the code being optimized, where applicable ๐ท๏ธ,
- the "inlining chain" for the code being optimized, so that when a function is inlined into several different places (which might themselves be inlined), the reader can tell the copies apart ๐งฉ,
bestie, the message details are lowkey the best part ๐ each one hands you:
- ๐ the parts of the message that point at expressions, statements or symbol-table nodes, which kind of thing each one is, and (when GCC knows it โจ) the source code location
- ๐ ๏ธ the GCC pass that spat out the message, and
- ๐ the spot in GCC's own code where the message came from
Also, some messages are logically nested inside other messages, because they mirror the little implementation details of the optimization passes ๐ง
-fsched-verbose=nโ okay so, on targets that do instruction scheduling ๐ this one controls how chatty the scheduler is when it writes debugging output to the dump files.
For n greater than zero, it gives you the same info as -fdump-rtl-sched1 and -fdump-rtl-sched2 ๐ For n greater than one, it also adds basic block probabilities, detailed ready list info and unit/insn info. For n greater than two, it throws in RTL at the abort point, control-flow and regions info. And for n over four, -fsched-verbose also brings the dependence info ๐ญ๐ฅ
-fenable-kind-pass,-fdisable-kind-pass=range-listโ this is a whole family of options for explicitly turning optimization passes on and off ๐ฆ They're meant for debugging GCC itself. Regular compiler users should stick to the normal options for enabling and disabling passes instead ๐ซถ-fdisable-ipa-passโ disables the IPA pass called pass, where pass is the pass name ๐ If the same pass gets invoked statically more than once in the compiler, add a sequential number to the name, starting from 1.-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ disables the RTL pass called pass โจ pass is the pass name, and the same numbering rule applies if it runs more than once. range-list is a comma-separated list of function ranges or assembler names. Each range is a number pair split by a colon, and it's inclusive on both ends ๐ธ If the range is trivial, you can shorten the number pair to a single number. If a function's call graph node uid falls inside one of the 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 with-fdump-passes๐-fdisable-tree-pass,-fdisable-tree-pass=range-listโ disables the tree pass called pass ๐ Check out-fdisable-rtlfor how the option arguments work.-fenable-ipa-passโ the opposite energy: enables the IPA pass called pass ๐ pass is the pass name, and if it's invoked more than once, the same sequential numbering from 1 applies.-fenable-rtl-pass,-fenable-rtl-pass=range-listโ enables the RTL pass called pass ๐ See-fdisable-rtlfor the option argument description and examples.-fenable-tree-pass,-fenable-tree-pass=range-listโ enables the tree pass called pass โญ Same deal, see-fdisable-rtlfor the description of option arguments.
Here are some examples of these options in action ๐ง
# 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, so keep that in mind ๐-frandom-seed=stringโ this gives GCC a seed to use instead of random numbers when it generates certain symbol names that have to be unique in every compiled file ๐ฆ It's also used to stamp coverage data files and the object files that produce them. Pair it with-frandom-seedto get reproducibly identical object files, and that's a whole mood ๐ซถ
The string can be a number (decimal, octal or hex) or an arbitrary string. If it's an arbitrary string, GCC converts it to a number by computing CRC32 ๐ข
โ ๏ธ the string should be different for every file you compile, bestie!
-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 together 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 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/, where outdir/ is the directory of the output file given after the-ooption, including any directory separators ๐ท If you don't use-o, then-save-temps=objbehaves just like-save-temps=cwdโจ-time[=file]โ reports the CPU time each subprocess in the compilation sequence takes โฑ๏ธ For C source files, that's the compiler proper and the assembler (plus the linker if linking happens) ๐ง
Without an output file specified, 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 the program's behalf. Both numbers are in seconds ๐ฐ๏ธ
With an output file specified, the output gets appended to that named file and 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 shown too ๐ช That way 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's name comes from appending ".gkd" to the dump base name, see-dumpbase.-fcompare-debug[=opts]โ if no error happens during compilation, this runs the compiler a second time, adding opts and-fcompare-debug-secondto the arguments for that second run ๐ช It dumps the final internal representation in both compilations and prints an error if they differ. Iconic debugging energy ๐ญ
If the equal sign is omitted, the default -gtoggle is used.
The environment variable GCC_COMPARE_DEBUG, if it's defined, non-empty and nonzero, implicitly enables -fcompare-debug ๐ If GCC_COMPARE_DEBUG is defined to a string starting with a dash, that string is used for opts. Otherwise the default -gtoggle is used.
-fcompare-debug=, with the equal sign but without opts, is the same as -fno-compare-debug ๐
That turns off dumping the final representation and the second compilation, and it even stops GCC_COMPARE_DEBUG from taking effect.
To verify full coverage during -fcompare-debug testing, set GCC_COMPARE_DEBUG to say -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any actual compilation (rather than preprocessing, assembly or linking) ๐ If you only want a warning instead, setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do the trick โจ
-fcompare-debug-secondโ this one gets passed to the compiler implicitly for the second compilation requested by-fcompare-debug๐ซง 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. Dump files and preserved temporary files get renamed to include the ".gk" extra extension during that second compilation, 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. That makes it pretty useful for basically nothing except debugging the compiler proper ๐ค
-gtoggleโ turns off debug info generation if leaving out this option would generate it, or turns it on at level 2 otherwise ๐ Its position on the command line doesn't matter. It takes effect after all other options are processed, and it only does so once, no matter how many times you give it. It's mainly meant to be used with-fcompare-debug๐-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-assignments๐ It works the same way that-gtoggletoggles-g.-Qโ when you use it on the command line before--help=,-Qacts as a modifier for the help output ๐งพ
Otherwise, this option makes the compiler print out each function name as it gets compiled, and print some statistics about each pass when it finishes ๐
-ftime-reportโ makes the compiler print some statistics to stderr about the time each pass consumed when it finishes โณ
If SARIF output of diagnostics was requested with -fdiagnostics-format=sarif-file or -fdiagnostics-format=sarif-stderr, then the -ftime-report information gets emitted as JSON inside the SARIF output instead ๐งฉ The precise format of that JSON data is subject to change, and the values may not exactly match what goes to stderr, since they're written out at a slightly different place within 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 is 5. Ifnis greater than or equal to 10, the dump output gets sent to stderr using the same format asnminus 10 ๐-flto-reportโ okay so this one's a total gossip sesh for the compiler ๐ต๏ธโโ๏ธ It prints a report with internal details on how the link-time optimizer is working. The contents change from version to version, so don't get too attached to the exact format. It's mainly for GCC developers poking around when processing object files in LTO mode (via-flto) ๐ฆ
Disabled by default ๐
-flto-report-wpaโ same tea as-flto-report, but it only spills during the WPA phase of link-time optimization ๐ซ-fmem-reportโ the compiler gives you a little stats recap about permanent memory allocation once it's totally finished ๐โจ-fmem-report-wpaโ same memory stats moment, but only for the WPA phase ๐ง-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ the compiler spills permanent memory allocation stats either before or after interprocedural optimization. Pick your timeline bestie ๐ฐ๏ธ๐-fmultiflagsโ this one is lowkey iconic ๐ It lets multilib-awareTFLAGSbuild target libraries with options that are different 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, it means the target libraries can be built for portable baseline environments, while the compiler's defaults stay more demanding. That's so useful, because users can easily override the compiler's defaults for their own programs if those aren't ideal for their target environment. Rebuilding the runtime libraries is usually not as easy or desirable, so this is a whole vibe ๐ธ
Unlike TFLAGS, specs let different flags get picked for different multilibs. The way to make that happen is to build with make TFLAGS=-fmultiflags, after configuring with --with-specs=%{fmultiflags:...}.
โ ๏ธ This option gets discarded by the driver once it's done processing driver self spec. So it's gone after that, periodt.
It's also handy for checking that TFLAGS are being used to build all the 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โ the compiler prints stats about how consistent the (estimated) profile is and what effect each individual pass had ๐-fstack-usageโ the compiler outputs stack usage info for your program, per function ๐ฅ The dump file's name is made by appending.suto the auxname. The auxname comes from the name of the output file if you explicitly specified one and it isn't 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 "static" qualifier means the function handles 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 happen in the function. The second field is that fixed number of bytes ๐งฑ
The "dynamic" qualifier means the function handles the stack dynamically. On top of the static allocation, stack adjustments are made in the function body, like pushing and popping arguments around function calls ๐ข If the "bounded" qualifier is also there, 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 adjustments isn't bounded at compile time, and the second field only represents the bounded part.
-fstatsโ emits stats about front-end processing at the end of compilation. Only the C++ front end supports this, and the info is mostly only useful to the G++ dev team ๐ค-fdbg-cnt-listโ prints the name and the counter upper bound for every debug counter ๐ข-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 counter's name and a list of closed intervals. The lower bound is 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) only returns true for the second, third, fourth, tenth and eleventh invocation. For dbg_cnt(tail_call), true is returned for the first 10 invocations ๐
-print-file-name=libraryโ prints the full absolute name of the library filelibrarythat would be used when linking, and then stops right there. GCC doesn't compile or link anything with this one, it just spits out the file name ๐จ๏ธ-print-multi-directoryโ prints the directory name for the multilib selected by any other switches on the command line. That directory is supposed to exist inGCC_EXEC_PREFIX๐-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-, and there are no spaces between multiple switches. This is meant to make shell processing easier ๐-print-multi-os-directoryโ prints the path to OS libraries for the selected multilib, relative to somelibsubdirectory. If OS libraries are in thelibsubdirectory and no multilibs are used, this is usually just.. If OS libraries are inlibsuffixsibling directories, it prints something like../lib64,../libor../lib32. If they're inlib/subdirsubdirectories, it prints something likeamd64,sparcv9orev6๐-print-multiarchโ prints the path to OS libraries for the selected multiarch, relative to somelibsubdirectory ๐๏ธ-print-prog-name=programโ same vibe as-print-file-name, but it searches for a program likecppinstead ๐-print-libgcc-file-nameโ same as-print-file-name=libgcc.aโจ
This is useful when you use -nostdlib or -nodefaultlibs but you do want to link with libgcc.a. You can do:
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirsโ prints the name of the configured installation directory and a list of the program and library directories gcc searches. Then it stops, no other action ๐
This is a lifesaver when gcc prints the error message installation problem, cannot exec cpp0: No such file or directory. To fix it, you either put cpp0 and the other compiler components where gcc expects to find them, or you set the environment variable GCC_EXEC_PREFIX to the directory where you installed them. And don't forget the trailing /! ๐
-print-sysrootโ prints the target sysroot directory that's used during compilation. This is the target sysroot specified either at configure time or with the--sysrootoption, possibly with an extra suffix that depends on compilation options. If no target sysroot is specified, it prints nothing ๐ท-print-sysroot-headers-suffixโ prints the suffix added to the target sysroot when searching for headers. If the compiler isn't configured with such a suffix, it gives an error instead. Then it stops ๐ซ-dumpmachineโ prints the compiler's target machine (for example,i686-pc-linux-gnu) and that's it ๐ฅ๏ธ-dumpversionโ prints the compiler version (for example,3.0,6.3.0or7) and then stops ๐ซง This is the compiler version used in filesystem paths and specs. Depending on how the compiler was configured, it can be a single number (major version), two numbers separated by a dot (major and minor version), or three numbers separated by dots (major, minor and patchlevel version).-dumpfullversionโ prints the full compiler version and nothing else. The output is always three numbers separated by dots: major, minor and patchlevel version ๐ฏ-dumpspecsโ prints the compiler's built-in specs, then stops. (This one gets used when GCC itself is being built ๐ ๏ธ)
๐ Machine-Dependent Options ๐
Each target machine GCC supports can have its very own options. For example, you can compile for a particular processor variant or ABI, or control optimizations that are specific to that machine. By convention, the names of machine-specific options start with -m ๐
Some configurations of the compiler also support extra target-specific options. These are usually there for compatibility with other compilers on the same platform ๐ซถ
๐ฆ AArch64 Options ๐ฆ
These options are defined for AArch64 implementations:
-mabi=nameโ generates code for the specified data model. The valid values areilp32, which is a SysV-like data model whereint,long intand pointers are 32 bits, andlp64, which is a SysV-like data model whereintis 32 bits butlong intand pointers are 64 bits ๐ง
The default depends on the 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 with a compatible set of libraries.
โ ๏ธ The ilp32 model is deprecated. Not the vibe anymore, bestie ๐
-mbig-endianโ generates big-endian code. This is the default when GCC is configured for anaarch64_be-*-*target ๐-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 little-endian code. This is the default when GCC is configured for anaarch64-*-*target but not anaarch64_be-*-*target ๐-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 ๐-mcmodel=largeโ generates code for the large code model. It makes no assumptions about addresses and sizes of sections. Programs can only be statically linked with this one. Also,-mcmodel=largeis incompatible with-mabi=ilp32,-fpicand-fPIC, so don't mix them up ๐
๐ OPTIONS (AArch64 cont.) ๐
-mtp=name lets you pick which system register acts as the thread pointer ๐งต. The valid values are tpidr_el0, tpidrro_el0, tpidr_el1, tpidr_el2, and tpidr_el3. For backwards compatibility, the aliases el0, el1, el2, and el3 also work ๐
. The default is tpidr_el0. Bestie, please compile everything that needs to interoperate with the same value of this option, or you'll end up grabbing a different thread pointer from the wrong exception level ๐ญ.
-mstrict-align,-mno-strict-alignโ โจ These let you avoid, or allow, 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โ ๐ Omit or keep the frame pointer in leaf functions. Omitting it is the default behaviour, so that's the one you get unless you ask otherwise ๐.-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 areglobalfor a global canary, orsysregfor a canary in an appropriate system register.
With the sysreg choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset decide which system register is the base register for reading the canary, and what offset from that base to read from. There is no default register or offset here, because this is entirely for use within the Linux kernel ๐ง. Hands off unless you know what you're doing, periodt ๐ซถ.
-mtls-dialect=descโ ๐ง Uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables. This is the default, so you're already good โจ.-mtls-dialect=traditionalโ ๐ฐ๏ธ Uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables, instead of descriptors.-mtls-size=sizeโ ๐ Sets the bit size of immediate TLS offsets. The valid values are12,24,32, and48. This option needs binutils 2.26 or newer, so check your toolchain first ๐ง.-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ ๐ฉน Enables or disables the workaround for the ARM Cortex-A53 erratum number 835769. It 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 the ARM Cortex-A53 erratum number 843419. This one is applied at link time, so this flag only passes the corresponding flag to the linker ๐. It gets ignored too if an architecture or cpu is specified on the command line that doesn't need it.-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ โก Enables or disables the reciprocal square root approximation. This only does anything if-ffast-mathor-funsafe-math-optimizationsis used as well. When enabled, reciprocal square root results drop to about 16 bits of precision for single precision and 32 bits for double precision ๐.-mlow-precision-sqrt,-mno-low-precision-sqrtโ โก Enables or disables the square root approximation. Again, this only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces square root results to about 16 bits for single precision and 32 bits for double precision. If you enable it, it also implies-mlow-precision-recip-sqrt๐ฅ.-mlow-precision-div,-mno-low-precision-divโ โก Enables or disables the division approximation. Same deal: it only has an effect with-ffast-mathor-funsafe-math-optimizations. Division results get reduced to about 16 bits for single precision and 32 bits for double precision ๐.-mtrack-speculation,-mno-track-speculationโ ๐ต๏ธ Enables or disables generation of extra code to track speculative execution through conditional branches. That tracking state can then be used by the compiler when expanding calls to "__builtin_speculation_safe_copy", so it can produce 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 they can't, they fall back to the load/store-exclusive instructions that are present in the base ARMv8.0 ISA ๐ง .
This option only applies when you're 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 ๐.
-march=nameโ ๐๏ธ Specifies the name of the target architecture and, optionally, one or more feature modifiers. The form is-march=arch{+[no]feature}*.
๐ธ The Architecture Lineup ๐ธ
Here's the table of permissible arch values and the features each one turns on by default ๐. Architecture is in the middle, the defaults are on the end:
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.4-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 recognise the host's architecture, this option does nothing. When you give -march=native and no other -mcpu or -mtune, GCC will pick the host CPU as the CPU to tune for, and also select the architecture features from it. In other words, -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 feature is the one that gets used ๐.
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โ ๐ฏ Specifies the name of the target processor that GCC should tune the performance of the code for. The 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,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,cobalt-100,apple-m1,apple-m2,apple-m3, andnative. ๐
The values 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 tell GCC to tune for a big.LITTLE system ๐ฃ๐.
The value neoverse-512tvb tells GCC to tune for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle. In other words, it tells GCC to tune for Neoverse cores that can execute 4 128-bit Advanced SIMD arithmetic instructions a cycle, and that can execute an equivalent number of SVE arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE). This is more general than tuning for a specific core like Neoverse V1, but more specific than the default tuning described below ๐.
Additionally, on native AArch64 GNU/Linux systems, the value native tunes performance to the host system. If the compiler can't recognise the processor of the host system, this option does nothing ๐ฅ๏ธ.
Where 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, so don't even try ๐ โโ๏ธ.
-mcpu=nameโ ๐ง Specifies the name of the target processor, optionally suffixed by one or more feature modifiers. The form is-mcpu=cpu{+[no]feature}*, where the permissible values for cpu are the same as those available for-mtune. The permissible values for feature are documented in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. Conflicting feature modifiers? The right-most one wins ๐.
GCC uses name to determine what kind of instructions it can emit when generating assembly code (as if by -march), and to determine the target processor it should tune for performance (as if by -mtune). If this option is used alongside -march or -mtune, those options take precedence over the matching part of this option ๐.
Okay so the Neoverse thing is lowkey the most iconic flag ever ๐
-mcpu=neoverse-512tvb isn't one specific core, it's a whole group of Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle ๐ฆ Unless you override it with -march, it makes code that can run on a Neoverse V1 core, since V1 is the first Neoverse core with both of those properties ๐ฅ And unless you override it with -mtune, it tunes your code the same way -mtune=neoverse-512tvb would โจ
-moverride=stringโ Okay this one is for the tuning nerds ๐ค It 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 stay the same across releases, so don't get too attached ๐
This option is only intended to be useful when developing GCC. Like, it's for the people building the compiler, bestie ๐
-mverbose-cost-dumpโ Turns on verbose cost model dumping in the debug dump files ๐ง It's here so you can debug the compiler itself, so it's giving compiler-dev energy ๐-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ Turn PC-relative literal loads on or off ๐ธ With this on, literal pools get accessed with a single instruction and get emitted after each function. The catch is that it caps the maximum size of functions at 1MB ๐ญ It's on by default for-mcmodel=tiny.-msign-return-address=scopeโ Picks which functions get return address signing ๐ The valid values arenone(turns signing off),non-leaf(signs functions that aren't leaf functions), andall(signs every single function). The default isnone.
This option has been deprecated by -mbranch-protection, so maybe use that one instead ๐
-mbranch-protection=none|standard|pac-ret[+leaf+b-key]|bti|gcsโ Picks which branch protection features you want ๐noneis the default and turns off all branch protection types ๐ซถstandardturns on all the branch protection types. If a feature has extra tuning options,standardsets it to its standard level โจpac-ret[+leaf]turns on return address signing to its standard level, meaning it signs functions that save the return address to memory (non-leaf functions basically always do this) using the A-key. The optionalleafargument extends the signing to include leaf functions ๐- The optional
b-keyargument signs the functions with the B-key instead of the A-key ๐ btiturns on the branch target identification mechanism ๐ฏgcsturns on guarded control stack compatible code generation ๐ก๏ธ
-mharden-sls=optsโ Enables compiler hardening against straight line speculation (SLS) ๐ opts is a comma-separated list of the following options:retbrblr
-mharden-sls=all enables all SLS hardening, while -mharden-sls=none disables all of it ๐
-mearly-ra=scopeโ Decides when to turn on an early register allocation pass ๐ง This 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, like SME2's stridedLD1andST1โจallruns the pass on all functions ๐ซงstridedruns the pass on functions that have access to strided multi-register instructions ๐ฆnonedisables 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โ Enables the copy of the AArch64 load/store pair fusion pass that runs before register allocation ๐ It's on by default at-Oand above.-mlate-ldp-fusionโ Enables the copy of the AArch64 load/store pair fusion pass that runs after register allocation ๐ It's on by default at-Oand above too.-msve-vector-bits=bitsโ Sets how many bits are in an SVE vector register ๐ It only does anything when SVE is enabled.
GCC has two flavours of SVE code generation. There's "vector-length agnostic" output that works with any size of vector register, and "vector-length specific" output that lets GCC make assumptions about the vector length when that helps optimisation ๐ง The valid values for bits are scalable, 128, 256, 512, 1024, and 2048. scalable gives you vector-length agnostic output. Right now -msve-vector-bits=128 also makes vector-length agnostic output, but only for big-endian targets ๐ Every other value makes vector-length specific code. These values might change in future releases, so the only one you should count 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 ๐ธ
-Wexperimental-fmv-targetโ Warns you about using experimental Function Multi Versioning ๐จ The Arm C Language Extension spec for FMV is still beta and can change, so any FMV usage is caveated: future behaviour changes and incompatibility are likely ๐
โจ -march and -mcpu Feature Modifiers โจ
Feature modifiers used with -march and -mcpu can be any of the following, and each one also has an inverse you can write as nofeature ๐
crcโ Enables the CRC extension ๐ฅ It's on by default for-march=armv8.1-a.cryptoโ Enables the Crypto extension ๐ It also turns on Advanced SIMD and floating-point instructions.fpโ Enables floating-point instructions ๐ It's on by default for all possible values of-marchand-mcpu.simdโ Enables Advanced SIMD instructions ๐ฆ It also turns on floating-point instructions, and it's on by default for all possible values of-marchand-mcpu.sveโ Enables Scalable Vector Extension instructions ๐ It also turns on Advanced SIMD and floating-point instructions.lseโ Enables Large System Extension instructions ๐ง It's on by default for-march=armv8.1-a.rdmaโ Enables Round Double Multiply Accumulate instructions โจ It's on by default for-march=armv8.1-a.fp16โ Enables the FP16 extension ๐ It also turns on floating-point instructions.fp16fmlโ Enables the FP16fmlaextension ๐ It also enables the FP16 extensions and floating-point instructions. This one is enabled by default for-march=armv8.4-a. Using it with architectures before Armv8.2-A is not supported, so don't do it ๐ โโ๏ธrcpcโ Enables the RCpc extension ๐ This turns on the use of theLDAPRinstructions for load-acquire atomic semantics, and passes it along to the assembler so inline asm statements can use instructions from the RCpc extension ๐ซถdotprodโ Enables the Dot Product extension ๐ It also turns on Advanced SIMD instructions.aesโ Enables the Armv8-aaesandpmullcrypto extension ๐ It also turns on Advanced SIMD instructions.sha2โ Enables the Armv8-asha2crypto extension ๐ It also turns on Advanced SIMD instructions.sha3โ Enables thesha512andsha3crypto extension ๐ It also turns on Advanced SIMD instructions. Using it with architectures before Armv8.2-A is not supported ๐ซsm4โ Enables thesm3andsm4crypto extension ๐ It also turns on Advanced SIMD instructions. Using it with architectures before Armv8.2-A is not supported ๐ซprofileโ Enables the Statistical Profiling extension ๐ This only turns the extension on at the assembler level, and it does not affect code generation.rngโ Enables the Armv8.5-a Random Number instructions ๐ฒ This only turns the extension on at the assembler level, and it does not affect code generation.memtagโ Enables the Armv8.5-a Memory Tagging Extensions ๐ท๏ธ Using it with architectures before Armv8.5-A is not supported.sbโ Enables the Armv8-a Speculation Barrier instruction ๐ This only turns the extension on at the assembler level and does not affect code generation. It's enabled by default for-march=armv8.5-a.ssbsโ Enables the Armv8-a Speculative Store Bypass Safe instruction ๐ก๏ธ This only turns the extension on at the assembler level and does not affect code generation. It's enabled by default for-march=armv8.5-a.predresโ Enables the Armv8-a Execution and Data Prediction Restriction instructions ๐ This only turns the extension on at the assembler level and does not affect code generation. It's enabled by default for-march=armv8.5-a.sve2โ Enables the Armv8-a Scalable Vector Extension 2 ๐ It also turns on SVE instructions.sve2-bitpermโ Enables SVE2 bitperm instructions ๐งฉ It also turns on SVE2 instructions.sve2-sm4โ Enables SVE2sm4instructions ๐งฉ It also turns on SVE2 instructions.sve2-aesโ Enables SVE2aesinstructions ๐งฉ It also turns on SVE2 instructions.sve2-sha3โ Enables SVE2sha3instructions ๐งฉ It also turns on SVE2 instructions.sve2p1โ Enables SVE2.1 instructions ๐ It also turns on SVE2 instructions.tmeโ Enables the Transactional Memory Extension ๐งตi8mmโ Enables 8-bit Integer Matrix Multiply instructions ๐ข It also turns on Advanced SIMD and floating-point instructions. This one is enabled by default for-march=armv8.6-a. Using it with architectures before Armv8.2-A is not supported.f32mmโ Enables 32-bit Floating point Matrix Multiply instructions ๐งฎ It also turns on SVE instructions. Using it with architectures before Armv8.2-A is not supported.f64mmโ Enables 64-bit Floating point Matrix Multiply instructions ๐งฎ It also turns on SVE instructions. Using it with architectures before Armv8.2-A is not supported.bf16โ Enables brain half-precision floating-point instructions ๐ง It also turns on Advanced SIMD and floating-point instructions. This one is enabled by default for-march=armv8.6-a. Using it with architectures before Armv8.2-A is not supported.ls64โ Enables the 64-byte atomic load and store instructions for accelerators ๐mopsโ Enables the instructions that speed up memory operations like "memcpy", "memmove", "memset" ๐จ This one is enabled by default for-march=armv8.8-aflagmโ Enables the Flag Manipulation instructions Extension ๐ณ๏ธflagm2โ Enables the FlagM2 flag conversion instructions ๐pauthโ Enables the Pointer Authentication Extension ๐csscโ turns on the Common Short Sequence Compression instructions ๐๏ธโจsmeโ flips on the Scalable Matrix Extension ๐งฎ๐. Bestie, this one only works ifsve2is also enabled ๐sme-i16i64โ enables the FEAT_SME_I16I64 extension to SME ๐ธ. It also turns on SME instructions.sme-f64f64โ enables the FEAT_SME_F64F64 extension to SME ๐ฆ. It also turns on SME instructions.sme2โ enables the Scalable Matrix Extension 2 ๐. It also turns on SME instructions.sme-b16b16โ enables the FEAT_SME_B16B16 extension to SME ๐. It also turns on SME2 and SVE_B16B16 instructions.sme-f16f16โ enables the FEAT_SME_F16F16 extension to SME ๐ง. It also turns on SME2 instructions.sme2p1โ enables the Scalable Matrix Extension version 2.1 ๐ฅ. It also turns on SME2 instructions.fcmaโ enables the complex number SIMD extensions ๐jscvtโ enables thefjcvtzsJavaScript conversion instruction ๐frinttsโ enables floating-point round to integral value instructions โญwfxtโ enables thewfetandwfitinstructions ๐ซถxsโ enables the XS memory attribute extension ๐lse128โ enables the LSE128 128-bit atomic instructions extension ๐ . It also turns on LSE instructions.d128โ enables support for 128-bit system register read/write instructions โจ. It also turns on the LSE128 extension.gcsโ enables support for the Armv9.4-a Guarded Control Stack extension ๐ก๏ธ๐ธtheโ enables support for the Armv8.9-a/9.4-a translation hardening extension ๐rcpc2โ enables the RCpc2 extension ๐rcpc3โ enables the RCpc3 (Release Consistency) extension ๐ฆfp8โ enables the fp8 (8-bit floating point) extension ๐ซงfp8fmaโ enables the fp8 (8-bit floating point) multiply accumulate extension ๐ssve-fp8fmaโ enables the fp8 (8-bit floating point) multiply accumulate extension, but in streaming mode ๐fp8dot4โ enables the fp8 (8-bit floating point) to single-precision 4-way dot product extension ๐ฅssve-fp8dot4โ enables that same fp8 to single-precision 4-way dot product extension, but in streaming mode ๐fp8dot2โ enables the fp8 (8-bit floating point) to half-precision 2-way dot product extension ๐ฌssve-fp8dot2โ enables that same fp8 to half-precision 2-way dot product extension, but in streaming mode ๐faminmaxโ enables the Floating Point Absolute Maximum/Minimum extension ๐lutโ enables the Lookup Table extension ๐งพcpaโ enables the Checked Pointer Arithmetic instructions ๐ ๏ธsve-b16b16โ enables the SVE non-widening brain floating-point ("bf16") extension ๐ง . This only has an effect whensve2orsme2are also enabled.
Feature crypto implies aes, sha2, and simd, which implies fp. Conversely, nofp implies nosimd, which implies nocrypto, noaes and nosha2. Main character energy, but make it a chain ๐๐
๐ Adapteva Epiphany Options
These -m options are defined for Adapteva Epiphany ๐๐ธ:
-mhalf-reg-fileโ okay so this one stops the compiler from allocating any register in the ranger32...r63๐. That lets your code run on hardware variants that don't have those registers.-mprefer-short-insn-regsโ the compiler will prefer registers that allow short instruction generation โจ. Heads up, this can bump the instruction count, so overall code size might go down or up ๐คทโโ๏ธ.-mbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions ๐ . This cost is only a heuristic, so it's not guaranteed to give consistent results across releases.-mcmoveโ enables the generation of conditional moves ๐ฆ-mnops=numโ emitsnumNOPs before every other generated instruction ๐ญ-mno-soft-cmpsfโ for single-precision floating-point comparisons, the compiler emits anfsubinstruction and tests the flags ๐โโ๏ธ. This is faster than a software comparison, but it can get incorrect results with NaNs, or when two different small numbers are compared and their difference is calculated as zero ๐. The default is-msoft-cmpsf, which uses slower but IEEE-compliant software comparisons ๐ซถ.-mstack-offset=numโ sets the offset between the top of the stack and the stack pointer ๐. E.g., a value of8means the eight bytes in the rangesp+0...sp+7can be used by leaf functions without stack allocation. Values other than8or16are untested and unlikely to work ๐. Also, this option changes the ABI, so compiling a program with a different stack offset than the libraries were compiled with generally does not work.
Heads up, bestie: this option changes the ABI! If you just want to see whether a different stack offset gives better code, this is a fine place to experiment ๐งช. But to actually build working programs with a different stack offset, the recommended move is to configure the toolchain with the appropriate --with-stack-offset=num option ๐จ.
-mno-round-nearestโ makes 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 all calls might be beyond the offset range of theb/blinstructions ๐. So it loads the function address into a register before performing a (otherwise direct) call. This is the default ๐.-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.-msmall16โ assumes addresses can be loaded as 16-bit unsigned values ๐. This does not apply to function addresses where-mlong-callssemantics are in effect.-mfp-mode=modeโ sets the prevailing mode of the floating-point unit ๐๏ธ. This decides the floating-point mode that is provided and expected at function call and return time. Matching this to the mode you mostly need at function start can make your programs smaller and faster by avoiding unnecessary mode switches ๐.
mode can be set to one of the following values:
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 is handy for compiling libraries or other compilation units you want to drop into programs with different prevailing FPU modes. The convenience of a single object file can outweigh the extra mode-switching overhead compared with a more specific choice of prevailing FPU mode.truncateโ the mode used for floating-point calculations with truncating (round towards zero) rounding mode ๐ง. That includes conversion from floating point to integer.round-nearestโ the mode used for floating-point calculations with round-to-nearest-or-even rounding mode ๐ฏintโ the mode used to perform integer calculations in the FPU, e.g. integer multiply, or integer multiply-and-accumulate ๐ข
The default is -mfp-mode=caller ๐
-mno-split-lohi,-mno-postinc,-mno-postmodifyโ code generation tweaks that disable, 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.-mnovect-doubleโ changes the preferred SIMD mode toSImode๐. The default is-mvect-double, which usesDImodeas the preferred SIMD mode.-max-vect-align=numโ the maximum alignment for SIMD vector mode types ๐.nummay be4or8, and the default is8. Note that this is an ABI change, even though many 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โ splits vector moves into single word moves before reload ๐ช. In theory this can give better register allocation, but so far the reverse seems to be the general case ๐ญ.-m1reg-regโ specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster โก. Allowable values forregarer43andr63, which specify use of 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 ๐ฎ๐
-march=gpu,-mtune=gpuโ sets the architecture type or tuning forgpu๐ง . Supported values forgpuare:gfx900โ compiles for GCN5 Vega 10 devices (gfx900) ๐gfx902โ compiles for GCN5 Vegagfx902devices. (Experimental) ๐งชgfx904โ compiles for GCN5 Vegagfx904devices. (Experimental) ๐งชgfx906โ compiles for GCN5 Vega 20 devices (gfx906) ๐gfx908โ compiles for CDNA1 Instinct MI100 series devices (gfx908) ๐ฅgfx909โ compiles for GCN5 Vegagfx909devices. (Experimental) ๐งชgfx90aโ compiles for CDNA2 Instinct MI200 series devices (gfx90a) ๐gfx90cโ compiles for GCN5 Vega 7 devices (gfx90c) ๐gfx9-genericโ compiles generic code for Vega devices, executable on the following subset of GFX9 devices:gfx900,gfx902,gfx904,gfx906,gfx909andgfx90c. (Experimental) ๐ธgfx1030โ compiles for RDNA2gfx1030devices (GFX10 series) ๐ฆgfx1031โ compiles for RDNA2gfx1031devices (GFX10 series). (Experimental) ๐งชgfx1032โ compiles for RDNA2gfx1032devices (GFX10 series). (Experimental) ๐งชgfx1033โ compiles for RDNA2gfx1033devices (GFX10 series). (Experimental) ๐งชgfx1034โ compiles for RDNA2gfx1034devices (GFX10 series). (Experimental) ๐งชgfx1035โ compiles for RDNA2gfx1035devices (GFX10 series). (Experimental) ๐งชgfx1036โ compiles for RDNA2gfx1036devices (GFX10 series) ๐gfx10-3-genericโ compiles generic code for GFX10-3 devices, executable ongfx1030,gfx1031,gfx1032,gfx1033,gfx1034,gfx1035, andgfx1036. (Experimental) โจgfx1100โ compiles for RDNA3gfx1100devices (GFX11 series) ๐gfx1101โ compiles for RDNA3gfx1101devices (GFX11 series). (Experimental) ๐งชgfx1102โ compiles for RDNA3gfx1102devices (GFX11 series). (Experimental) ๐งชgfx1103โ compiles for RDNA3gfx1103devices (GFX11 series) ๐ซง
gfx1150โ okay so this one's for RDNA3 gfx1150 devices (GFX11 series) ๐ (Experimental) ๐งชgfx1151โ same energy, but for RDNA3 gfx1151 devices (GFX11 series) โจ (Experimental)gfx1152โ RDNA3 gfx1152 devices (GFX11 series) get the spotlight here ๐ฆ (Experimental)gfx1153โ and RDNA3 gfx1153 devices (GFX11 series) round out the squad ๐ธ (Experimental)gfx11-genericโ this is the generic one, bestie ๐ It compiles generic code for GFX11 devices, and that code can run on gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, and gfx1153. Very inclusive ๐ซถ (Experimental)-msram-ecc=on,-msram-ecc=off,-msram-ecc=anyโ these pick which SRAM-ECC mode your binaries are built for.onmeans the device has SRAM-ECC enabled,offmeans it's disabled, andanymeans either mode works ๐ Some devices let you flip this per-process, but the compiled code has to match the device mode, no exceptions ๐ The default isany, as long as the device actually supports it โจ-mstack-size=bytesโ this sets how many bytes of stack space each GPU thread (wave-front) gets ๐ง Be careful though, because there can be a lot of threads and not a ton of memory available ๐ญ The stack size can also affect run-time performance. The default is 32KB when you're using OpenACC or OpenMP, and 1MB otherwise ๐-mxnack=on,-mxnack=off,-mxnack=anyโ this one's about the XNACK feature ๐ Your binaries can be built for XNACK enabled, XNACK disabled, or either mode. Some devices always need XNACK, and some let the user decide. The compiled code has to match the device mode too. The default is-mxnack=anyon devices that support Unified Shared Memory, and-mxnack=noeverywhere else ๐
โจ ARC Options โจ
Okay bestie, this next batch controls the architecture variant your code gets compiled for ๐
-mbarrel-shifterโ generates instructions that the barrel shifter supports ๐ฅ This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ forces function calls to use thejli_sinstruction ๐ This option is only valid for the ARCv2 architecture.-mcpu=cpuโ this is the big one ๐ It sets the architecture type, register usage, and instruction scheduling parameters forcpu. There are also shortcut alias options around for backward compatibility and convenience ๐ซถ These are the supported values forcpu:arc600โ compiles for ARC600. Aliases:-mA6,-mARC600๐ธarc601โ compiles for ARC601. Alias:-mARC601๐ฆarc700โ compiles for ARC700. Aliases:-mA7,-mARC700. This is the default when you configure with--with-cpu=arc700โจarcemโ compiles for ARC EM ๐งarchsโ compiles for ARC HS ๐emโ compiles for an ARC EM CPU with no hardware extensions ๐em4โ compiles for an ARC EM4 CPU ๐em4_dmipsโ compiles for an ARC EM4 DMIPS CPU ๐em4_fpusโ compiles for an ARC EM4 DMIPS CPU with the single-precision floating-point extension ๐ฅem4_fpudaโ compiles for an ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions ๐hsโ compiles for an ARC HS CPU with no hardware extensions except the atomic instructions ๐hs34โ compiles for an ARC HS34 CPU โญhs38โ compiles for an ARC HS38 CPU ๐ฆhs38_linuxโ compiles for an ARC HS38 CPU with all hardware extensions turned on ๐hs4xโ compiles for an ARC HS4x CPU ๐ธhs4xdโ compiles for an ARC HS4xD CPU โจhs4x_rel31โ compiles for an ARC HS4x CPU release 3.10a ๐arc600_normโ compiles for an ARC 600 CPU with"norm"instructions enabled ๐ซถarc600_mul32x16โ compiles for an ARC 600 CPU with"norm"and 32x16-bit multiply instructions enabled ๐ฅarc600_mul64โ compiles for an ARC 600 CPU with"norm"and"mul64"-family instructions enabled ๐arc601_normโ compiles for an ARC 601 CPU with"norm"instructions enabled ๐arc601_mul32x16โ compiles for an ARC 601 CPU with"norm"and 32x16-bit multiply instructions enabled ๐arc601_mul64โ compiles for an ARC 601 CPU with"norm"and"mul64"-family instructions enabled ๐nps400โ compiles for ARC 700 on the NPS400 chip ๐งem_miniโ compiles for the ARC EM minimalist configuration, which features a reduced register set ๐
-mdpfp,-mdpfp-compactโ generates double-precision FPX instructions, tuned for the compact implementation ๐-mdpfp-fastโ generates double-precision FPX instructions, tuned for the fast implementation โก-mno-dpfp-lrsrโ disables"lr"and"sr"instructions from using FPX extension aux registers ๐ โโ๏ธ-meaโ generates extended arithmetic instructions ๐งฎ Right now only"divaw","adds","subs", and"sat16"are supported. This is only valid for-mcpu=ARC700๐ฅ-mno-mpyโ doesn't generate"mpy"-family instructions for ARC700 ๐ฅ This option is deprecated, so maybe don't build your whole vibe around it ๐-mmul32x16โ generates 32x16-bit multiply and multiply-accumulate instructions โจ-mmul64โ generates"mul64"and"mulu64"instructions ๐ฆ This is only valid for-mcpu=ARC600.-mnormโ generates"norm"instructions ๐ธ This is the default if-mcpu=ARC700is in effect.-mspfp,-mspfp-compactโ generates single-precision FPX instructions, tuned for the compact implementation ๐-mspfp-fastโ generates single-precision FPX instructions, tuned for the fast implementation ๐ฅ-msimdโ enables ARC SIMD instructions through target-specific builtins ๐ง This is only valid for-mcpu=ARC700.-msoft-floatโ this one is basically a no-op ๐ It's only here for compatibility purposes. 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 ๐ซถ-mswapโ generates"swap"instructions ๐-matomicโ enables the locked load/store conditional extension so it can power the atomic memory built-in functions ๐ This is not available for ARC 6xx or ARC EM cores ๐ โโ๏ธ-mdiv-remโ enables"div"and"rem"instructions for ARCv2 cores โ-mcode-densityโ enables code density instructions for ARC EM ๐ This option is on by default for ARC HS.-mll64โ enables double load/store operations for ARC HS cores ๐-mtp-regno=regnoโ specifies the thread pointer register number ๐งต-mmpy-option=multoโ this picks a multiplier design option for ARCv2 code ๐ข You can specify it with either a string or a numeric value formulto.wlh1is the default. These are the recognized values:0ornoneโ no multiplier available ๐ฅฒ1orwโ a 16x16 multiplier, fully pipelined ๐ธ These instructions get enabled:"mpyw"and"mpyuw".2orwlh1โ a 32x32 multiplier, fully pipelined (1 stage) โจ These instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s".3orwlh2โ a 32x32 multiplier, fully pipelined (2 stages) ๐ These instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s".4orwlh3โ two 16x16 multipliers, blocking, sequential ๐ฆ These instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s".5orwlh4โ one 16x16 multiplier, blocking, sequential ๐ง These instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s".6orwlh5โ one 32x4 multiplier, blocking, sequential ๐ These 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 ๐
Heads up: this option is only available for ARCv2 cores ๐
-mfpu=fpuโ turns on support for specific floating-point hardware extensions on ARCv2 cores ๐ These are the supported values forfpu:fpusโ enables single-precision floating-point hardware extensions ๐ธfpudโ enables double-precision floating-point hardware extensions ๐ The single-precision floating-point extension gets turned on too. Not available for ARC EM ๐ โโ๏ธfpudaโ enables double-precision floating-point hardware extensions using double-precision assist instructions โจ The single-precision floating-point extension is also enabled. This is only available for ARC EM ๐งfpuda_divโ enables 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 is only available for ARC EM ๐ฅfpuda_fmaโ enables 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 is only available for ARC EM ๐ฆfpuda_allโ enables double-precision floating-point hardware extensions using double-precision assist instructions ๐ All single-precision floating-point hardware extensions are also enabled. This is only available for ARC EM ๐fpus_divโ enables single-precision floating-point, square-root, and divide hardware extensions โfpud_divโ enables double-precision floating-point, square-root, and divide hardware extensions ๐ This option includesfpus_div. Not available for ARC EM ๐ โโ๏ธfpus_fmaโ enables single-precision floating-point and fused multiply and add hardware extensions ๐ธfpud_fmaโ enables double-precision floating-point and fused multiply and add hardware extensions ๐ This option includesfpus_fma. Not available for ARC EM ๐ โโ๏ธfpus_allโ enables all single-precision floating-point hardware extensions โจfpud_allโ enables all single- and double-precision floating-point hardware extensions ๐ Not available for ARC EM ๐ โโ๏ธ
Okay so this batch is all about interrupts and registers, and honestly the chip is doing a lot of babysitting here ๐ซถโจ
-mirq-ctrl-saved=register-range, blink, lp_count: this tells the processor which general-purpose registers to auto-save and restore on interrupt entry and exit ๐ Theregister-rangeis two registers joined by a dash. It always starts atr0, and the upper limit is thefpregister.blinkandlp_countare optional. Only valid for ARC EM and ARC HS cores ๐ฅ-mrgf-banked-regs=number: sets how many registers get copied into the second register bank when a fast interrupt hits ๐ฆ Fast interrupts are the ones at the highest priority level,P0. They only save thePCandSTATUS32registers so they can skip memory transactions on entry and exit, which is so efficient ๐ญ Use this when you're doing fast interrupts on an ARC V2 family processor. Permitted values are4,8,16, and32.-mlpc-width=width: specifies the width of the"lp_count"register ๐ง Valid widths are8,16,20,24,28, and32bits, and the default is fixed at32bits. If the width is less than32, the compiler won't transform your loops to use the zero-delay loop mechanism unless it knows the"lp_count"register can hold the loop counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for various other needs ๐ธ This option also defines the macro"__ARC_LPC_WIDTH__"with the value of width.-mrf16: tells the compiler to generate code for a 16-entry register file ๐ It also defines the"__ARC_RF16__"preprocessor macro.-mbranch-index: enables the use ofbiorbihinstructions to build jump tables ๐
๐ง Passed through to the assembler (and defining macros)
These options get handed down to the assembler, and they also define preprocessor macro symbols, so you can check for them in your code ๐
-mdsp-packa: enables the DSP Pack A extensions in the assembler ๐ It also sets the"__Xdsp_packa"preprocessor symbol. This option is deprecated ๐-mdvbf: enables the dual Viterbi butterfly extension in the assembler ๐ฆ It also sets"__Xdvbf". This option is deprecated.-mlock: enables the locked load/store conditional extension in the assembler ๐ It also sets"__Xlock".-mmac-d16: passed down to the assembler, and sets"__Xxmac_d16". This option is deprecated.-mmac-24: passed down to the assembler, and sets"__Xxmac_24". This option is deprecated.-mrtsc: enables the 64-bit time-stamp counter extension instruction in the assembler โฑ๏ธ It also sets"__Xrtsc". This option is deprecated.-mswape: enables the swap byte ordering extension instruction in the assembler ๐ It also sets"__Xswape".-mtelephony: enables dual- and single-operand instructions for telephony in the assembler ๐ It also sets"__Xtelephony". This option is deprecated.-mxy: enables the XY memory extension in the assembler โจ It also sets"__Xxy".
๐ Controlling how assembly gets annotated
The following options control how the assembly code is annotated ๐
-misize: annotates assembler instructions with estimated addresses ๐-mannotate-align: does nothing, it's just kept around for backward compatibility ๐ซ
๐ Passed through to the linker
-marclinux: passed through to the linker to specify use of the"arclinux"emulation ๐ธ This one is turned on by default in toolchains built for the"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is not requested.-marclinux_prof: passed through to the linker to specify use of the"arclinux_prof"emulation ๐ This one is turned on by default in toolchains built for the"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is requested.
๐ Controlling the semantics of generated code
-mlong-calls: generates calls as register indirect calls, which gives you access to the full 32-bit address range ๐-mmedium-calls: doesn't use anything less than a 25-bit addressing range for calls ๐ซ That's the offset available for an unconditional branch-and-link instruction. Conditional execution of function calls gets suppressed so the 25-bit range can be used, instead of the 21-bit range you'd get with conditional branch-and-link. This is the default for toolchains built for the"arc-linux-uclibc"and"arceb-linux-uclibc"targets.-G num: puts definitions of externally-visible data in a small data section, as long as that data is no bigger thannumbytes ๐งธ The default value ofnumis4for any ARC configuration, or8when you have double load/store operations.-mno-sdata: stops sdata references from being generated ๐ โโ๏ธ This is the default for toolchains built for the"arc-linux-uclibc"and"arceb-linux-uclibc"targets.-mvolatile-cache: uses ordinarily cached memory accesses for volatile references ๐พ This is the default.-mno-volatile-cache: enables cache bypass for volatile references ๐โโ๏ธ
๐ Fine-tuning code generation
The following options fine-tune code generation, so they're kind of the glam squad ๐
-malign-call: does nothing, preserved for backward compatibility ๐ซถ-mauto-modify-reg: enables the use of pre/post modify with register displacement ๐ช-mbbit-peephole: does nothing, preserved for backward compatibility ๐ซ-mno-brcc: disables a target-specific pass inarc_reorgthat generates compare-and-branch ("brcc") instructions ๐ It has no effect on the generation of these instructions when they're driven by the combiner pass.-mcase-vector-pcrel: uses PC-relative switch case tables to enable case table shortening โ๏ธ This is the default for-Os.-mcompact-casesi: enables the compact"casesi"pattern ๐๏ธ This is the default for-Os, and it's only available for ARCv1 cores. This option is deprecated ๐-mno-cond-exec: disables the ARCompact-specific pass that generates conditional execution instructions ๐ โโ๏ธ
Okay real talk about why this one exists ๐ง Delay slot scheduling and the interactions between operand numbers, literal sizes, instruction lengths, and conditional execution support mean the target-independent conditional execution pass is often lacking. 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, at the cost of extra compilation time, which is why there's an option to switch it off. If you're having a problem with call instructions exceeding their allowable offset range because they got conditionalized, you should consider using -mmedium-calls instead ๐ญ
-mearly-cbranchsi: enables pre-reload use of the"cbranchsi"pattern โช-mexpand-adddi: expands"adddi3"and"subdi3"at RTL generation time into"add.f","adc"etc. ๐งฎ This option is deprecated.-mindexed-loads: enables the use of indexed loads ๐ฆ Heads up, this can be problematic, because some optimizers then assume indexed stores exist, and they don't in this case.-mlra: does nothing, preserved for backward compatibility ๐ซ-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 optimizing for size (using-Os), prologues and epilogues that have to save or restore a large number of registers often get shortened by calling a special function in libgcc. That's called a millicode call ๐งฉ Since these calls can cause performance issues, and/or linking issues when you link in a nonstandard way, 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.-mmixed-code: does nothing, preserved for backward compatibility ๐ซ-mq-class: this option is deprecated ๐ It enablesqinstruction alternatives. This is the default for-Os.-mRcq: does nothing, preserved for backward compatibility ๐ซ-mRcw: does nothing, preserved for backward compatibility ๐ซ-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 are used opportunistically โจ2: in addition, alignment of loops and of code after barriers gets dropped ๐3: in addition, optional data alignment gets dropped, and theOsoption is enabled ๐ฅ
This defaults to 3 when -Os is in effect. Otherwise, the behavior when this isn't set is equivalent to level 1.
-mtune=cpu: sets instruction scheduling parameters forcpu, overriding anything implied by-mcpu=๐๏ธ
Supported values for cpu are:
ARC600: tunes for the ARC600 CPU ๐งARC601: tunes for the ARC601 CPU ๐งARC700: tunes for the ARC700 CPU with the standard multiplier block ๐ชARC700-xmac: tunes for the ARC700 CPU with the XMAC block โกARC725D: tunes for the ARC725D CPU ๐ทARC750D: tunes for the ARC750D CPU ๐ทcore3: tunes for the 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 ๐งฎ-munalign-prob-threshold=probability: does nothing, preserved for backward compatibility ๐ซ
๐ชฆ Deprecated, but still here for backward compatibility
The following options are kept around for backward compatibility, but they're now deprecated and will be removed in a future release. So don't build your whole life around them ๐ฅน
-margonaut: obsolete FPX ๐ฐ๏ธ-mbig-endian,-EB: compiles code for big-endian targets ๐ Using these options is now deprecated. Big-endian code is supported by configuring GCC to build the"arceb-elf32"and"arceb-linux-uclibc"targets, and for those, big endian is the default ๐
Okay so bestie, we're picking up right where the ARC deprecated list leaves off ๐ โจ
-mlittle-endian,-ELโ Okay so these tell GCC to build for little-endian targets ๐ซถ but they're now deprecated ๐ญ Little-endian is already handled by configuring GCC to build thearc-elf32andarc-linux-uclibctargets, and little endian is the default for those ๐ธ-mbarrel_shifterโ Replaced by-mbarrel-shifter๐-mdpfp_compactโ Replaced by-mdpfp-compact๐-mdpfp_fastโ Replaced by-mdpfp-fast๐-mdsp_packaโ Replaced by-mdsp-packa๐-mEAโ Replaced by-mea๐-mmac_24โ Replaced by-mmac-24๐-mmac_d16โ Replaced by-mmac-d16๐-mspfp_compactโ Replaced by-mspfp-compact๐-mspfp_fastโ Replaced by-mspfp-fast๐-mtune=cpuโ The valuesarc600,arc601,arc700andarc700-xmacforcpuare replaced byARC600,ARC601,ARC700andARC700-xmacrespectively ๐-multcost=numโ Replaced by-mmultcost๐
๐ ARM Options ๐
These -m options are defined for the ARM port, so if you're on ARM, this is your moment ๐ฆ
-mabi=nameโ Generate code for the specified ABI ๐ The permissible values areapcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt-mapcs-frameโ Generate a stack frame that follows the ARM Procedure Call Standard for all functions ๐ง even when it isn't strictly needed for the code to run correctly. If you pair this with-fomit-frame-pointer, stack frames won't be generated for leaf functions. The default is-mno-apcs-frame, and this option is deprecated ๐-mapcsโ A synonym for-mapcs-frame, and it's also deprecated ๐-mthumb-interworkโ Generate 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, because slightly larger code gets generated when-mthumb-interworkis specified. In AAPCS configurations this option is meaningless ๐-mno-sched-prologโ Stops the reordering of instructions in the function prologue, and also stops those instructions from being merged with the instructions in the function's body โจ This means every function starts with a recognizable set of instructions (or one from a small set of different prologues), so you can use that info to find where functions start inside an executable chunk of code ๐ The default is-msched-prolog-mfloat-abi=nameโ Picks which floating-point ABI to use ๐ The permissible values aresoft,softfpandhardsoftmakes GCC generate output with library calls for floating-point operations ๐softfplets the code use hardware floating-point instructions, but still uses the soft-float calling conventions ๐ซถhardallows floating-point instructions and uses FPU-specific calling conventions โก
The default depends on the specific target configuration. Heads up though, bestie: the hard-float and soft-float ABIs are not link-compatible ๐ญ You have to compile your entire program with the same ABI and link it with a compatible set of libraries ๐
-mgeneral-regs-onlyโ Generate code that only uses the general-purpose registers ๐ธ This stops the compiler from using floating-point and Advanced SIMD registers, but it won't put any restrictions on the assembler ๐-mlittle-endianโ Generate code for a processor running in little-endian mode ๐ This is the default for all standard configurations ๐-mbig-endianโ Generate code for a processor running in big-endian mode ๐งฟ The default is to compile for a little-endian processor, so you have to ask for this one explicitly ๐-mbe8,-mbe32โ When linking a big-endian image, pick between the BE8 and BE32 formats ๐ These have no effect on little-endian images and get ignored there ๐ The default depends on the selected target architecture: for ARMv6 and later it's BE8, and for older architectures it's BE32. ARM has deprecated the BE32 format ๐
โจ -march=name[+extension...] โจ
This picks the name of the target ARM architecture ๐ฆ GCC uses this name to figure out what kinds of instructions it's allowed to emit when generating assembly code. You can use this option together with -mcpu=, or instead of it ๐
The 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 ๐
Also, these architectures don't support the Thumb execution state, so they're recognized but support is deprecated ๐ญ That's just armv4 ๐
Lots of the architectures support extensions, which you add by appending +extension to the architecture name ๐ง Extension options are processed in order and their capabilities stack up. An extension will also turn on any base extensions it depends on. For example, +crypto will always enable +simd ๐ฅ The exception to the stacking is extensions prefixed with +no...: those disable the option they name, plus any other extensions that depend on it โ
For example, -march=armv7-a+simd+nofp+vfpv4 is equivalent to writing -march=armv7-a+vfpv4, since +simd gets totally disabled by the +nofp that comes after it ๐
Most extension names are generic, but what they actually do depends on the architecture you apply them to ๐ฆ For example, +simd works on both armv7-a and armv8-a, but it turns on the original ARMv7-A Advanced SIMD (Neon) extensions for armv7-a, and the ARMv8-A variant for armv8-a ๐ซถ
Here's the table of supported extensions for each architecture, in list form bestie ๐ Architectures not mentioned don't support any extensions.
๐ธ armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk ๐ธ
+fpโ The VFPv2 floating-point instructions ๐ The extension+vfpv2can be used as an alias for this one+nofpโ Disables the floating-point instructions ๐ โโ๏ธ
๐ง 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 ๐ The extension+vfpv3-d16can be used as an alias for this one. Heads up: floating-point isn't supported by the base ARMv7-M architecture, but it is compatible with both ARMv7-A and ARMv7-R ๐+nofpโ Disables the floating-point instructions ๐ โโ๏ธ
๐ armv7-a ๐
+mpโ The multiprocessing extension ๐ซถ+secโ The security extension ๐+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers ๐ The extension+vfpv3-d16can be used as an alias for this one+simdโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions ๐ฅ The extensions+neonand+neon-vfpv3can be used as aliases for this one+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers ๐+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations ๐+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and 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, with 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 (this does not disable floating point) ๐ โโ๏ธ+nofpโ Disables the floating-point and Advanced SIMD instructions ๐
๐ฆ armv7ve ๐ฆ
The extended version of the ARMv7-A architecture, with support for virtualization ๐งฟ
+fpโ The VFPv4 floating-point instructions, with 16 double-precision registers ๐ The extension+vfpv4-d16can be used as an alias for this one+simdโ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions ๐ฅ The extension+neon-vfpv4can be used as 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 and the half-precision floating-point conversion operations ๐+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and 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 ๐ The extension+neon-vfpv3can be used as an alias for this one+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations โจ+nosimdโ okay so this one switches off the Advanced SIMD instructions ๐ โโ๏ธ but floating point stays on, so it's not a total wipeout ๐ (it does not disable floating point).+nofpโ bye bye to the floating-point and Advanced SIMD instructions ๐ both get disabled together ๐ญ
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, no cap ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions all at once ๐+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 one also turns on the Advanced SIMD and floating-point instructions, so it's giving bundle deal ๐+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 and armv8.3-a
+fp16โ the half-precision floating-point data processing instructions ๐ธ this also enables the Advanced SIMD and floating-point instructions too โจ+fp16fmlโ the half-precision floating-point fmla extension ๐ฆ this also enables 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 enables the Advanced SIMD and floating-point instructions ๐+dotprodโ enables the Dot Product extension ๐ง this also enables 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 enables Advanced SIMD and floating-point instructions ๐ฅ+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions ๐ฅ
armv8.4-a
+fp16โ the half-precision floating-point data processing instructions ๐ธ this also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions, as well as 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 enables Advanced SIMD and floating-point instructions ๐ฅ+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions ๐ฅ
armv8.5-a
+fp16โ the half-precision floating-point data processing instructions ๐ธ this also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions, as well as 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 enables Advanced SIMD and floating-point instructions ๐ฅ+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions ๐ฅ
armv8.6-a
+fp16โ the half-precision floating-point data processing instructions ๐ธ this also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions, as well as 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 enables Advanced SIMD and floating-point instructions ๐ฅ+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions ๐ฅ
armv7-r
+fp.spโ the single-precision VFPv3 floating-point instructions ๐ the extension+vfpv3xdcan be used as an alias for this extension ๐ฆ+fpโ the VFPv3 floating-point instructions with 16 double-precision registers ๐ the extension+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โ disables the floating-point extension ๐ โโ๏ธ+idivโ the ARM-state integer division instructions โ+noidivโ disables 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โ disables 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โ disables the floating-point extension ๐ โโ๏ธ+cdecp0,+cdecp1, ... ,+cdecp7โ enables the Custom Datapath Extension (CDE) on selected coprocessors, according to the numbers given in the options in the range 0 to 7 ๐งฉ+pacbtiโ enables the Pointer Authentication and Branch Target Identification Extension ๐
armv8-m.main
+dspโ the DSP instructions โญ+nodspโ disables the DSP extension ๐ โโ๏ธ+fpโ the single-precision floating-point instructions ๐+fp.dpโ the single- and double-precision floating-point instructions ๐ฅ+nofpโ disables the floating-point extension ๐ โโ๏ธ+cdecp0,+cdecp1, ... ,+cdecp7โ enables 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โ disables the cryptographic instructions ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐
Okay, two special flags you need to know about ๐ซถ
-march=native tells the compiler to auto-detect the architecture of the build computer ๐ but right now this only works on GNU/Linux, and not every architecture gets recognized ๐ฌ if the auto-detect doesn't work out, the option just has no effect ๐
-march=unset tells the compiler to ignore any -march=... options that showed up earlier on the command line, and to behave like the option was never passed at all โจ this is super useful for avoiding warnings about conflicting CPU and architecture options when the two produce different architecture specifications ๐
-mtune=nameโ okay bestie, this one tells GCC which target ARM processor to tune your code's performance for โจ Some ARM chips run noticeably faster when you use it ๐ The permissible names arearm7tdmi,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-mc1andxgene1๐
Also, this option can tune for a big.LITTLE system ๐ The permissible big.LITTLE 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 and cortex-a76.cortex-a55 ๐ซถ
-mtune=generic-arch is giving "blend of everything" energy ๐ธ It tells GCC to tune performance for a mix of processors within the architecture arch. The goal is code that runs well on the most popular chips right now, balancing the optimizations that help some CPUs in the range while dodging the performance pitfalls of others. The effects of this may change in future GCC versions as CPU models come and go, so don't be shocked if it shifts ๐ฆ
-mtune accepts the same extension options as -mcpu, but the extensions don't change how the generated code gets tuned ๐ง
-mtune=native makes the compiler auto-detect the CPU of the build computer ๐ Right now this only works on GNU/Linux, and not every architecture is recognized. If the auto-detect doesn't work out, the option has no effect ๐
-mcpu=name[+extension...]โ this names the target ARM processor, and GCC uses it to figure out two things: the target ARM architecture (as if you'd passed-march) and the processor type to tune for (as if you'd passed-mtune) โจ If you use this alongside-marchor-mtune, those two take precedence over the matching part of this option ๐
Lowkey, a lot of the supported CPUs come with optional architectural extensions ๐ Those are usually enabled by default. If some implementations don't have an extension, you can use the extension syntax to switch off the ones that are missing ๐ซ Floating-point and Advanced SIMD (Neon) instructions also depend on -mfloat-abi and -mfpu. FP and SIMD instructions only get used if -mfloat-abi isn't set to soft, and any -mfpu setting other than auto will override the available floating-point and SIMD extension instructions ๐ญ
For example, cortex-a9 shows up in three main configurations: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD ๐ฅ By default everything is enabled, but you can use +nosimd to turn off just the SIMD, or +nofp to turn off both SIMD and floating-point ๐
The permissible names for this option are the same as the ones for -mtune ๐
These extension options are shared by the listed CPUs:
+nodsp: switches off the DSP instructions oncortex-m33,cortex-m35p,cortex-m52,cortex-m55andcortex-m85. It also switches off the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85๐+nopacbti: switches off the Pointer Authentication and Branch Target Identification Extension oncortex-m52andcortex-m85๐+nomve: switches off the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85๐+nomve.fp: switches off just the M-Profile Vector Extension (MVE) single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85โจ+cdecp0,+cdecp1, ... ,+cdecp7: enables the Custom Datapath Extension (CDE) on selected coprocessors, based on 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. 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, it disables the floating-point and SIMD instructions ๐+nofp.dp: disables the double-precision component of the floating-point instructions oncortex-r5,cortex-r7,cortex-r8,cortex-r52,cortex-r52plusandcortex-m7๐ธ+nosimd: disables the SIMD (but not floating-point) instructions ongeneric-armv7-a,cortex-a5,cortex-a7andcortex-a9๐ฆ+crypto: enables the cryptographic instructions oncortex-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-a53andcortex-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 and neon-vfpv4. They mean the same thing as the extensions to -march=armv7-a ๐
-mcpu=generic-arch is also allowed, and it's equivalent to -march=arch -mtune=generic-arch. Check -mtune for more info ๐ซถ
-mcpu=native makes the compiler auto-detect the CPU of the build computer ๐
Right now this only works on GNU/Linux, and not every architecture is recognized. If the auto-detect fails, the option has no effect ๐
-mcpu=unset tells the compiler to ignore any -mcpu=... options that appeared earlier on the command line, and to act like that option was never passed ๐งน This is handy for avoiding warnings about conflicting CPU and architecture options when the two produce different architecture specifications โจ
-mfpu=nameโ this specifies what floating-point hardware (or hardware emulation) is available on the target ๐ The permissible names areauto,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-armv8andcrypto-neon-fp-armv8. Note thatneonis an alias forneon-vfpv3, andvfpis an alias forvfpv2๐
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 โจ
If the floating-point hardware you picked includes the NEON extension (e.g. -mfpu=neon), heads up: floating-point operations aren't generated by GCC's auto-vectorization pass unless -funsafe-math-optimizations is also specified ๐ญ That's because NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic (denormal values are treated as zero, in particular), so using NEON instructions may lead to a loss of precision ๐
You can also set the fpu name at function level using the target("fpu=") function attributes or pragmas ๐ฆ
-mfp16-format=nameโ specifies the format of the"__fp16"half-precision floating-point type ๐ The permissible names arenone,ieeeandalternative. The default isnone, and in that case the"__fp16"type isn't defined ๐-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 ๐ Permissible values are8,32and64. The default value varies for different toolchains. For the COFF targeted toolchain, the default is8. A value of64is only allowed if the underlying ABI supports it ๐
Going bigger can produce faster, more efficient code, but it can also increase the size of your program โจ Different values are potentially incompatible. Code compiled with one value can't necessarily expect to work with code or libraries compiled with another value, if they exchange information using structures or unions ๐ฌ
โ ๏ธ This option is deprecated. Don't build new stuff around it, bestie ๐
-mabort-on-noreturnโ generates a call to the function"abort"at the end of a"noreturn"function ๐ธ It's executed if the function tries to return ๐ณ-mlong-callsand-mno-long-callsโ tells the compiler to perform 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 lies outside the 64-megabyte addressing range of the offset-based version of the subroutine call instruction ๐
Even if this switch is enabled, not every function call gets turned into a long call ๐ The vibe check goes like this: static functions, functions with the "short_call" attribute, functions inside a #pragma no_long_calls scope, and functions whose definitions were already compiled in the current compilation unit all stay short. The exceptions are always long calls, no cap: weak function definitions, functions with the "long_call" or "section" attribute, and functions inside a #pragma long_calls scope ๐
This feature is not enabled by default ๐ -mno-long-calls brings back the default behavior, and so does wrapping the function calls in a #pragma long_calls_off directive. Also, these switches do nothing for how the compiler handles function calls through function pointers, so don't expect them to โจ
-msingle-pic-baseโ okay so this one treats the register used for PIC addressing as read-only ๐ Instead of loading it in the prologue for every function, the runtime system is the one responsible for setting it to an appropriate value before execution begins ๐ฆ-mpic-register=regโ this lets you pick the register used for PIC addressing ๐ For the standard PIC base case, the default is any suitable register the compiler decides on. For the single PIC base case, the default isR9if the target is EABI based or stack-checking is enabled, and otherwise it'sR10๐ธ-mpic-data-is-text-relativeโ assume the displacement between the text and data segments is fixed at static link time ๐ง This lets you use PC-relative addressing to access data you know is in the data segment. For non-VxWorks RTP targets this is enabled by default, and if you disable it on those targets,-msingle-pic-basegets enabled by default instead ๐ซถ-mpoke-function-nameโ this one writes the name of each function into the text section, right before the function prologue โจ The generated code looks kind of 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 you're doing a stack backtrace, the code can check the pc value stored at fp + 0 ๐ If the trace function then looks at location pc - 12 and the top 8 bits are set, we know there's a function name embedded right before that location, with length ((pc[-3]) & 0xff000000) ๐ญ
-mthumb,-marmโ pick between generating code that runs in ARM state or Thumb state ๐ For most configurations the default is ARM state, but you can change that by configuring GCC with the--with-mode=stateconfigure option ๐ You can also override ARM or Thumb mode for each function with thetarget("thumb")andtarget("arm")function attributes or pragmas, which is honestly so iconic ๐-mflip-thumbโ switches ARM and Thumb modes on alternating functions ๐ This one exists purely for regression testing of mixed Thumb/ARM code generation, so please don't use it to compile your actual code ๐-mtpcs-frameโ generates a stack frame that follows 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โ same energy, but this time it generates a Thumb Procedure Call Standard compliant stack frame for all leaf functions ๐ธ (Again, a leaf function is one that doesn't call any other functions.) The default is-mno-apcs-leaf-frame๐-mcallee-super-interworkingโ gives every externally visible function in the file being compiled an ARM instruction set header ๐ง That header switches to Thumb mode before running the rest of the function, so these functions can be called from non-interworking code. This option is not valid in AAPCS configurations, because interworking is already enabled by default there ๐-mcaller-super-interworkingโ lets calls through function pointers (including virtual functions) run correctly, no matter whether the target code was compiled for interworking or not ๐ซถ Heads up, there's a small overhead when executing a function pointer if you turn this on. It's also not valid in AAPCS configurations, since interworking is already enabled by default there ๐-mtp=nameโ specifies the access model for the thread local storage pointer ๐ฅ Thesoftmodel generates calls to__aeabi_read_tp. The other accepted models aretpidrurw,tpidruro, andtpidrprw, which fetch the thread pointer straight from the matching system register (supported from the arm6k architecture and later) โจ Those system registers get accessed through the CP15 co-processor interface, and the argumentcp15is also accepted as a convenience alias oftpidruro๐ The argumentautouses the best available method for the selected processor, and that's also the default setting ๐-mtls-dialect=dialectโ picks the dialect used for accessing thread local storage ๐ There are two:gnuandgnu2. Thegnudialect selects the original GNU scheme for supporting local and global dynamic TLS models. Thegnu2dialect selects the GNU descriptor scheme, which performs better for shared libraries ๐ The GNU descriptor scheme is compatible with the original scheme, but it does need new assembler, linker, and library support. Initial and local exec TLS models aren't affected by this option and always use the original scheme ๐ซถ-mword-relocationsโ only generates absolute relocations on word-sized values (i.e.R_ARM_ABS32) ๐ This is enabled by default on targets (uClinux, SymbianOS) where the runtime loader imposes this restriction, and whenever-fpicor-fPICis specified. This option conflicts with-mslow-flash-data๐-mfix-cortex-m3-ldrdโ some Cortex-M3 cores can cause data corruption whenldrdinstructions with overlapping destination and base registers get used ๐ญ This option avoids generating those instructions. It's enabled by default when-mcpu=cortex-m3is specified ๐-mfix-cortex-a57-aes-1742098,-mno-fix-cortex-a57-aes-1742098,-mfix-cortex-a72-aes-1655431,-mno-fix-cortex-a72-aes-1655431โ these enable (or disable) the mitigation for an erratum on Cortex-A57 and Cortex-A72 that affects the AES cryptographic instructions ๐ This is enabled by default when either-mcpu=cortex-a57or-mcpu=cortex-a72is specified ๐ธ-munaligned-access,-mno-unaligned-accessโ enables (or disables) reading and writing 16- and 32-bit values from addresses that aren't 16- or 32-bit aligned ๐ฆ By default, unaligned access is disabled for all pre-ARMv6, all ARMv6-M, and ARMv8-M Baseline architectures, and enabled for every other architecture. 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's setting โจ If unaligned access is enabled, the preprocessor symbol __ARM_FEATURE_UNALIGNED is also defined ๐ง
-mneon-for-64bitsโ this one is deprecated and has no effect ๐ Bye bye ๐-mslow-flash-dataโ assumes loading data from flash is slower than fetching instructions, so literal loads get minimized for better performance ๐ข This option 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 ๐ The default is currently off, which implies divided syntax. This option has no impact on Thumb2, but that may change in future releases of GCC. Divided syntax should be considered deprecated, so be careful with it ๐ซถ-mrestrict-itโ restricts generation of IT blocks so they conform to the rules of ARMv8-A ๐ฅ IT blocks can only contain a single 16-bit instruction from a select set of instructions. This option is on by default for ARMv8-A Thumb mode ๐-mprint-tune-infoโ prints CPU tuning information as a comment in the assembler file ๐ This is only used for regression testing of the compiler and isn't meant for ordinary code compiling. It's disabled by default ๐-mverbose-cost-dumpโ enables verbose cost model dumping in the debug dump files ๐ This one's provided for debugging the compiler, so it's a niche pick ๐ง-mpure-codeโ doesn't allow constant data to be placed in code sections ๐ Also, when compiling for the ELF object format, it gives all text sections the ELF processor-specific section attribute"SHF_ARM_PURECODE". This option is only available when generating non-PIC code for M-profile targets ๐-mcmseโ generates secure code as per the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification", which you can find at<https://developer.arm.com/documentation/ecm0359818/latest/>๐ก๏ธโจ-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 option 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-35465to disable the mitigation ๐ซถ-mstack-protector-guard=guard,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard๐ก๏ธ Supported locations areglobalfor a global canary, ortlsfor a canary accessible via the TLS register. The option-mstack-protector-guard-offset=is for use with-fstack-protector-guard=tls, and it's not for use in user-land code ๐ โโ๏ธ๐
-mfdpic -mno-fdpic
Okay so -mfdpic switches on 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 you haven't given any PIC/PIE-related options. On other targets it only turns on the FDPIC-specific code generation features, so you'll need to pass the PIC/PIE options yourself as needed ๐
.
Static linking is NOT supported with FDPIC ๐. The program still involves the dynamic linker when it self-relocates. If you're okay with that behavior anyway, use-staticand-Wl,-dynamic-linkeroptions.
The opposite, -mno-fdpic, is useful (and required) when you're building the Linux kernel with the same arm-*-uclinuxfdpiceabi toolchain you use for your userland programs ๐ธ.
-mbranch-protection=none|standard|pac-ret[+leaf][+bti]|bti[+pac-ret[+leaf]]
Enable branch protection features, but only on armv8.1-m.main โจ. Here's the breakdown:
noneโ no branch protection or return address signing, just plain code ๐.standard[+leaf]โ all branch protection features turned on at their standard level ๐ฅ.pac-ret[+leaf]โ return address signing at its standard level, which means signing every function that saves the return address to memory ๐.leafโ when return address signing is on, this also signs leaf functions, even the ones that never write the return address to memory ๐.+btiโ adds landing-pad instructions at the permitted targets of indirect branch instructions ๐ง.
If the +pacbti architecture extension isn't enabled, all branch protection and return address signing operations are restricted to 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 still kick in at run time on processors that support the PACBTI extension ๐.
Branch target enforcement with BTI can only be enabled at runtime if all the code in the application was compiled with at least -mbranch-protection=bti ๐.
Anything other than none is only supported on armv8-m.main or later ๐.
The default is to generate code without branch protection or return address signing ๐.
โจ AVR Options โจ
These options are defined for AVR implementations ๐ง.
-mmcu=mcu
Specify the AVR instruction set architecture (ISA) or device type. The default is avr2 ๐.
Here are the AVR devices and ISAs that are supported. Heads up bestie: complete device support needs a startup code file crtmcu.o, a device header avr/io*.h, a device library libmcu.a, and a device-specs file specs-mcu. Only the last one is provided by the compiler, and only for the mcus listed 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) that the hardware manufacturer hands out ๐ฆ. For the spec files, check out https://gcc.gnu.org/wiki/avr-gcc#spec-files โจ.
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 theMOVWinstruction ๐ฆ. 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 theMOVWinstruction ๐ซถ. 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 ๐. This is the big one, so buckle up ๐ญ. 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 ๐ฅ. mcu =atmega128,atmega128a,atmega128rfa1,atmega128rfr2,atmega1280,atmega1281,atmega1284,atmega1284p,atmega1284rfr2,at90can128,at90usb1286,at90usb1287.avr6โ "Enhanced" devices with a 3-byte PC, so more than 128 KiB of program memory ๐. mcu =atmega256rfr2,atmega2560,atmega2561,atmega2564rfr2.avrxmega2โ "XMEGA" devices with more than 8 KiB and up to 64 KiB of program memory ๐. mcu =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 ๐ง. mcu =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,avr32da28,avr32da28s,avr32da32,avr32da32s,avr32da48,avr32da48s,avr32db28,avr32db32,avr32db48,avr32dd14,avr32dd20,avr32dd28,avr32dd32,avr32du14,avr32du20,avr32du28,avr32du32,avr32ea28,avr32ea32,avr32ea48,avr32sd20,avr32sd28,avr32sd32.avrxmega4โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory ๐. mcu =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 =atxmega64a1,atxmega64a1u.avrxmega6โ "XMEGA" devices with more than 128 KiB of program memory ๐ฆ. mcu =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 =atxmega128a1,atxmega128a1u,atxmega128a4u.
okay bestie, the tiny chips get their own little squad ๐ธ
avrtinyโ the "Reduced Tiny" crew ๐ง These tiny core devices only have 16 general purpose registers and 512 B up to 4 KiB of program memory. mcu ="attiny4","attiny5","attiny9","attiny10","attiny102","attiny104","attiny20","attiny40".avr1โ this ISA is baked into the minimal AVR core, and it's only supported for the assembler ๐ mcu ="attiny11","attiny12","attiny15","attiny28","at90s1200".
-mabsdataโ okay so this one assumes all data in static storage can be reached withLDS/STSinstructions ๐ It only does anything on reduced Tiny devices like ATtiny40. Also see the "absdata" AVR Variable Attributes, variable attribute โจ-mcvtโ compact vector table energy ๐ฆ Some devices support a CVT with only four entries: 0=Reset, 1=NMI, 2=Prio1 IRQ, 3=Prio0 IRQs. With this on, startup code gets linked from"crtmcu-cvt.o"instead of the usual"crtmcu.o". Besides the tiny table, the startup code also sets the bitCPUINT_CTRLA.CPUINT_CVT, which switches the CVT on for the device.
If you don't want the startup code touching CPUINT_CTRLA.CPUINT_CVT, you can satisfy the symbol "__init_cvt" so that code isn't pulled in from "libmcu.a" anymore. For example, 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").
-mdouble=bits,-mlong-double=bitsโ these set the size (in bits) of thedoubleorlong doubletype, respectively ๐ Valid values for bits are 32 and 64. Whether a 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 these options.-mgas-isr-prologuesโ ISRs are allowed to use the"__gcc_isr"pseudo instruction that GNU Binutils supports ๐ฅ If this option is on, you can still turn the feature off for individual ISRs with the AVR Function Attributes,"no_gccisr"function attribute. This feature is on by default if optimization is on (but not with-Og, @pxref{Optimize Options}), and only if GNU Binutils support PR21683 ("https://sourceware.org/PR21683") โจ-mint8โ this makesintan 8-bit integer ๐ All the types shrink: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes.
Heads up: 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๐ It works the same as attaching the AVR Function Attributes,"OS_task"attribute tomain. It's on by default when optimization is on.-mno-call-mainโ don't runmainthrough the usual call-and-exit dance ๐งโโ๏ธ
XCALL main
XJMP exit
Instead, main gets put in the section ".init9" ("https://avrdudes.github.io/avr-libc/avr-libc-user-manual/mem_sections.html#sec_dot_init"), so no call is needed at all. By turning this on you're promising that main will never return ๐
This one is perfect for devices with very limited resources, since 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 won't be compatible with hardware interrupts ๐ญ The upside is that the code size is smaller.-mrelaxโ this tries to swapCALL(orJMP) for the shorterRCALL(orRJMP) when it's allowed โจ Setting-mrelaxjust adds--mlink-relaxto the assembler's command line and--relaxto the linker's command line.
The linker does the jump relaxing, because jump offsets aren't known until the code is located. So the assembler code the compiler spits out is the same, but the instructions in the executable might look different from it ๐
Relaxing must be turned on if linker stubs are needed. See the section on "EIND" and linker stubs below.
-mrodata-in-ram,-mno-rodata-in-ramโ these decide whether the".rodata"sections for read-only data live in RAM or in program memory ๐ For most devices there's no real choice, so this option basically acts like an assertion.
Since v14, and for the AVR64* and AVR128* devices, ".rodata" lives in flash memory by default, as long as the required GNU Binutils support (PR31124 ("https://sourceware.org/PR31124")) is around. In that case, -mrodata-in-ram can bring back the old layout with ".rodata" in RAM.
-mtiny-stackโ only change the lower 8 bits of the stack pointer ๐-mfract-convert-truncateโ lets you use truncation instead of rounding towards zero for fractional fixed-point types ๐ฆ-nodevicelibโ don't link against AVR-LibC's device specific library"libmcu.a"๐ฅบ
Heads up: since AVR-LibC v2.3, that library holds code that's essential for your program to work properly! It contains parts of the startup code, like "__init_sp" ("https://github.com/avrdudes/avr-libc/issues/1011"), which sets up the stack pointer with the symbol "__stack". It also has "__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 calls "main" and "exit", and "__do_flmap_init" ("https://github.com/avrdudes/avr-libc/issues/931"), which sets up FLMAP according to the symbol "__flmap".
-nodevicespecsโ don't add-specs=device-specs/specs-mcuto the compiler driver's command line ๐ง Now you're in charge of giving the subprocesses (compiler proper, assembler and linker) the right command line options. That means you have to supply your own device specs file with-specs=path-to-specs-file. Once you do that, there's no more need for-mmcu=mcu.
This option can also replace the older way of making custom device-specs files. That one needed -B some-path to point to a directory with a folder named "device-specs", and inside that folder a specs file named "specs-mcu", where mcu was whatever you set with -mmcu=mcu.
-Waddr-space-convertโ warns you about conversions between address spaces when the resulting address space isn't contained in the incoming one ๐-Wmisspelled-isrโ warns if an ISR is misspelled, meaning it's missing the__vectorprefix. It's enabled by default โจ
โจ AVR Optimization Options โจ
These are the pure optimization options ๐
The options -mgas-isr-prologues, -mmain-is-OS_task, -mno-call-main and -mrelax from above are only almost optimization options, because there are rare moments where their different code generation actually matters.
-maccumulate-argsโ collects outgoing function arguments and grabs/releases the stack space for them just once, in the function prologue/epilogue ๐ธ Without this option, outgoing arguments get pushed before a call and popped afterwards. See also the -fdefer-pop Optimize Options, optimization option.
Popping arguments after a call can be expensive on AVR. Accumulating the stack space can lead to smaller executables, since arguments don't need to be removed from the stack after each call.
This can shrink code for functions that make several calls to functions that take their arguments on the stack, like printf-like functions ๐จ๏ธ
-mbranch-cost=costโ sets the branch costs for conditional branch instructions tocost. Reasonable values forcostare small, non-negative integers. The default branch cost is 0 ๐-mcall-prologuesโ function prologues/epilogues get expanded as calls to appropriate subroutines ๐ง Code size is smaller.-mfuse-add,-mno-fuse-add,-mfuse-add=levelโ optimizes indirect memory accesses on reduced Tiny devices ๐ฆ The default useslevel=1for the-Ogand-O1optimizations, andlevel=2for higher optimizations. Valid values for level are 0, 1 and 2.-mfuse-move,-mno-fuse-move,-mfuse-move=levelโ runs a post reload optimization pass that tries to fuse move instructions and to split multi-byte instructions into 8-bit operations ๐ฅ The default useslevel=3for-O1optimization, andlevel=23for higher optimizations. Valid values for level are in the range0 ... 23, which is a 3:2:2:2 mixed radix value. Each digit controls some aspect of the optimization.-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 for indirect, post-increment or pre-decrement addressing.
Without this option, the X register can be used the same way as Y or Z, which then gets emulated with extra instructions. For example, loading a value with X+const addressing (with a small non-negative const < 64) into a register Rn gets 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 shift with a byte offset plus a residual shift with a non-byte offset โ๏ธ This is turned on by default for-O2and higher, including-Osbut excluding-Oz. Splitting shifts with a constant offset that's a multiple of 8 is controlled by-mfuse-move.-msplit-ldstโ splits multi-byte loads and stores into several byte loads and stores ๐ It's 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 ๐ง It's turned on by default for-O2and higher.
โจ "EIND" and Devices With More Than 128 Ki Bytes of Flash โจ
Pointers in the implementation are 16 bits wide ๐ The address of a function or label is represented as a word address, so indirect jumps and calls can target any code address in the range of 64 Ki words ๐ธ
okay so, bestie, this part is about EIND ๐ง, a special function register that's basically the boss of big AVR chips. Devices with more than 128 Ki bytes of program memory need it for indirect jumps ๐
The register is called EIND, and it supplies the most significant part of the target address whenever the EICALL or EIJMP instructions get used ๐ธ
Here's the tea on indirect jumps and calls on these chips. The compiler handles them like this, and there are some limits you need to know about ๐ซถ
- The compiler never sets
EIND. It doesn't touch it at all ๐ - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or it might readEINDdirectly so it can fake an indirect call or jump with aRETinstruction โจ - The compiler assumes
EINDnever changes during the startup code or the application. Like, not once.EINDis not saved or restored in function or interrupt service routine prologues or epilogues ๐ญ - The linker makes stubs for indirect calls to functions and for computed goto. Stubs are jump pads, sometimes called trampolines ๐ฆ So the indirect call or jump lands on a stub, and the stub holds a direct jump to where you actually wanted to go ๐
- Linker relaxation has to be on so the linker builds the stubs correctly in every situation. Check out the compiler option
-mrelaxand the linker option--relax. Heads up: there are corner cases where the linker is supposed to make stubs but just aborts without relaxation, and it won't give you a helpful error message ๐ - The default linker script is set up for code with
EIND = 0. If your code is supposed to work withEIND != 0, you need a custom linker script ๐ It has to put the sections whose names start with.trampolinesinto the segment thatEINDpoints to ๐ - The startup code from libgcc never sets
EIND. Also, startup code is a blend of libgcc and AVR-LibC, so for how AVR-LibC affectsEIND, go read the AVR-LibC user manual athttps://avrdudes.github.io/avr-libc/avr-libc-user-manual/๐ - Your own startup code is allowed to set up
EINDearly. For example, you can do it with initialization code in the section.init3. That code runs before the general startup code that sets up RAM and calls constructors, but after the bit of AVR-LibC startup code that pointsEINDat the segment holding the vector table ๐
Here's an example of that .init3 trick โจ
#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 only when both of these conditions are met ๐
- The address of a label is taken with the
gsmodifier, which is short for generate stubs. It looks like this:
- The address of a label is taken with the
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The final location of that label is in a code segment that's outside the segment where the stubs live ๐ค
- The compiler slaps
gsmodifiers on code labels in these situations ๐- Taking the address of a function or code label
- Computed goto
- When a prologue-save function is used, see the
-mcall-prologuescommand-line option - Switch/case dispatch tables. If you don't want those dispatch tables, you can use the
-fno-jump-tablescommand-line option - C and C++ constructors and destructors that get called during startup or shutdown
- If the tools run into a
gs()modifier like the one described 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 you call the function through a symbol. In the example below, that symbol is func_4 ๐ฆ
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. Or you can define func_4 in the linker script instead ๐ซถ
๐ Handling of the RAMPD, RAMPX, RAMPY and RAMPZ Special Function Registers ๐
Some AVR devices have more memory than the 64 KiB that 16-bit pointers can reach. To get at memory locations past that 64 KiB range, the content of a RAMP register becomes the high part of the address. The X, Y and Z address registers get glued to RAMPX, RAMPY and RAMPZ respectively to make a wide address. RAMPD does the same job with direct addressing ๐ธ
- The startup code sets all the
RAMPspecial function registers to zero ๐ - If a named address space other than generic or
__flashis used (that's the AVR Named Address Spaces stuff), thenRAMPZgets set as needed before the operation โจ - If the device supports more than 64 KiB of RAM and the compiler has to change
RAMPZto pull off an operation, thenRAMPZgets reset to zero once the operation is done ๐ - If the device has a specific
RAMPregister, the ISR prologue and epilogue save and restore that SFR, and they set it to zero in case the ISR code might use it, even implicitly ๐ก๏ธ - GCC does not support RAM larger than 64 KiB for AVR targets ๐ฌ If you use inline assembler to read from locations outside the 16-bit address range and you change one of the
RAMPregisters, you must reset it to zero after the access.
๐ AVR Built-in Macros ๐
GCC defines a bunch of built-in macros so your code can check whether features are there or not ๐ Almost all of the following built-in macros are worked out from device capabilities, so they get triggered by the -mmcu= command-line option ๐ง
For even more AVR-specific built-in macros, check out AVR Named Address Spaces and AVR Built-in Functions ๐
__AVR_ARCH__โ This one is a built-in macro that resolves to a decimal number identifying the architecture. It depends on the-mmcu=mcuoption. The possible values are:
2, 25, 3, 31, 35, 4, 5, 51, 6
Those match mcu="avr2", "avr25", "avr3", "avr31", "avr35", "avr4", "avr5", "avr51" and "avr6" respectively. The values below are for mcu="avrtiny", "avrxmega2", "avrxmega3", "avrxmega4", "avrxmega5", "avrxmega6" and "avrxmega7", in order ๐
100, 102, 103, 104, 105, 106, 107
If mcu names a device, this built-in macro gets set accordingly. For example, -mmcu=atmega8 sets the macro to 4 โจ
__AVR_Device__โ Setting-mmcu=devicedefines this built-in macro, which reflects the device's name. For example,-mmcu=atmega8defines__AVR_ATmega8__, and-mmcu=attiny261adefines__AVR_ATtiny261A__, and so on ๐
The built-in macro names follow the scheme __AVR_Device__, where Device is the device name as it appears in the AVR user manual. The difference between Device in the built-in macro and device in -mmcu=device is that the latter is always lowercase ๐
If device is not an actual device but just a core architecture like avr51, this macro is not defined ๐
__AVR_DEVICE_NAME__โ Setting-mmcu=devicedefines this one to the device's name. For example,-mmcu=atmega8sets it to"atmega8"๐ฆ
If device is just a core architecture like avr51 and not a real device, this macro is not defined ๐
__AVR_CVT__โ The code is being compiled with the-mcvtoption, so it uses 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, which does 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. That's 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. That's 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. Defining 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 it has an 8-bit stack pointer, respectively. Defining these macros is affected by-mmcu=, and for-mmcu=avr2and-mmcu=avr25it's also affected by-msp8๐ฆ__AVR_HAVE_RAMPD__,__AVR_HAVE_RAMPX__,__AVR_HAVE_RAMPY__and__AVR_HAVE_RAMPZ__โ The device has theRAMPD,RAMPX,RAMPYorRAMPZspecial function register, respectively ๐ง__NO_INTERRUPTS__โ This macro reflects the-mno-interruptscommand-line option ๐__AVR_ERRATA_SKIP__and__AVR_ERRATA_SKIP_JMP_CALL__โ Some AVR devices (AT90S8515 and ATmega103) must not skip 32-bit instructions because of a hardware erratum ๐ญ The skip instructions areSBRS,SBRC,SBIS,SBICandCPSE. The second macro only gets defined if__AVR_HAVE_JMP_CALL__is also set โ ๏ธ__AVR_ISA_RMW__โ The device has Read-Modify-Write instructions (XCH,LAC,LASandLAT) ๐ฅ__AVR_SFR_OFFSET__=offsetโ Instructions that can address I/O special function registers directly, likeIN,OUT,SBI, and so on, may use a different address than an instruction accessing RAM, likeLDorSTS. This offset depends on the device architecture, and you have to subtract it from the RAM address to get the matching I/O address ๐ธ__AVR_SHORT_CALLS__โ The-mshort-callscommand-line option is set ๐
"__AVR_PM_BASE_ADDRESS__=addr"
okay so some devices can read flash memory with the LD* instructions ๐ง the flash shows up in the data address space at an offset of __AVR_PM_BASE_ADDRESS__. if that macro isn't defined, this feature just isn't available. if it is defined, the address space is linear and you don't need to shove .rodata into RAM ๐ the default linker description file handles that, and it's currently available for avrtiny and avrxmega3. even better, you don't need address spaces like __flash or stuff like the progmem attribute and pgm_read_* โจ
"__AVR_HAVE_FLMAP__"
this one is defined only when ALL of these conditions are met ๐
- the device has the
NVMCTRL_CTRLB.FLMAPbitfield. this applies to the AVR64* and AVR128* devices ๐ - it's not known at assembler-time which emulation will be used. ๐ซถ
and it 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, it's defined to 1 if the .rodata sections for read-only data live in RAM, and defined to 0 otherwise ๐ง
"__WITH_AVRLIBC__"
the compiler is configured to be used together with AVR-LibC ๐ see the --with-avrlibc configure option.
"__HAVE_SIGNAL_N__"
the compiler supports the signal(num) and interrupt(num) AVR Function Attributes, with an argument num that specifies the number of the interrupt service routine โญ
"__HAVE_DOUBLE_MULTILIB__"
defined if -mdouble= acts as a multilib option ๐
"__HAVE_DOUBLE32__" "__HAVE_DOUBLE64__"
defined if the compiler supports 32-bit double (respectively 64-bit double) ๐ฆ the actual layout is specified by option -mdouble=.
"__DEFAULT_DOUBLE__"
the size in bits of double if -mdouble= is not set ๐ธ if you want to test the layout of double in a program, use the built-in macro __SIZEOF_DOUBLE__ ๐
"__HAVE_LONG_DOUBLE32__" "__HAVE_LONG_DOUBLE64__" "__HAVE_LONG_DOUBLE_MULTILIB__" "__DEFAULT_LONG_DOUBLE__"
same vibe as above, but for long double instead of double ๐
"__WITH_DOUBLE_COMPARISON__"
this one reflects the --with-double-comparison={tristate|bool|libf7} configure option (https://gcc.gnu.org/install/configure.html#avr) and is defined to 2 or 3 โจ
"__WITH_LIBF7_LIBGCC__" "__WITH_LIBF7_MATH__" "__WITH_LIBF7_MATH_SYMBOLS__"
these reflect the --with-libf7={libgcc|math|math-symbols} configure option (https://gcc.gnu.org/install/configure.html#avr) ๐ซง
โจ AVR Internal Options โจ
okay bestie, these are used internally by the compiler and to chat with device specs files and the compiler proper ๐ซถ you don't need to set them by hand. they are not optimization options, fr ๐
using these options the wrong way may lead to sub-optimal or wrong code. they're documented for completeness, and so you can better understand device specs (https://gcc.gnu.org/wiki/avr-gcc#spec-files) files ๐ญ
-mn-flash=numโ assumes the flash memory has a size ofnumtimes 64 KiB ๐ this decides which__flashNaddress spaces are available.-mflmapโ the device has theFLMAPbit field sitting in the special function registerNVMCTRL_CTRLB๐-mrmwโ assumes the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT๐ฅ-mshort-callsโ assumesRJMPandRCALLcan target the whole program memory ๐ฆ this is used for multilib generation and selection for the devices from architectureavrxmega3.-mskip-bugโ generates code without skips (CPSE,SBRS,SBRC,SBIS,SBIC) over 32-bit instructions ๐-msp8โ treats the stack pointer register as an 8-bit register, i.e. assumes the high byte of the stack pointer is zero ๐ธ the compiler uses this to select and build multilibs for architecturesavr2andavr25, since those mix devices with and withoutSPH๐
๐ Blackfin Options ๐
-mcpu=cpu[-sirevision]โ picks the target Blackfin processor ๐ right nowcpucan be one ofbf512,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 is the silicon revision of the target Blackfin processor ๐
any workarounds for that revision get enabled. if sirevision is none, no workarounds are enabled. if it's 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 at all. if it's any, __SILICON_REVISION__ is defined to be 0xffff. if you skip this optional sirevision, 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 ๐
note that support for bf561 is incomplete ๐ญ for bf561, 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. it only has effect 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 skips the instructions to save, set up and restore frame pointers and frees up an extra register in leaf functions โจ-mspecld-anomalyโ when enabled, the compiler makes sure the generated code doesn't contain speculative loads after jump instructions ๐ก๏ธ if you use this option,__WORKAROUND_SPECULATIVE_LOADSis defined.-mno-specld-anomalyโ don't generate extra code to stop speculative loads from happening ๐ โโ๏ธ-mcsync-anomalyโ when enabled, the compiler makes sure the generated code doesn't containCSYNCorSSYNCinstructions too soon after conditional branches ๐ if you use this option,__WORKAROUND_SPECULATIVE_SYNCSis defined.-mno-csync-anomalyโ don't generate extra code to stopCSYNCorSSYNCinstructions from happening too soon after a conditional branch ๐-mlow64kโ when enabled, the compiler is free to take advantage of knowing the entire program fits into the low 64k of memory ๐-mno-low64kโ assumes the program is arbitrarily large ๐ธ this is the default.-mstack-check-l1โ does stack checking using information placed into L1 scratchpad memory by the uClinux kernel ๐ง-mid-shared-libraryโ generates code that supports shared libraries via the library ID method ๐ this lets you execute in place and use shared libraries in an environment without virtual memory management. this option implies-fPIC, and with abfin-elftarget it also implies-msim๐-mno-id-shared-libraryโ generates code that doesn't assume ID-based shared libraries are being used ๐ this is the default.-mleaf-id-shared-libraryโ generates code that supports shared libraries via the library ID method, but assumes this library or executable won't link against any other ID shared libraries ๐ฆ that lets the compiler use faster code for jumps and calls โญ-mno-leaf-id-shared-libraryโ don't assume the code being compiled won't link against any ID shared libraries ๐ข slower code gets generated for jump and call insns.-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 it's no more space- or time-efficient than omitting this option.-msep-dataโ 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, by getting rid of relocations against the text section ๐ง-mno-sep-dataโ generates code that assumes the data segment follows the text segment ๐ this is the default.-mlong-calls,-mno-long-callsโ tells the compiler to do function calls by first loading the function's address into a register, and then doing a subroutine call on that register ๐ you need this switch if the target function lies outside the 24-bit addressing range of the offset-based version of the subroutine call instruction ๐ญ
this feature is not enabled by default. -mno-long-calls restores the default behavior ๐
โโ๏ธ also note these switches have no effect on how the compiler handles function calls via function pointers ๐
-mfast-fpโ links with the fast floating-point library ๐๏ธ this library relaxes some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN), in the interest of performance ๐ธ-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.-mmulticoreโ builds a standalone application for multicore Blackfin processors ๐ this makes sure the proper start files and link scripts supporting multicore get used, and defines the macro__BFIN_MULTICORE. it can only be used with-mcpu=bf561[-sirevision]๐ซง
this option can be combined with -mcorea or -mcoreb, which select the one-application-per-core programming model ๐
without -mcorea or -mcoreb, the single-application/dual-core programming model is used instead. in this model, the main function of Core B should be named coreb_main ๐ง
if you don't use this option, the single-core application programming model is used ๐
-mcoreaโ Builds a standalone app for Core A of BF561 when you're doing the one-application-per-core thing. It swaps in the right start files and link scripts for Core A and defines the macro"__BFIN_COREA"for you โจ. This one only works alongside-mmulticore๐ซถ.-mcorebโ Same deal, but for Core B of BF561 in the one-application-per-core setup. It uses the Core B start files and link scripts and defines"__BFIN_COREB". When you turn this on, your entry point has to be"coreb_main"instead of"main"๐. It also only works with-mmulticore๐.-msdramโ Builds a standalone app that runs out of SDRAM ๐ง. The start files and link scripts put the app in SDRAM and the macro"__BFIN_SDRAM"gets defined. Your loader has to initialize SDRAM before it loads the app, so don't skip that step bestie ๐ญ.-micplbโ Tells GCC to assume ICPLBs are enabled at run time ๐ธ. That changes how certain anomaly workarounds behave. For Linux targets it assumes ICPLBs are on by default, but for standalone apps the default is off.
๐ฆ C6X Options ๐ฆ
-march=nameโ Picks the target architecture, and GCC uses it to decide which instructions it's allowed to emit when it generates assembly ๐ . The names you can use 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, so you're already slay ๐.-msimโ Picks startup files and a linker script that work with the simulator ๐.-msdata=defaultโ Small global and static data goes in the".neardata"section, whichB14points to โจ. Small uninitialized global and static data goes in".bss", right next to".neardata". Small read-only data goes in".rodata". For the big stuff, the matching sections are".fardata",".far", and".const".-msdata=allโ Shoves all data into the small-data sections, not just the tiny stuff, and accesses it relative to theB14register ๐ฅ.-msdata=noneโ No small-data sections at all ๐. Every access uses absolute addresses. All initialized global and static data goes in".fardata", all uninitialized data goes in".far", and all constant data goes in".const".
๐ CRIS Options ๐
These options are made specifically for the CRIS ports, so they only show up in that world ๐ง.
-march=architecture-type,-mcpu=architecture-typeโ Generates code for the architecture you name โญ. The choices arev3,v8, andv10, which map to ETRAX 4, ETRAX 100, and ETRAX 100 LX. The default isv0.-mtune=architecture-typeโ Tunes everything that can be tuned in the generated code to the architecture you pick ๐ฆ. The ABI and the set of available instructions stay the same though. Your choices are the same as for-march=architecture-type.-mmax-stack-frame=nโ Gives you a warning if a function's stack frame goes overnbytes ๐ญ.-metrax4,-metrax100โ These two are just nicknames:-metrax4means-march=v3, and-metrax100means-march=v8๐.-mmul-bug-workaround,-mno-mul-bug-workaroundโ Works around a bug in the"muls"and"mulu"instructions on the CPU models where it actually applies ๐. It's off by default.-mpdebugโ Turns on CRIS-specific verbose debug info in the assembly code โจ. It also turns off the#NO_APPformatted-code marker that normally sits at the top of the assembly file for the assembler.-mcc-initโ Stops GCC from reusing condition-code results from the previous instruction ๐ . Instead it always emits compare and test instructions before using condition codes.-mno-side-effectsโ No instructions with side effects in addressing modes, unless it's post-increment ๐ซถ.-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ The non-no-versions make the stack frame, individual data, and constants line up to the biggest single data access size your chosen CPU model supports ๐. Theno-versions undo that. By default everything is aligned to 32 bits. ABI stuff like structure layout doesn't change with any of these ๐.-m32-bit,-m16-bit,-m8-bitโ Same vibe as the align options above, but these set the alignment of stack frames, writable data, and constants to 32, 16, or 8 bits ๐ธ. The default is 32-bit.-mno-prologue-epilogue,-mprologue-epilogueโ With-mno-prologue-epilogue, GCC skips the usual function prologue and epilogue that set up the stack frame โ ๏ธ. It also won't generate any return instructions or return sequences. Only use this if you're going to eyeball the compiled code yourself, because GCC won't warn or error when call-saved registers need saving or when local variables need storage ๐.-melfโ A legacy no-op, so it does nothing ๐.-simโ Links with the input-output functions from a simulator library ๐ง. Code, initialized data, and zero-initialized data get allocated one right after the other.-sim2โ Like-sim, but it also passes linker options so initialized data lands at0x40000000and zero-initialized data lands at0x80000000๐ฅ.
๐ธ C-SKY Options ๐ธ
GCC supports these when you're compiling for C-SKY V2 processors ๐ฆ.
-march=archโ Specifies the C-SKY target architecture. The valid values areck801,ck802,ck803,ck807, andck810. The default isck810๐ .-mcpu=cpuโ Specifies the C-SKY target processor. Valid values forcpuare: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, andck810ftv๐.-mbig-endian,-EB,-mlittle-endian,-ELโ Picks big-endian or little-endian code ๐ซถ. Little-endian is the default.-mfloat-abi=nameโ Picks which floating-point ABI to use. The options aresoft,softfp, andhard๐ฅ.
soft makes GCC generate output that calls library functions for floating-point math. softfp lets it use hardware floating-point instructions but still follows the soft-float calling conventions. hard gives you floating-point instructions and uses FPU-specific calling conventions ๐.
The default depends on your specific target configuration. Heads up though: the hard-float and soft-float ABIs are not link-compatible ๐ญ. You have to compile your whole program with the same ABI and link it against a compatible set of libraries.
-mhard-float,-msoft-floatโ Picks hardware or software floating-point implementations ๐ฆ. The default is soft float.-mdouble-float,-mno-double-floatโ When-mhard-floatis on, this enables double-precision float instructions โจ. It's the default except when compiling for CK803.-mfdivdu,-mno-fdivduโ When-mhard-floatis on, this enables the"frecipd","fsqrtd", and"fdivd"instructions ๐ง. It's the default except when compiling for CK803.-mfpu=fpuโ Picks the floating-point processor ๐ . This one only works with-mhard-float. The values forfpuarefpv2_sf(which is the same as-mno-double-float -mno-fdivdu),fpv2(which is-mdouble-float -mno-divdu), andfpv2_divd(which is-mdouble-float -mdivdu).-melrw,-mno-elrwโ Enables the extended"lrw"instruction ๐. It defaults to on for CK801 and off for everything else.-mistack,-mno-istackโ Enables interrupt stack instructions ๐ฅ. The default is off.
The-mistackoption is required if you want to handle the"interrupt"and"isr"function attributes ๐.
-mmpโ Enables multiprocessor instructions. Default is off ๐ซถ.-mcpโ Enables coprocessor instructions. Default is off ๐.-mcacheโ Also enables coprocessor instructions. Default is off ๐.-msecurityโ Enables C-SKY security instructions. Default is off ๐.-mtrustโ Enables C-SKY trust instructions. Default is off โจ.-mdsp,-medsp,-mvdspโ These turn on C-SKY DSP, Enhanced DSP, or Vector DSP instructions, in that order ๐. All of them default to off.-mdiv,-mno-divโ Generates divide instructions. Default is off ๐ฆ.-msmart,-mno-smartโ Generates code for Smart Mode, which only uses registers numbered 0-7 so you can use 16-bit instructions ๐ง. This gets ignored for CK801, where that's already the required behavior, and it defaults to on for CK802. For other targets the default is off.-mhigh-registers,-mno-high-registersโ Generates code that uses the high registers numbered 16-31 ๐. This isn't supported on CK801, CK802, or CK803, and it's enabled by default on other processors.-manchor,-mno-anchorโ Generates code that uses global anchor symbol addresses โญ.-mpushpop,-mno-pushpopโ Generates code using"push"and"pop"instructions ๐ . It defaults to on.-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ Generates code using"stm"and"ldm"instructions ๐. This isn't supported on CK801, but it's enabled by default on other processors.-mconstpool,-mno-constpoolโ Creates constant pools in the compiler, instead of leaving it to the assembler ๐ซถ. This is the default, and it's required for correct code generation on CK801 and CK802. It's optional on other processors.-mstack-size,-mno-stack-sizeโ Emits".stack_size"directives for each function in the assembly output ๐. It defaults to off.-mccrt,-mno-ccrtโ Generates code for the C-SKY compiler runtime instead of libgcc ๐. It defaults to off.-mbranch-cost=nโ Sets the branch costs to roughlyninstructions ๐. The default is 1.-msched-prolog,-mno-sched-prologโ okay so these let you turn on scheduling for function prologue and epilogue sequences ๐ง Heads up, though: this can produce code that doesn't follow the C-SKY V2 ABI prologue rules, and you won't be able to debug it or backtrace through it ๐ญ It's off by default, so you'd have to opt in on purpose.-msimโ this links in the librarylibsemi.a, which is compatible with the simulator ๐ป It only applies to the ELF compiler, so don't expect it anywhere else ๐ธ
โจ Cygwin and MinGW Options โจ
These extra options are for Microsoft Windows targets ๐ช๐
-mconsoleโ this tells the linker to set the PE header subsystem type to console, so you get a console application ๐ฅ๏ธ It works for Cygwin and MinGW targets and is already on by default there ๐ซถ-mcrtdll=libraryโ this one is kind of a big deal ๐ It preprocesses, compiles or links with the C RunTime DLL library you name. It changes the predefined macros"__CRTDLL__","__MSVCRT__","_UCRT"and"__MSVCRT_VERSION__"for that CRT library, picks the start file for it, and links against it too. The CRT library names the preprocessor recognises are"crtdll*","msvcrt10*","msvcrt20*","msvcrt40*","msvcr40*","msvcrtd*","msvcrt-os*","msvcr70*","msvcr71*","msvcr80*","msvcr90*","msvcr100*","msvcr110*","msvcr120*"and"ucrt*"โจ If you don't use this option, the default MinGW import library"msvcrt"gets used for linking, and the preprocessor doesn't get any adjustments. That"msvcrt"library is just a symlink to, or a copy of, another MinGW CRT import library that gets picked when MinGW is compiled ๐ The"msvcrt-os"library is for the Windows system CRT DLL"msvcrt.dll", and it's usually the default MinGW import library ๐ Generally speaking, switching the CRT DLL means recompiling the entire MinGW CRT, so this is strictly for experiments and testing ๐งช It's only for MinGW targets.-mdllโ this one's for Cygwin and MinGW targets ๐ฆ It makes a DLL, which is a dynamic link library, and lets you pick the runtime startup object and entry point you need.-mnop-fun-dllimportโ available for Cygwin and MinGW targets ๐ It tells GCC to ignore the"dllimport"attribute.-mthreadsโ for MinGW targets only ๐งต It turns on MinGW-specific thread support.-municodeโ for MinGW-w64 targets ๐ It predefines the"UNICODE"preprocessor macro and picks Unicode-capable runtime startup code.-mwin32โ for Cygwin and MinGW targets ๐ It sets the typical Microsoft Windows predefined macros in the preprocessor, but it doesn't change which runtime library or startup code gets chosen.-mwindowsโ for Cygwin and MinGW targets ๐ช It makes a GUI application by telling the linker to set the PE header subsystem type to match.-fno-set-stack-executableโ for MinGW targets ๐ It means the executable flag isn't set for the stack that nested functions use. This matters for binaries running in Microsoft Windows kernel mode, because the User32 API that sets executable privileges isn't available there ๐-fwritable-relocated-rdataโ for MinGW and Cygwin targets ๐ It puts relocated data from a read-only section into the".data"section. This is needed for older runtimes that can't modify".rdata"sections for pseudo-relocation.-mpe-aligned-commonsโ for Cygwin and MinGW targets โจ It uses the GNU extension to the PE file format that lets COMMON variables be aligned correctly when generating code. It's on by default if GCC detects that the target assembler found during configuration supports the feature ๐ซถ
See also under x86 Options for standard options ๐
๐ Darwin Options ๐
These options are defined for every architecture running the Darwin operating system ๐ธ
FSF GCC on Darwin doesn't make "fat" object files ๐
โโ๏ธ It makes an object file for the single architecture that GCC was built to target. Apple's GCC on Darwin does make "fat" files when you use multiple -arch options ๐ It does this by running the compiler or linker several times and joining the results together with lipo.
The subtype of the file (like ppc7400, ppc970 or i686) comes from the flags that specify the ISA GCC is targeting, like -mcpu or -march โจ The -force_cpusubtype_ALL option can override that.
The Darwin tools act differently when they hit an ISA mismatch ๐ The assembler, as, only lets you use instructions that are valid for the subtype of the file it's making, so you can't put 64-bit instructions in a ppc750 object file ๐ซ The linker for shared libraries, /usr/bin/libtool, fails and prints an error if you ask it to make a shared library with a less restrictive subtype than its input files. For instance, trying to put a ppc970 object file in a ppc7400 library is a no-go ๐ญ The linker for executables, ld, quietly gives the executable the most restrictive subtype of any of its input files ๐คซ
-Fdirโ this adds the framework directorydirto the front of the list of directories searched for header files ๐ These directories get mixed in with the ones from-Ioptions, and they're scanned left to right ๐
A framework directory is just a directory full of frameworks ๐ง A framework is a directory with a Headers and/or PrivateHeaders directory right inside it, and its name ends in .framework. The framework's name is that directory's name without the .framework part. Headers for the framework live in one of those two directories, and Headers gets searched first ๐ฅฐ A subframework is a framework directory that sits inside a framework's Frameworks directory. Including subframework headers only works from a header inside the framework that holds the subframework, or from a sibling subframework header. Two subframeworks are siblings if they live in the same framework ๐ฏ A subframework shouldn't share a name with a framework, and if it does, you'll get a warning โ ๏ธ 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 the PrivateHeaders or Headers directory ๐
-iframeworkdirโ this is 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 found throughdir๐ This only works for the C family of languages.-gusedโ this emits debugging info for symbols that are actually used ๐ For the stabs debugging format, it turns on-feliminate-unused-debug-symbols. It's ON by default โ-gfullโ this emits debugging info for every symbol and type ๐-fconstant-cfstringsโ this is just an alias for-mconstant-cfstrings๐-mconstant-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 ๐-mmacosx-version-min=versionโ this sets the earliest version of MacOS X that the executable will run on ๐ Typical values forversioninclude12,10.12, and10.5.8๐
If the compiler was built to use the system's headers by default, the default for this option is the system version the compiler is running on โจ Otherwise, the default is to make choices that are compatible with as many systems and code bases as possible ๐ซถ
-mkernelโ this turns on kernel development mode ๐งโ๐ป It sets-static,-fno-common,-fno-use-cxa-atexit,-fno-exceptions,-fno-non-call-exceptions,-fapple-kext,-fno-weakand-fno-rttiwhere they apply. It also sets-mno-altivec,-msoft-float,-fno-builtinand-mlong-branchfor PowerPC targets ๐-mone-byte-boolโ this overrides the defaults for"bool"so thatsizeof(bool)==1๐ฏ By defaultsizeof(bool)is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86, so this option does nothing on x86.
Warning: The -mone-byte-bool switch makes GCC generate code that isn't binary compatible with code generated without it ๐ฑ You may have to recompile all the other modules in a program, including system libraries, if you use it. Only use this switch when you need to match a non-default data model ๐
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ these generate code built for quick turnaround development ๐ฅ For example, they let GDB dynamically load.ofiles into programs that are already running โก-findirect-dataand-ffix-and-continueare only here for backwards compatibility ๐ฐ๏ธ-all_loadโ this loads every member of static archive libraries ๐ฆ Seeman ld(1)for more information ๐-arch_errors_fatalโ this makes errors about files with the wrong architecture fatal ๐จ-bind_at_loadโ this marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched ๐ช-bundleโ this produces a Mach-o bundle format file ๐ Seeman ld(1)for more information.-bundle_loader executableโ this names the executable that will load the build output file being linked ๐ซถ Seeman ld(1)for more information.-dynamiclibโ when you pass this, GCC makes a dynamic library instead of an executable when linking, using the Darwinlibtoolcommand ๐ฆ-force_cpusubtype_ALLโ this gives GCC's output file the ALL subtype, instead of the one that-mcpuor-marchwould pick ๐
Okay so the Darwin linker bit is next, and bestie, there are SO many of these ๐ ๐ธ
Quick heads up: all of these get handed straight to the Darwin linker, so if you want the full lowdown on each one, go read that linker's man page ๐ง
-nodefaultrpathsโ Ngl this one is kinda important ๐ It stops GCC from tossing default run paths for the compiler library directories into your executables, modules, or dynamic libraries. On macOS 10.5 and later, the embedded runpath gets added automatically unless you add-nodefaultrpathsto your link line. Run paths are needed (so they're enforced!) to build on macOS 10.11 or later โจ
Now here's the whole squad of Darwin linker options, and they all share the same vibe ๐
-allowable_client client_name-client_name-compatibility_version-current_version-dead_strip-dependency-file-dylib_file-dylinker_install_name-dynamic-exported_symbols_list-filelist-flat_namespace-force_flat_namespace-headerpad_max_install_names-image_base-init-install_name-keep_private_externs-multi_module-multiply_defined-multiply_defined_unused-noall_load-no_dead_strip_inits_and_terms-nofixprebinding-nomultidefs-noprebind-noseglinkedit-pagezero_size-prebind-prebind_all_twolevel_modules-private_bundle-read_only_relocs-sectalign-sectobjectsymbols-whyload-seg1addr-sectcreate-sectobjectsymbols-sectorder-segaddr-segs_read_only_addr-segs_read_write_addr-seg_addr_table-seg_addr_table_filename-seglinkedit-segprot-segs_read_only_addr-segs_read_write_addr-single_module-static-sub_library-sub_umbrella-twolevel_namespace-umbrella-undefined-unexported_symbols_list-weak_reference_mismatches-whatsloaded
These get passed straight to the Darwin linker, which has the full deep dive on each one ๐ฆ
โจ DEC Alpha Options โจ
These -m options are defined for the DEC Alpha implementations ๐
-mno-soft-float-msoft-floatโ Okay so these two are opposites bestie ๐ซถ One uses the hardware floating-point instructions for floating-point ops, the other doesn't. With-msoft-float, functions inlibgcc.ado the floating-point work instead. Unless those get replaced with routines that emulate the floating-point operations, or get compiled to call those emulation routines, these routines issue floating-point operations. So 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 ๐ญ
Also, Alpha implementations without floating-point operations are still required to have floating-point registers, so keep that in mind ๐ธ
-mfp-reg-mno-fp-regsโ Generates code that uses (or doesn't use) the floating-point register set.-mno-fp-regsimplies-msoft-float. If the 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-regsalso has to be compiled with that option. Big rule, bestie ๐จ
A typical use is building a kernel that doesn't use (and therefore doesn't need to save and restore) any floating-point registers ๐ง
-mieeeโ The Alpha architecture has floating-point hardware that's optimized for max performance, and it's mostly IEEE compliant. For full compliance though, it needs software help ๐ This option makes fully IEEE-compliant code, EXCEPT the inexact-flag isn't maintained (see below). When it's on, the preprocessor macro"_IEEE_FP"gets defined during compilation. The code is less efficient, but it can correctly handle denormalized numbers and exceptional IEEE values like not-a-number and plus/minus infinity. Other Alpha compilers call this option-ieee_with_no_inexact๐
DEBIAN SPECIFIC: This option is on by default for alpha-linux-gnu, unless -ffinite-math-only (which is part of the -ffast-math set) is specified. Why? Because the software functions in the GNU libc math libraries generate denormalized numbers, NaNs, and infs, and all of those will make a program SIGFPE when it tries to use the results without -mieee ๐
-mieee-with-inexactโ This is like-mieee, except the generated code also maintains the IEEE inexact-flag. Turn this on and the code implements fully-compliant IEEE math. On top of"_IEEE_FP", the preprocessor macro"_IEEE_FP_EXACT"also gets defined. On some Alpha implementations the code might run way slower than the default, and since there's very little code that depends on the inexact-flag, you should normally NOT specify this one ๐ Other Alpha compilers call it-ieee_with_inexactโจ-mfp-trap-mode=trap-modeโ Controls which floating-point related traps are enabled ๐ฅ Other Alpha compilers call this option-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 disabled in software (like the division by zero trap).uโ On top of everythingnenables, underflow traps get enabled too.suโ Likeu, but the instructions are marked as safe for software completion (see the Alpha architecture manual for details).suiโ Likesu, but inexact traps are enabled as well.
-mfp-rounding-mode=rounding-modeโ Selects the IEEE rounding mode ๐ Other Alpha compilers call this one-fprm rounding-mode. Therounding-modecan be one of:nโ Normal IEEE rounding mode. Floating-point numbers get rounded towards the nearest machine number, or towards the even machine number in case of a tie.mโ Round towards minus infinity.cโ Chopped rounding mode. Floating-point numbers get rounded towards zero.dโ Dynamic rounding mode. A field in the floating-point control register (fpcr, see the Alpha architecture reference manual) controls the rounding mode in effect. The C library sets this register up for rounding towards plus infinity. So unless your program messes with thefpcr,dmeans round towards plus infinity ๐ฆ
-mtrap-precision=trap-precisionโ Okay so on the Alpha architecture, 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 location that caused a floating-point trap. Depending on what your app needs, you can pick one of these precision levels:pโ Program precision. This is the default, and it means a trap handler can only tell which program caused the floating-point exception.fโ Function precision. The trap handler can figure out the function that caused a floating-point exception.iโ Instruction precision. The trap handler can figure out the exact instruction that caused a floating-point exception.
Other Alpha compilers have the equivalent options called -scope_safe and -resumption_safe โจ
-mieee-conformantโ This marks the generated code as IEEE conformant ๐ You must NOT use this unless you also specify-mtrap-precision=iAND either-mfp-trap-mode=suor-mfp-trap-mode=sui. 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 build it 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 using code, even if that takes more instructions (the max is six). You'd typically use this to build a shared library dynamic loader. Since it's a shared library itself, 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โ Says 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 CPU GCC was built on if you don't specify one.-msafe-bwa-mno-safe-bwaโ Says whether, when the optional BWX instruction set is missing, GCC should generate multi-thread and async-signal safe code for byte and aligned word memory accesses ๐-msafe-partial-mno-safe-partialโ Says 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 respectively start and end on an aligned 64-bit data boundary ๐ซถ-mfloat-vax-mfloat-ieeeโ Generates code that uses (or doesn't use) VAX F and G floating-point arithmetic instead of IEEE single and double precision ๐-mexplicit-relocs-mno-explicit-relocsโ Okay so 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 gets accessed via gp-relative relocations. With-msmall-data, objects 8 bytes long or smaller get placed in a small data area (the".sdata"and".sbss"sections) and get accessed through 16-bit relocations off of the$gpregister. This limits the small data area to 64KB, but the upside is the variables can be accessed directly with a single instruction, which is iconic ๐
The default is -mlarge-data, bestie ๐ With this on, the data area is capped at just under 2GB. If your program needs more than 2GB of data, it has to use malloc or mmap to grab memory from the heap instead of stuffing it into the program's data segment ๐ง โจ
When you're 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 for the whole program (or shared library) fits in 4MB, so everything is reachable with a branch instruction. With-msmall-data, the compiler can assume all local symbols share the same$gpvalue, which cuts the instructions needed for a function call from 4 down to 1. It's giving efficiency ๐ญ
The default is -mlarge-text ๐
-mcpu=cpu_typeโ ๐ Sets the instruction set and instruction scheduling parameters for the machine typecpu_type. You can use either the EV style name or the matching chip number. GCC has scheduling parameters for the EV4, EV5, and EV6 families, and it picks the default instruction set based on the processor you name. If you don't name a processor type, GCC just goes with whatever 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 does nothing if GCC doesn't recognize the processor ๐
-mtune=cpu_typeโ ๐ฏ Only sets the instruction scheduling parameters for the machine typecpu_type. The instruction set stays exactly the same.
Native toolchains also support the value native, which picks the best architecture option for the host processor. -mtune=native does nothing 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 really depends on the memory access patterns the application uses and how big the external cache is on the machine. Lowkey a vibe-check number ๐
Valid options for time are:
numberโ A decimal number representing clock cycles ๐ขL1,L2,L3,mainโ The compiler has estimates of clock cycles for "typical" EV4 & EV5 hardware for the Level 1, 2, and 3 caches (also called Dcache, Scache, and Bcache), plus main memory. Note thatL3is only valid for EV5 ๐ซถ
โจ eBPF Options โจ
-mframe-limit=bytesโ ๐ง Specifies the hard limit for frame sizes, in bytes. Right now the value you pass should be less than or equal to 32767. It defaults to whatever limit the targeted version of the Linux kernel imposes ๐ง-mbig-endianโ ๐ Generates code for a big-endian target ๐-mlittle-endianโ ๐ Generates code for a little-endian target. This is the default ๐-mjmpext,-mno-jmpextโ ๐ฆ Enables or disables generation of extra conditional-branch instructions. Enabled for CPU v2 and above ๐ฅ-mjmp32,-mno-jmp32โ ๐ฆ Enables or disables generation of 32-bit jump instructions. Enabled for CPU v3 and above ๐ฅ-malu32,-mno-alu32โ ๐ฆ Enables or disables generation of 32-bit ALU instructions. Enabled for CPU v3 and above ๐ฅ-mv3-atomics,-mno-v3-atomicsโ โ๏ธ Enables or disables instructions for general atomic operations introduced in CPU v3. Enabled for CPU v3 and above ๐ฅ-mbswap,-mno-bswapโ ๐ Enables or disables byte swap instructions. Enabled for CPU v4 and above ๐-msdiv,-mno-sdivโ โ Enables or disables signed division and modulus instructions. Enabled for CPU v4 and above ๐-msmov,-mno-smovโ ๐ Enables or disables sign-extending move and memory load instructions. Enabled for CPU v4 and above ๐-mcpu=versionโ ๐ Specifies which version of the eBPF ISA to target. Newer versions might not be supported by every kernel. The default isv4.
Supported values for version are:
v1โ The first stable eBPF ISA, with no special features or extensions ๐ผv2โ Supports the jump extensions, as in-mjmpext๐ฑv3โ All features of v2, plus:-<32-bit jump operations, as in -mjmp32>-<32-bit ALU operations, as in -malu32>-<general atomic operations, as in -mv3-atomics>
v4โ All features of v3, 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>
-mco-reโ ๐ง Enables BPF Compile Once - Run Everywhere (CO-RE) support. It requires and is implied by-gbtf๐ซถ-mno-co-reโ ๐ Disables BPF Compile Once - Run Everywhere (CO-RE) support. BPF CO-RE support is enabled by default when generating BTF debug information for the BPF target ๐-mxbpfโ ๐ Generates code for an expanded version of BPF, which relaxes some of the restrictions the BPF architecture imposes. It can:-<Save and restore callee-saved registers at function entry and exit, respectively.>
-masm=dialectโ ๐ Outputs assembly instructions using the selected eBPF dialect. The default ispseudoc๐
Supported values for dialect are:
normalโ Outputs the normal assembly dialect ๐pseudocโ Outputs the pseudo-C assembly dialect ๐-minline-memops-threshold=bytesโ ๐ Specifies a size threshold in bytes at or below whichmemmove,memcpy, andmemsetare always expanded inline. Operations dealing with sizes bigger than this threshold would have to use a library call instead of being expanded inline. BPF doesn't allow libcalls, though, so going over this threshold is a compile-time error ๐ The default is 1024 bytes.
๐ง FR30 Options ๐ง
These options are defined specifically for the FR30 port ๐ธ
-msmall-modelโ ๐ฌ Uses the small address space model. This can produce smaller code, but it does assume that all symbolic values and addresses fit into a 20-bit range.-mno-lsimโ ๐ ๏ธ Assumes runtime support has been provided, so there's no need to include the simulator library (libsim.a) on the linker command line.
๐ท FT32 Options ๐ท
These options are defined specifically for the FT32 port ๐ฆ
-msimโ ๐ฅ๏ธ Specifies that the program will run on the simulator. This links in an alternate runtime startup and library. You must not use this option when generating programs for real hardware. You have to provide your own runtime library for whatever I/O functions are needed ๐จ-mlraโ ๐คท Does nothing. Preserved for backward compatibility.-mnodivโ โ Do not usedivandmodinstructions.-mft32bโ โจ Enables use of the extended instructions of the FT32B processor.-mcompressโ ๐๏ธ Compresses all code using the Ft32B code compression scheme.-mnopmโ ๐ Do not generate code that reads program memory.
๐ฆ 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 ๐งธ-malloc-ccโ Dynamically allocates condition code registers ๐ฒ-mfixed-ccโ Does not try to dynamically allocate condition code registers. It only usesicc0andfcc0๐-mdwordโ Changes the ABI to use double word instructions ๐ฏ-mno-dwordโ Does not use double word instructions ๐-mdoubleโ Uses floating-point double instructions ๐-mno-doubleโ Does not use floating-point double instructions ๐-mmediaโ Uses media instructions ๐ฌ-mno-mediaโ Does not use media instructions ๐-mmuladdโ Uses multiply and add/subtract instructions โ-mno-muladdโ Does not use 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 are not known to bind locally. It has no effect without-mfdpic. It's enabled by default when optimizing for speed and compiling for shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is on 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 ofGPRELrelocations in the FDPIC ABI for data known to be in read-only sections. It's enabled by default, except for-fpicor-fpie: even though it may make the global offset table smaller, it trades 1 instruction for 4. With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols. It also avoids the need for a GOT entry for the referenced symbol, so it's more likely to be a win. If it isn't,-mno-gprel-rocan be used to 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โ Sticks to the EABI rule that a frame pointer must always be created whenever a stack frame gets allocated. It's on by default, and you can turn it off with-mno-linked-fp๐ฆ-mlong-callsโ Calls functions outside the current compilation unit through indirect addressing, so those functions can live anywhere in the 32-bit address space โจ-malign-labelsโ Tries to align labels to an 8-byte boundary by slipping NOPs into the previous packet ๐ธ. This only does anything when VLIW packing is on. It never makes new packets, it just adds NOPs to packets that already exist ๐-mlibrary-picโ Generates position-independent EABI code ๐ง-macc-4โ Only uses the first four media accumulator registers ๐-macc-8โ Uses all eight media accumulator registers ๐ฅ-mpackโ Packs VLIW instructions ๐ฆ-mno-packโ Does not pack VLIW instructions ๐ โโ๏ธ-mno-eflagsโ Doesn't mark ABI switches ine_flags๐ซถ-mcond-moveโ Turns on conditional-move instructions. This is the default ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-cond-moveโ Turns off conditional-move instructions ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-msccโ Turns on conditional set instructions. This is the default โจ
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-sccโ Turns off conditional set instructions ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mcond-execโ Turns on conditional execution. This is the default ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-cond-execโ Turns off conditional execution ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mvliw-branchโ Runs a pass that packs branches into VLIW instructions. This is the default ๐ฆ
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-vliw-branchโ Skips that pass, so branches don't get packed into VLIW instructions ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mmulti-cond-execโ Turns on optimization of"&&"and"||"in conditional execution. This is the default ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-multi-cond-execโ Turns off optimization of"&&"and"||"in conditional execution ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mnested-cond-execโ Turns on nested conditional execution optimizations. This is the default ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-nested-cond-execโ Turns off nested conditional execution optimizations ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-moptimize-membarโ Removes redundant"membar"instructions from the compiler-generated code. It's on by default ๐งน-mno-optimize-membarโ Stops the automatic removal of redundant"membar"instructions from the generated code ๐ โโ๏ธ-mtomcat-statsโ Makes gas print out tomcat statistics ๐-mcpu=cpuโ Picks the processor type you want code generated for. The options arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300andsimple๐
๐ง 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โ Uses the uClibc C library. This is the default on*-*-linux-*uclibc*targets โจ-mmuslโ Uses the musl C library. This is the default on*-*-linux-*musl*targets ๐ฆ-mbionicโ Uses the Bionic C library. This is the default on*-*-linux-*android*targets ๐ค-mandroidโ Compiles code that's compatible with the Android platform. This is the default on*-*-linux-*android*targets ๐ฑ
When compiling, this option turns on -mbionic, -fPIC, -fno-exceptions and -fno-rtti by default. When linking, it makes the GCC driver pass Android-specific options to the linker. And finally, it causes the preprocessor macro "__ANDROID__" to get defined ๐ซถ
-tno-android-ccโ Undoes the compilation effects of-mandroid. That means it won't turn on-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐-tno-android-ldโ Undoes the linking effects of-mandroid, so the linker gets standard Linux linking options instead ๐ง
๐ H8/300 Options ๐
These -m options are defined for the H8/300 implementations ๐
-mrelaxโ Shortens some address references at link time when it's possible. It uses 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. This switch has to be used with either-mhor-ms๐-ms2600โ Generates code for the H8S/2600. This switch has to be used with-ms๐ฅ-mexrโ Extended registers get stored on the stack before a function with the monitor attribute runs. The default option is-mexr. This option is only valid for H8S targets ๐-mno-exrโ Extended registers do not get stored on the stack before a function with the monitor attribute runs. The default option is-mno-exr. This option is only valid for H8S targets ๐ โโ๏ธ-mint32โ Makes"int"data 32 bits by default ๐-malign-300โ On the H8/300H and H8S, uses the same alignment rules as the H8/300. By default, the H8/300H and H8S align longs and floats on 4-byte boundaries, but-malign-300makes them align on 2-byte boundaries instead. This option does nothing 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 for architecture-type 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 on an HP-UX system, check/usr/lib/sched.models๐. 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.1, and-march=2.0respectively ๐ฆ-matomic-libcallsโ Generates libcalls for atomic loads and stores when sync libcalls are disabled. This is on by default, and it only affects how the HPPA backend generates atomic libcalls โจ
Both the sync and libatomic libcall implementations use locking. Because of that, processor stores aren't atomic with respect to other atomic operations. Processor loads up to DImode are 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 for the "ldcw" instruction. So all atomic support is implemented using sync and atomic libcalls. Sync libcall support lives in libgcc.a, and atomic libcall support lives in libatomic ๐
This option generates "__atomic_exchange" calls for atomic stores. It also gives special handling to atomic DImode accesses on 32-bit targets ๐
-mbig-switchโ Does nothing. It's only kept around for backward compatibility ๐ฐ๏ธ-mcaller-copiesโ The caller copies function arguments that get passed by hidden reference. Be careful with this one, because it isn't compatible with the default 32-bit runtime ๐จ. The only aggregates passed by hidden reference are the ones larger than eight bytes, and this option gives you better compatibility with OpenMP ๐-mcoherent-ldcwโ Uses theldcw/ldcdcoherent cache-control hint ๐ง-mdisable-fpregsโ Disables the floating-point registers. It's equivalent to"-msoft-float"๐-mdisable-indexingโ Stops the compiler from using indexing address modes. This avoids some rather obscure problems when compiling MIG generated code under MACH ๐ค-mfast-indirect-callsโ Generates code that assumes calls never cross space boundaries. That lets GCC emit code that does indirect calls faster โก
This option does not 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 you're compiling kernel code ๐งโ๐ป. You specify a register range as two registers separated by a dash, and you can list several ranges separated by a comma ๐-mgasโ Enables the use of assembler directives that only GAS understands ๐ฆ-mgnu-ldโ Uses options specific to GNU ld. It passes-sharedto ld when building a shared library. This is the default when GCC is configured, explicitly or implicitly, with the GNU linker. This option doesn't affect which ld gets called. It only changes which parameters get passed to that ld ๐. The ld that's called is decided by the--with-ldconfigure option, GCC's program search path, and finally the user's PATH ๐บ๏ธ. You can see which linker GCC uses by runningwhichgcc -print-prog-name=ld``. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*๐-mhp-ldโ Uses options specific to HP ld. It passes-bto ld when building a shared library, and it passes+Accept TypeMismatchto ld on all links. This is the default when GCC is configured, explicitly or implicitly, with the HP linker. Like-mgnu-ld, it doesn't affect which ld gets called, only which parameters get passed to it ๐ซง. The ld that's called is decided by the--with-ldconfigure option, GCC's program search path, and finally the user's PATH. You can print the linker GCC uses withwhichgcc -print-prog-name=ld``. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*๐-mlinker-optโ Turns on the optimization pass in the HP-UX linker. Heads up, though: this makes symbolic debugging impossible ๐ญ-mlong-callsโ okay so this one tells GCC to generate long call sequences โจ, which guarantees a call can always reach linker-generated stubs ๐ง. By default, long calls only show up when the distance from the call site to the start of the function or translation unit (depending on the case) goes past a limit set by the branch type in use. For normal calls those limits are 7,600,000 bytes on PA 2.0 and 240,000 bytes on PA 1.X. Sibcalls are always capped at 240,000 bytes ๐.
Distances get measured from the beginning of functions when you use -ffunction-sections, or when you combine -mgas and -mno-portable-runtime under HP-UX with the SOM linker ๐.
Honestly? It's normally not a vibe to use this one, because it degrades performance ๐ญ. It can still be useful in large applications, especially when partial linking is used to build the app ๐ซถ.
The kind of long calls you get depends on what the assembler and linker can do, plus the type of code being generated. Systems that support long absolute calls, and long PIC symbol-difference or pc-relative calls, should only feel a small impact. BUT an indirect call is used on 32-bit ELF systems in PIC code, and it is quite long ๐.
-mlong-load-storeโ generates 3-instruction load and store sequences, which the HP-UX 10 linker sometimes needs ๐. It's the same thing as the+koption on the HP compilers.-mjump-in-delayโ this one is ignored ๐. It's only here for compatibility purposes.-mno-space-regsโ tells GCC to assume the target has no space registers ๐ธ. That lets GCC generate faster indirect calls and use unscaled index address modes โก. This kind of 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 type cpu-type ๐. The choices are700,7100,7100LC,7200,7300and8000. If you're on an HP-UX system and want to figure out the right scheduling option for your machine, check out/usr/lib/sched.models๐. The default scheduling is8000.-msioโ generates the predefine_SIOfor server IO ๐ฅ๏ธ. The default is-mwsio, which instead generates the predefines__hp9000s700,__hp9000s700__and_WSIOfor workstation IO ๐ป. These options are available under HP-UX and HI-UX.-msoft-floatโ generates output that contains library calls for floating point ๐ข.
Warning: the requisite libraries are NOT available for all HPPA targets ๐จ. Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation, so you need to 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 thexmpyuinstruction.-munix=unix-stdโ generates compiler predefines and selects a startfile for the specified UNIX standard ๐. The choices for unix-std 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 ๐๏ธ.
-munix=93 provides the same predefines as GCC 3.3 and 3.4 ๐ง. -munix=95 gives you extra predefines for XOPEN_UNIX and _XOPEN_SOURCE_EXTENDED, plus the startfile unix95.o. -munix=98 adds predefines for _XOPEN_UNIX, _XOPEN_SOURCE_EXTENDED, _INCLUDE__STDC_A1_SOURCE and _INCLUDE_XOPEN_SOURCE_500, plus the startfile unix98.o โจ.
It is super important to know that this option changes the interfaces for various library routines ๐. It also affects the operational behavior of the C library, so extreme care is needed when using it ๐ซฃ.
Library code that's meant to work with more than one UNIX standard has to test, set and restore the variable __xpg4_extended_mask as appropriate ๐ง . Most GNU software doesn't provide this capability, btw.
-nolibdldโ suppresses the generation of link options that searchlibdld.slwhen-staticis specified on HP-UX 10 and later ๐ซ.-staticโ okay so HP-UX's implementation ofsetlocalein libc depends onlibdld.sl๐งฉ, and there isn't an archive version oflibdld.sl. That means when-staticis specified, special link options are needed to resolve this dependency.
On HP-UX 10 and later, the GCC driver adds the necessary options to link with libdld.sl when -static is specified ๐. This makes the resulting binary dynamic. On the 64-bit port, the linkers generate dynamic binaries by default anyway. If you want to stop the GCC driver from adding these link options, use -nolibdld ๐
โโ๏ธ.
-threadsโ adds support for multithreading with the DCE thread library under HP-UX ๐งต. This option 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 ๐ ๏ธ. This is the default.-mgnu-ld,-mno-gnu-ldโ generates (or doesn't) code for the GNU linker ๐ง. This is the default.-mno-picโ generates code that does not use a global pointer register ๐ซ. 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 immediately before and after volatileasmstatements ๐.-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โ does not 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โ does not 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โ does not generate inline code forsqrt๐ .-mfused-madd,-mno-fused-maddโ does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions ๐งฎ. The default is to use these instructions ๐.-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 preceding the instruction that triggered the stop bit ๐ฐ๏ธ. This can improve instruction scheduling, but it doesn't always do so ๐คทโโ๏ธ.-mfixed-range=register-rangeโ generates code treating the given register range as fixed registers ๐. A fixed register is one that the register allocator cannot use. This is useful when compiling kernel code. A register range is specified as two registers separated by a dash, and you can specify multiple register 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 (i.e. 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 Okay so these two let you flip speculative scheduling for instructions that depend on data speculative loads before reload ๐ฅ. It only does anything if -msched-br-data-spec is turned on too. Default is enabled โจ
-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ Same energy, but this one controls speculative scheduling of those data-speculation-dependent instructions after reload ๐ง. It only works when-msched-ar-data-specis enabled. Default is enabled ๐-msched-in-control-spec,-mno-sched-in-control-specโ Toggles speculative scheduling for instructions that depend on the control speculative loads ๐ฆ. This is only effective with-msched-control-specenabled. Default is enabled ๐-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ When enabled, data-speculative instructions only get picked for scheduling if there's literally nothing else on the table right now ๐. It makes data speculation way more conservative. Default is disabled.-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ Same vibe as above, but for control-speculative instructions ๐. They only get chosen when there are no other options at the moment, so control speculation gets way more cautious. Default is disabled.-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ When enabled, speculative dependencies get counted when computing instruction priorities ๐. It makes speculation a bit more conservative. Default is disabled.-msched-spec-ldcโ Uses a simple data speculation check ๐. On by default.-msched-control-spec-ldcโ Uses a simple check for control speculation ๐ธ. On by default.-msched-stop-bits-after-every-cycleโ Drops a stop bit after every cycle when scheduling โญ. On by default.-msched-fp-mem-deps-zero-costโ Assumes floating-point stores and loads aren't likely to conflict when they land in the same instruction group ๐ซถ. Disabled by default.-msel-sched-dont-check-control-specโ Generates checks for control speculation in selective scheduling ๐ง . Disabled by default.-msched-max-memory-insns=max-insnsโ Sets a limit on how many memory insns can go in one instruction group โจ. Later memory insns trying to squeeze into the same group get lower priority. This is super handy for dodging cache bank conflicts ๐. The default value is1.-msched-max-memory-insns-hard-limitโ Turns the limit from-msched-max-memory-insnsinto a hard limit ๐, so you can't go over that number in an instruction group. Without it, the limit is "soft": non-memory operations get preferred once the limit is hit, but memory operations can still get scheduled anyway ๐ฆ.
๐ธ 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 ๐ง. Heads up bestie:-march=arch-typelets GCC generate code that might not run at all on processors other than the one you named ๐.
Be careful with this one, the code may not run at all on other chips!
The choices for arch-type are:
nativeโ The local processor type, detected by the native compiler ๐ป.loongarch64โ Generic LoongArch 64-bit processor ๐ธ.la464โ LoongArch LA464-based processor with LSX and LASX ๐.la664โ 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 โจ.
More info on the LoongArch ISA versions is over 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, detected by the native compiler ๐ .genericโ Generic LoongArch processor ๐.loongarch64โ Generic LoongArch 64-bit processor ๐.la464โ LoongArch LA464 core โญ.la664โ LoongArch LA664 core ๐ฆ.
-mabi=base-abi-typeโ Generates code for the calling convention you specify ๐ซถ. base-abi-type can be one of:lp64dโ Uses 64-bit general purpose registers and 32/64-bit floating-point registers for parameter passing ๐. The data model is LP64, whereintis 32 bits, whilelong intand pointers are 64 bits.lp64fโ Uses 64-bit general purpose registers and 32-bit floating-point registers for parameter passing ๐ธ. The data model is LP64, whereintis 32 bits, whilelong intand pointers are 64 bits.lp64sโ Uses 64-bit general purpose registers and no floating-point registers for parameter passing ๐. The data model is LP64, whereintis 32 bits, whilelong intand pointers are 64 bits.
-mfpu=fpu-typeโ Generates code for the FPU type you pick, which can be one of ๐ฅ:64โ Allows hardware floating-point instructions for 32-bit and 64-bit operations ๐.32โ Allows hardware floating-point instructions for 32-bit operations ๐ง.noneor0โ Prevents the use of hardware floating-point instructions ๐ซ.
-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 may be generated ๐ .
-msoft-floatโ Forces-mfpu=noneand stops floating-point registers from being used for parameter passing ๐ซง. This can change the target ABI.-msingle-floatโ Forces-mfpu=32and lets you use 32-bit floating-point registers for parameter passing ๐ฆ. This can change the target ABI.-mdouble-floatโ Forces-mfpu=64and lets you use 32/64-bit floating-point registers for parameter passing ๐ . This can change the target ABI.-mlasx,-mno-lasx,-mlsx,-mno-lsxโ These tweak the SIMD extension scope (none / LSX / LASX) the compiler can use for code generation, one step at a time ๐. 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 incremental changes in the order they show up on the GCC driver's command line. From that, they figure out 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โ Traps (or doesn't trap) on integer division by zero ๐. The default is-mcheck-zero-divisionfor-O0or-Og, and-mno-check-zero-divisionfor other optimization levels โจ.-mcond-move-int,-mno-cond-move-intโ Conditional moves for integral data in general-purpose registers get enabled (or disabled) ๐. The default is-mcond-move-int.-mcond-move-float,-mno-cond-move-floatโ Conditional moves for floating-point registers get enabled (or disabled) ๐ฆ. The default is-mcond-move-float.-mmemcpy,-mno-memcpyโ Forces (or doesn't force) the use ofmemcpyfor non-trivial block moves ๐. The default is-mno-memcpy, which lets GCC inline most constant-sized copies. Setting the optimization level to-Osalso forces the use ofmemcpy, but-mno-memcpycan override that if you explicitly set it, no matter what order these 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 tomemcpyor structure copies) that are less than or equal tonbytes ๐ฅ. The default value ofnis1024.-mcmodel=code-modelโ Sets the code model to one of these ๐:tiny-staticโ (Not implemented yet) ๐งtinyโ (Not implemented yet) ๐งnormalโ The text segment must be within 128MB of addressing space ๐ธ. 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 ๐.largeโ (Not implemented yet) ๐งextremeโ This mode doesn't limit the size of the code segment or the data segment ๐.-mcmodel=extremeis incompatible with-fpltand/or-mexplicit-relocs=none.
The-mcmodel=extremeoption clashes with-fpltand/or-mexplicit-relocs=none, so don't pair them! ๐
The default code model is normal ๐.
-mexplicit-relocs=styleโ okay so this one decides when GCC uses assembler relocation operators for symbolic addresses ๐ The other option is assembler macros, which can limit instruction scheduling but still let the linker relax things โจ-mexplicit-relocs=nonemeans the assembler macros are always used.-mexplicit-relocs=alwaysmeans the relocation operators are always used.-mexplicit-relocs=automeans the compiler uses relocation operators wherever linker relaxation is impossible, to improve code quality, and macros everywhere else.- The default is picked from what the assembler could do when GCC was built, plus the setting of
-mrelax. It's-mexplicit-relocs=noneif the assembler doesn't support relocation operators at all,-mexplicit-relocs=alwaysif it supports them but-mrelaxisn't enabled, and-mexplicit-relocs=autoif it supports them and-mrelaxis enabled.
-mexplicit-relocsโ an alias of-mexplicit-relocs=always, kept around for backward compatibility ๐ซถ-mno-explicit-relocsโ an alias of-mexplicit-relocs=none, also just for backward compatibility ๐-mdirect-extern-access,-mno-direct-extern-accessโ these decide whether the GOT gets used to access external symbols ๐ฆ The default is-mno-direct-extern-access, so 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 at all and every external symbol is addressed PC-relatively. This only suits environments where no dynamic linking happens, like firmware, OS kernels, or executables linked with-staticor-static-pie. -mdirect-extern-accessis not compatible with-fPICor-fpic.
- With
Heads up bestie:-mdirect-extern-accessdoesn't work alongside-fPICor-fpic, so don't mix them ๐
-mrelax,-mno-relaxโ take advantage of linker relaxations, or don't ๐ธ If-mpass-mrelax-to-asis enabled, this option also gets passed to the assembler. The default is worked out when GCC is built by checking for assembler support. It's-mrelaxif the assembler supports both the-mrelaxoption and conditional branch relaxation (you actually need that part, because the.aligndirectives and conditional branch instructions in GCC's assembly output can get rejected with a relocation overflow otherwise). It's-mno-relaxotherwise.-mpass-mrelax-to-as,-mno-pass-mrelax-to-asโ pass (or don't pass) the-mrelaxor-mno-relaxoption along to the assembler โจ The default is decided at GCC build-time by checking assembler support:-mpass-mrelax-to-asif the assembler supports the-mrelaxoption, and-mno-pass-mrelax-to-asotherwise. This one is mostly handy for debugging, or for working with assemblers that aren't the one from build-time ๐ง-mrecipโ this turns on 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 divide on floating-point arguments ๐ฅ These instructions only get generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math. It's off by default. Before you use it, you need to make sure the target CPU supportsfrecipeandfrsqrteinstructions. Also note that although the sequence has higher throughput than the non-reciprocal instruction, its precision can drop by up to 2 ulp (for example, the inverse of 1.0 comes out as 0.99999994) ๐ญ-mrecip=optโ this controls which reciprocal estimate instructions may be used ๐optis a comma-separated list, and any item can be preceded by a!to invert it:allโ enable all estimate instructions.defaultโ enable the default instructions, which is the same as-mrecip.noneโ disable all estimate instructions, the same as-mno-recip.divโ enable the approximation for scalar division.vec-divโ enable the approximation for vectorized division.sqrtโ enable the approximation for scalar square root.vec-sqrtโ enable the approximation for vectorized square root.rsqrtโ enable the approximation for scalar reciprocal square root.vec-rsqrtโ enable the approximation for vectorized reciprocal square root.
So, for example, -mrecip=all,!sqrt turns on every reciprocal approximation except scalar square root ๐
-mfrecipe,-mno-frecipeโ use (or don't use) the"frecipe.{s/d}"and"frsqrte.{s/d}"instructions โจ When building with-march=la664, it's enabled by default. The default is-mno-frecipe.-mdiv32,-mno-div32โ use (or don't use) the"div.w[u]"and"mod.w[u]"instructions with input that isn't sign-extended ๐ When building with-march=la664, it's enabled by default. The default is-mno-div32.-mlam-bh,-mno-lam-bhโ use (or don't use) the"am{swap/add}[_db].{b/h}"instructions ๐ When building with-march=la664, it's enabled by default. The default is-mno-lam-bh.-mlamcas,-mno-lamcasโ use (or don't use) the"amcas[_db].{b/h/w/d}"instructions ๐ When building with-march=la664, it's enabled by default. The default is-mno-lamcas.-mld-seq-sa,-mno-ld-seq-saโ this decides whether a same-address load-load barrier ("dbar 0x700") is needed ๐ When building with-march=la664, it's enabled by default. The default is-mno-ld-seq-sa, which means the load-load barrier is needed.-mtls-dialect=optโ controls which TLS dialect gets used for the general dynamic and local dynamic TLS models ๐ฆtradโ use traditional TLS. This is the default.descโ use TLS descriptors.
-mannotate-tablejump,-mno-annotate-tablejumpโ creates an annotation section called".discard.tablejump_annotate"that correlates thejirlinstruction with the jump table, for when a jump table is used to optimize aswitchstatement ๐ Some external tools, like objtool from the Linux kernel build system, need that annotation to analyze control flow. The default is-mno-annotate-tablejump.--param loongarch-vect-unroll-limit=nโ the vectorizer uses available tuning info to decide whether unrolling the main vectorized loop would be worth it, and by how much ๐ This parameter sets the upper bound on how much the vectorizer will unroll that main loop. The default value is six.
โจ M32C Options โจ
-mcpu=nameโ pick the CPU you're generating code 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 the program will run on the simulator ๐ง This links in an alternate runtime library that supports things like file I/O. You must not use this option for programs that will run on real hardware! For that, you need to provide your own runtime library for whatever I/O functions you need ๐-memregs=numberโ sets how many memory-based pseudo-registers GCC uses during code generation ๐ซถ These get used like real registers, so there's a tradeoff between GCC fitting your code into the available registers and the performance cost of using memory instead. Every module in a program must 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โ generate code for the M32R/2 ๐ฆ-m32rxโ generate code for the M32R/X ๐ฆ-m32rโ generate 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 the"ld24"instruction), and that all subroutines are reachable with the"bl"instruction. This is the default ๐- The addressability of a particular object can be set with the
"model"attribute.
- The addressability of a particular object can be set with the
-mmodel=mediumโ assumes objects may be anywhere in the 32-bit address space (the compiler generates"seth/add3"instructions to load their addresses), and that all subroutines are reachable with the"bl"instruction ๐-mmodel=largeโ assumes objects may be anywhere in the 32-bit address space (the compiler generates"seth/add3"instructions to load their addresses), and that subroutines may not be reachable with the"bl"instruction. The compiler then generates the much slower"seth/add3/jl"instruction sequence ๐ข-msdata=noneโ disables the small data area โจ Variables get put into one of".data",".bss", or".rodata"(unless the"section"attribute is specified). This is the default.- The small data area consists of the
".sdata"and".sbss"sections. Objects can be explicitly put in the small data area with the"section"attribute using one of these sections.
- The small data area consists of the
-msdata=sdataโ puts small global and static data in the small data area, but doesn't generate any special code to reference them ๐ง-msdata=useโ puts small global and static data in the small data area and generates special instructions to reference them ๐ฅ-G numโ puts global and static objects less than or equal tonumbytes into the small data or BSS sections, instead of the normal data or BSS sections ๐ The default value ofnumis 8. The-msdataoption must be set tosdataorusefor this option to do anything.- Every module should be compiled with the same
-G numvalue. Compiling with different values ofnummay or may not work. If it doesn't, the linker gives an error message, so incorrect code is never generated ๐ซถ
- Every module should be compiled with the same
-mdebugโ makes the M32R-specific code in the compiler display some statistics that might help you debug your programs ๐-malign-loopsโ aligns all loops to a 32-byte boundary โจ-mno-align-loopsโ doesn't enforce a 32-byte alignment for loops. This is the default ๐-missue-rate=numberโ issuesnumberinstructions per cycle.numbercan only be 1 or 2 โก-mbranch-cost=numberโnumbercan only be 1 or 2. If it's 1, branches are preferred over conditional code. If it's 2, the opposite applies ๐ธ
-mflush-trap=number is where we start, bestie, and it's all about picking which trap number gets used to flush the cache ๐ง. The default is 12, and valid numbers run from 0 to 15 inclusive ๐
.
-mflush-trap=numberโ pick the trap number used to flush the cache ๐ธ. Default is12, and anything from0to15inclusive is valid โจ.-mno-flush-trapโ tells GCC the cache can't be flushed with a trap at all ๐.-mflush-func=nameโ names the operating system function that gets called to flush the cache ๐ฆ. The default is_flush_cache, but the function call only happens if a trap isn't available ๐.-mno-flush-funcโ says there's no OS function for flushing the cache, so don't even look for one ๐ญ.
๐ M680x0 Options ๐
okay so these are the -m options for M680x0 and ColdFire processors ๐. The defaults depend on which architecture got picked when the compiler was configured, so I've listed the defaults for the most common choices below ๐ซถ.
-march=archโ generates code for a specific M680x0 or ColdFire instruction set architecture โจ. For M680x0, the permissible values ofarchare68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures get picked using Freescale's ISA classification, so the options areisaa,isaaplus,isabandisac๐ฅ.
GCC defines a 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, you get code that runs on a family of similar processors but is tuned 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,68332andcpu32๐. The ColdFire cpus are in the table below, which also sorts each CPU into a family ๐ :
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
Okay, the main rule here: -mcpu=cpu overrides -march=arch if arch is compatible with cpu โจ. Any other combos of -mcpu and -march get rejected ๐ญ.
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 only within the limits set by-marchand-mcpu๐. The M680x0 microarchitectures are68000,68010,68020,68030,68040,68060andcpu32โจ. The ColdFire microarchitectures arecfv1,cfv2,cfv3,cfv4andcfv4e๐.
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 also covers 68060 targets ๐ฅ. These two pick the same tuning decisions as -m68020-40 and -m68020-60 respectively ๐.
GCC defines the macros "__mcarch" and "__mcarch__" when it's 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, like with -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in that range ๐.
GCC also defines the macro "__muarch__" when it's 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 ๐ฆ. It's equivalent to-march=68000๐ .
Use this one for microcontrollers with a 68000 or EC000 core, including the 68008, 68302, 68306, 68307, 68322, 68328 and 68356 โจ.
-m68010โ generates output for a 68010 ๐. This is the default when the compiler is configured for 68010-based systems ๐. It's equivalent to-march=68010๐ง.-m68020,-mc68020โ generates output for a 68020 ๐ฅ. This is the default when the compiler is configured for 68020-based systems ๐. It's equivalent to-march=68020๐.-m68030โ generates output for a 68030 ๐. This is the default when the compiler is configured for 68030-based systems ๐. It's equivalent to-march=68030๐ธ.-m68040โ generates output for a 68040 ๐. This is the default when the compiler is configured for 68040-based systems ๐ฆ. It's equivalent to-march=68040๐ .
This option stops the use of 68881/68882 instructions that have to be emulated in software on the 68040 โจ. Use it if your 68040 doesn't have code to emulate those instructions ๐ญ.
-m68060โ generates output for a 68060 ๐. This is the default when the compiler is configured for 68060-based systems ๐. It's equivalent to-march=68060๐ง.
This option stops the use of 68020 and 68881/68882 instructions that have to be emulated in software on the 68060 ๐ฅ. Use it if your 68060 doesn't have code to emulate those instructions ๐.
-mcpu32โ generates output for a CPU32 ๐. This is the default when the compiler is configured for CPU32-based systems ๐. It's equivalent to-march=cpu32๐.
Use this for microcontrollers with a CPU32 or CPU32+ core, including the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360 ๐ธ.
-m5200โ generates output for a 520X ColdFire CPU ๐. This is the default when the compiler is configured for 520X-based systems ๐ฆ. It's equivalent to-mcpu=5206, and it's now deprecated in favor of that option ๐.
Use this for microcontrollers with a 5200 core, including the MCF5202, MCF5203, MCF5204 and MCF5206 โจ.
-m5206eโ generates output for a 5206e ColdFire CPU ๐. It's now deprecated in favor of the equivalent-mcpu=5206e๐ญ.-m528xโ generates output for a member of the ColdFire 528X family ๐ง. It's now deprecated in favor of the equivalent-mcpu=528x๐ซถ.-m5307โ generates output for a ColdFire 5307 CPU ๐ . It's now deprecated in favor of the equivalent-mcpu=5307๐.-m5407โ generates output for a ColdFire 5407 CPU ๐ฅ. It's now deprecated in favor of the equivalent-mcpu=5407๐.-mcfv4eโ generates output for a ColdFire V4e family CPU, like 547x/548x ๐. This includes hardware floating-point instructions ๐. It's equivalent to-mcpu=547x, and it's now deprecated in favor of that option ๐ธ.-m68020-40โ generates output for a 68040 without using any of the new instructions ๐ฆ. This gives code that 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 ๐.
This option is equivalent to -march=68020 -mtune=68020-40 ๐
.
-m68020-60โ generates output for a 68060 without using any of the new instructions ๐. This gives code that 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 ๐.
This option is equivalent to -march=68020 -mtune=68020-60 ๐ฅ.
-mhard-float,-m68881โ generates floating-point instructions ๐. This is the default for 68020 and above, and for ColdFire devices that have 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 have no 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 picked 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โ considers type"int"to be 16 bits wide, like"short int"๐. Also, parameters passed on the stack get aligned to a 16-bit boundary, even on targets whose API says they should be promoted to 32-bit ๐ฅ.-mno-shortโ doesn't consider type"int"to be 16 bits wide ๐. This is the default ๐.-mnobitfield,-mno-bitfieldโ doesn't use the bit-field instructions ๐. The-m68000,-mcpu32and-m5200options imply-mnobitfield๐.-mbitfieldโ does use the bit-field instructions ๐ธ. The-m68020option implies-mbitfield๐. This is the default if you use a configuration designed for a 68020 ๐ฆ.-mrtdโ uses a different function-calling convention โจ. In this one, functions that take a fixed number of arguments return with the"rtd"instruction, which pops their arguments as it returns ๐. That saves one instruction in the caller, since there's no need to pop the arguments there ๐ .
โ ๏ธ 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 ๐.
In addition, seriously incorrect code results if you call a function with too many arguments ๐. (Normally, extra arguments are harmlessly ignored ๐ซถ.)
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 ๐.
โจ MACHINE-SPECIFIC OPTIONS โจ
-malign-int,-mno-align-intโ okay so these decide whether GCC lines upint,long,long long,float,double, andlong doublevariables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐. Aligning to 32 bits makes the code run a bit faster on processors with 32-bit busses, but it eats more memory ๐พ
โ ๏ธ bestie, heads up: if you use -malign-int, GCC lines up structs holding those types differently than most published application binary interface specs for the m68k. Watch out for that one ๐
-mpcrelโ this one tells the 68000 to use its pc-relative addressing mode directly, instead of going through a global offset table ๐ฆ. Right now it implies-fpic, which allows at most a 16-bit offset for pc-relative addressing.-fPICisn't supported with-mpcrelat the moment, though that could change for 68020 and higher processors โจ-mno-strict-align,-mstrict-alignโ-mno-strict-alignmeans GCC does not assume unaligned memory references get handled by the system, and-mstrict-alignmeans it does assume that ๐-msep-dataโ 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. It implies-fPIC.-mno-sep-dataโ generates code that assumes the data segment follows the text segment. This is the default ๐-mid-shared-libraryโ generates code that supports shared libraries through the library ID method ๐ธ This allows execute-in-place and shared libraries in an environment without virtual memory management. It implies-fPIC.-mno-id-shared-libraryโ generates code that doesn't assume ID-based shared libraries are being used. This is the default ๐ซถ-mshared-library-id=nโ specifies the identification number of the ID-based shared library being compiled ๐ Specifying0gives you more compact code. Other values force that number onto the current library, but that's no more space- or time-efficient than just leaving the option out.-mxgot,-mno-xgotโ when generating position-independent code for ColdFire,-mxgotmakes code that works even if the GOT has more than 8192 entries ๐ It's larger and slower, though. On M680x0 processors this option isn't needed, because-fPICis enough โจ
GCC normally uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker throw an error that looks like this:
relocation truncated to fit: R_68K_GOT16O foobar
If you see that, recompile your code with -mxgot. It should then work with very large GOTs ๐ Just know that code made 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've got one of those, 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 ๐
-mlong-jump-table-offsetsโ uses 32-bit offsets inswitchtables. 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 fewer ๐ฅ-mdiv,-mno-divโ uses the divide instruction. It's enabled by default ๐ฆ-mrelax-immediate,-mno-relax-immediateโ 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โ prefers word access when reading byte quantities โญ-mlittle-endian,-mbig-endianโ generates code for a little-endian target ๐-m210,-m340โ generates code for the 210 processor ๐-mno-lsimโ assumes runtime support has been provided, so the simulator library (libsim.a) gets left off the linker command line ๐ซถ-mstack-increment=sizeโ sets the maximum amount for a single stack increment operation โจ Big values can speed up programs with functions that need a lot of stack space, but they can also cause a segmentation fault if the stack gets extended too much ๐ The default value is0x1000.
โจ MicroBlaze Options โจ
-msoft-floatโ uses software emulation for floating point. This is the default ๐ธ-mhard-floatโ uses hardware floating-point instructions ๐ฅ-mmemcpyโ doesn't optimize block moves, and uses"memcpy"instead ๐ฆ-mno-clearbssโ this option is deprecated ๐ Use-fno-zero-initialized-in-bssinstead.-mcpu=cpu-typeโ uses features of, and schedules code for, the given CPU ๐ Supported values are in the formatvX.YY.Z, whereXis a major version,YYis the minor version, andZis compatibility code. Example values arev3.00.a,v4.00.b,v5.00.a,v5.00.b, andv6.00.a๐-mxl-soft-mulโ uses software multiply emulation. This is the default โจ-mxl-soft-divโ uses software emulation for divides. This is the default ๐ง-mxl-barrel-shiftโ uses the hardware barrel shifter ๐-mxl-pattern-compareโ uses pattern compare instructions ๐-msmall-dividesโ uses table lookup optimization for small signed integer divisions ๐-mxl-stack-checkโ this option is deprecated ๐ Use-fstack-checkinstead.-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โ selects the application modelapp-model. Valid models are:executableโ normal executable (default), uses startup codecrt0.o.xmdstubโ for use with the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent called xmdstub ๐ This uses startup filecrt1.oand sets the start address of the program to0x800.bootstrapโ for applications that get loaded using a bootloader ๐ This model uses startup filecrt2.o, which does not contain a processor reset vector handler. It's suited to handing control over to the bootloader on a processor reset instead of the application.novectorsโ for applications that don't need any of the MicroBlaze vectors ๐ง This option may be handy for apps running inside a monitoring application. This model usescrt3.oas a startup file.
Option -xl-mode-app-model is a deprecated alias for -mxl-mode-app-model ๐
-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 through the GOT, since PC-relative addressing isn't supported.
๐ MIPS Options ๐
-EBโ generates big-endian code ๐-ELโ 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 aremips1,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, xlr and xlp
The special value from-abi picks the most compatible architecture for the selected ABI. That means mips1 for 32-bit ABIs and mips3 for 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, so -march=r2k works ๐
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" โจ
Note that the "_MIPS_ARCH" macro uses the processor names given above. In other words, it has the full prefix and doesn't abbreviate 000 as k ๐ซถ In the case of from-abi, the macro names the resolved architecture (either "mips1" or "mips3"). It names the default architecture when no -march option is given ๐
-mtune=archโ okay so this one tunes the code for a specific chip โจ arch can be any of the same values-marchtakes. It changes things like how instructions get scheduled and how expensive the math ops look to the compiler ๐ If you skip it, GCC tunes for whatever-marchpicked. Using-marchand-mtunetogether is iconic: your code runs on a whole family of processors, but gets polished for one specific member ๐ฆ With-mtune, GCC also defines the macros"_MIPS_TUNE"and"_MIPS_TUNE_foo", which work the same way as the-marchones.-mips1โ same as-march=mips1๐-mips2โ same as-march=mips2๐-mips3โ same as-march=mips3๐-mips4โ same as-march=mips4๐-mips32โ same as-march=mips32๐-mips32r3โ same as-march=mips32r3๐-mips32r5โ same as-march=mips32r5๐-mips32r6โ same as-march=mips32r6๐-mips64โ same as-march=mips64๐-mips64r2โ same as-march=mips64r2๐-mips64r3โ same as-march=mips64r3๐-mips64r5โ same as-march=mips64r5๐-mips64r6โ same as-march=mips64r6๐-mips16,-mno-mips16โ okay so-mips16makes GCC generate MIPS16 code and-mno-mips16says nope, don't ๐ โโ๏ธ If you're targeting MIPS32 or MIPS64, GCC uses the MIPS16e ASE to get it done ๐ You can also flip MIPS16 on or off for a single function with the"mips16"and"nomips16"attributes, which is giving main character energy ๐-mmips16e2,-mno-mips16e2โ-mmips16e2tells GCC to use the MIPS16e2 ASE, and-mno-mips16e2says don't. This option changes what-mips16targets, so it aims at the MIPS16e2 ASE instead ๐ง-mflip-mips16โ this one makes GCC generate MIPS16 code on every other function ๐ It exists purely for regression testing of mixed MIPS16 and non-MIPS16 code generation. It is not meant for normal code you're actually shipping, so please don't use it for your everyday projects ๐-minterlink-compressed,-mno-interlink-compressedโ-minterlink-compressedrequires that code using the standard (uncompressed) MIPS ISA be link-compatible with MIPS16 and microMIPS code, and vice versa.-mno-interlink-compressedmeans you don't need that guarantee ๐ธ
For example, standard ISA code can't jump straight into MIPS16 or microMIPS code. It has to use a call or an indirect jump instead. So -minterlink-compressed turns off direct jumps unless GCC knows the jump target isn't compressed ๐ญ
-minterlink-mips16,-mno-interlink-mips16โ these are just aliases of-minterlink-compressedand-mno-interlink-compressed. They're older than the microMIPS ASE and only stick around so old builds don't break ๐ซถ-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generates code for the ABI you pick โจ
Heads up that EABI comes in a 32-bit and a 64-bit flavor. GCC usually goes 64-bit when you pick a 64-bit architecture, but if you want 32-bit code anyway, use -mgp32 ๐ฆ
For info on the O64 ABI, check out <https://gcc.gnu.org/projects/mipso64-abi.html> ๐
GCC also supports a version of the o32 ABI where floating-point registers are 64 bits wide instead of 32. Pick that combo with -mabi=32 -mfp64 ๐ฅ This one leans on the "mthc1" and "mfhc1" instructions, so it only works on MIPS32R2, MIPS32R3, and MIPS32R5 processors ๐
The register assignments for arguments and return values stay the same, but each scalar value gets passed in one 64-bit register instead of a pair of 32-bit ones. For example, scalar floating-point values come back in $f0 alone, not a $f0/$f1 pair. The call-saved registers stay the same too, meaning the even-numbered double-precision registers get saved ๐
There are two more o32 variants for moving from 32-bit to 64-bit registers: FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg). FPXX means all code has to run correctly with either 32-bit or 64-bit registers. It can link with FP32 or FP64, but not both at once ๐ง FP64A is like FP64 but it bans odd-numbered single-precision registers. Pair it with the "FRE" mode of FPUs on MIPS32R5 processors and FP32 and FP64A code can link together and run in the same process without switching FPU modes โจ
-mabicalls,-mno-abicallsโ-mabicallsgenerates code suitable for SVR4-style dynamic objects, and-mno-abicallsskips that.-mabicallsis the default on SVR4-based systems ๐ธ-mshared,-mno-sharedโ-msharedgenerates fully position-independent code that can be linked into shared libraries, and-mno-shareddoesn't. This only affects-mabicalls๐
Historically, all -mabicalls code was position-independent no matter what you set for -fPIC or -fpic. But the GNU toolchain has an extension where executables can use absolute accesses for locally-binding symbols. It can also use shorter GP initialization sequences and make direct calls to locally-defined functions. You turn this mode on with -mno-shared ๐ซถ
-mno-shared needs binutils 2.16 or higher, and it generates objects that only the GNU linker can link ๐ญ It doesn't change the ABI of the final executable, only the ABI of relocatable objects. Using -mno-shared usually makes executables smaller and quicker ๐ฅ
-mshared is the default โจ
-mplt,-mno-pltโ-mpltassumes the static and dynamic linkers support PLTs and copy relocations, and-mno-pltdoesn't assume that ๐ฆ This only matters with-mno-shared -mabicalls. For the n64 ABI, it does 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โ-mxgotlifts the usual size limits on the global offset table, and-mno-xgotkeeps them ๐
Normally GCC uses one instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger and the linker throws an error like this:
relocation truncated to fit: R_MIPS_GOT16 foobar
If you see that, recompile your code with -mxgot ๐ฅบ It handles really huge GOTs, but the code is a bit less efficient, since fetching a global symbol's value takes three instructions instead of one.
Some linkers can create multiple GOTs. If yours does, you usually only need -mxgot when a single object file touches more than 64k's worth of GOT entries. Very few linkers are like that ๐ค
These options do nothing unless GCC is generating position-independent code ๐
-mgp32โ assumes general-purpose registers are 32 bits wide ๐-mgp64โ assumes general-purpose registers are 64 bits wide ๐-mfp32โ assumes floating-point registers are 32 bits wide ๐ท-mfp64โ assumes floating-point registers are 64 bits wide ๐ท-mfpxxโ doesn't assume any particular width for floating-point registers ๐ฆ-mhard-floatโ uses floating-point coprocessor instructions ๐ฅ-msoft-floatโ doesn't use floating-point coprocessor instructions. Instead, floating-point math gets done with library calls ๐-mno-floatโ this is-msoft-floatplus a promise that your program never does any floating-point operations at all ๐ โโ๏ธ Right now it only works on some bare-metal MIPS configs, where it might pick a special set of libraries with zero floating-point support, including things like the floating-point"printf"formats. If code built with-mno-floataccidentally has floating-point ops in it, expect a link-time or run-time failure ๐-msingle-floatโ assumes the floating-point coprocessor only supports single-precision operations ๐ธ-mdouble-floatโ assumes the floating-point coprocessor supports double-precision operations. This is the default ๐-modd-spreg,-mno-odd-spregโ-modd-spreglets GCC use odd-numbered single-precision floating-point registers for the o32 ABI, and-mno-odd-spregstops it ๐ง It's the default for processors 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 special not-a-number (NaN) IEEE 754 floating-point data is handled by the"abs.fmt"and"neg.fmt"machine instructions ๐ฅ
By default, or when you use -mabs=legacy, you get the legacy treatment. In that case these instructions count as arithmetic, so they get avoided wherever correct operation matters and the input might be a NaN. GCC uses a longer sequence that manipulates the sign bit by hand instead, unless -ffinite-math-only is also specified ๐ญ
-mabs=2008 selects the IEEE 754-2008 treatment. Here these instructions count as non-arithmetic, so they work correctly in every case, especially when the input is a NaN. They're always used for the matching operations ๐
-mnan=2008,-mnan=legacyโ these control how special not-a-number (NaN) IEEE 754 floating-point data gets encoded ๐
-mnan=legacy picks the legacy encoding. Quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, and signaling NaNs (sNaNs) by that bit being 1 ๐
-mnan=2008 picks the IEEE 754-2008 encoding. Now 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โ-mllscusesll,sc, andsyncinstructions to implement atomic memory built-in functions, and-mno-llscdoesn't ๐ฆ If you specify neither, GCC uses those instructions as long as the target architecture supports them ๐ธ
Okay so the -mllsc vibe continues: -mllsc is clutch if the runtime can emulate the instructions, and -mno-llsc can be super useful when you're compiling for nonstandard ISAs ๐
. You can make either one the default by configuring GCC with --with-llsc or --without-llsc. Heads up, --with-llsc is already the default for some configurations, so peek at the installation docs for the tea โจ
-mdsp,-mno-dspโ Use (or don't use) revision 1 of the MIPS DSP ASE ๐. Turning it on defines the preprocessor macro"__mips_dsp"and sets"__mips_dsp_rev"to 1.-mdspr2,-mno-dspr2โ Use (or skip) revision 2 of the MIPS DSP ASE ๐. This one defines both"__mips_dsp"and"__mips_dspr2", and sets"__mips_dsp_rev"to 2.-msmartmips,-mno-smartmipsโ Use (or skip) the MIPS SmartMIPS ASE ๐ฆ.-mpaired-single,-mno-paired-singleโ Use (or skip) paired-single floating-point instructions ๐ธ. This one needs hardware floating-point support to be enabled, so make sure that's on first.-mdmx,-mno-mdmxโ Use (or skip) MIPS Digital Media Extension instructions ๐. These only work when you're generating 64-bit code, and they also need hardware floating-point support enabled.-mips3d,-mno-mips3dโ Use (or skip) the MIPS-3D ASE โญ. Heads up,-mips3dimplies-mpaired-single, so it comes along for the ride.-mmicromips,-mno-micromipsโ Generate (or don't generate) microMIPS code ๐ง.
You can also control microMIPS code generation on a per-function basis with the "micromips" and "nomicromips" attributes. Main character energy ๐.
-mmt,-mno-mtโ Use (or skip) MT Multithreading instructions ๐งต.-mmcu,-mno-mcuโ Use (or skip) the MIPS MCU ASE instructions ๐.-meva,-mno-evaโ Use (or skip) the MIPS Enhanced Virtual Addressing instructions ๐ฅ.-mvirt,-mno-virtโ Use (or skip) the MIPS Virtualization (VZ) instructions ๐ธ.-mxpa,-mno-xpaโ Use (or skip) the MIPS eXtended Physical Address (XPA) instructions โจ.-mcrc,-mno-crcโ Use (or skip) the MIPS Cyclic Redundancy Check (CRC) instructions ๐.-mginv,-mno-ginvโ Use (or skip) the MIPS Global INValidate (GINV) instructions ๐ซถ.-mloongson-mmi,-mno-loongson-mmiโ Use (or skip) the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐.-mloongson-ext,-mno-loongson-extโ Use (or skip) the MIPS Loongson EXTensions (EXT) instructions ๐ฆ.-mloongson-ext2,-mno-loongson-ext2โ Use (or skip) the MIPS Loongson EXTensions r2 (EXT2) instructions ๐.-mlong64โ Force"long"types to be 64 bits wide ๐. For the scoop on the default and how the pointer size gets decided, check out-mlong32below.-mlong32โ Force"long","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 "int"s. The n64 ABI uses 64-bit "long"s, and so does the 64-bit EABI; the others use 32-bit "long"s. Pointers are the same size as "long"s, or the same size as integer registers, whichever is smaller.
-msym32,-mno-sym32โ Assume (or don't assume) that all symbols have 32-bit values, no matter which ABI you picked ๐ฅ. This is super handy alongside-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 thannumbytes โจ. GCC can then generate more efficient accesses to the data; see-mgpoptfor the details.
The default -G option depends on the configuration ๐ซถ.
-mlocal-sdata,-mno-local-sdataโ Extend (or don't extend) the-Gbehavior to local data too, like static variables in C ๐ .-mlocal-sdatais the default for all configurations.
If the linker complains that an application is using too much small data, try rebuilding the less performance-critical parts with -mno-local-sdata ๐ญ. You might also want to build large libraries with -mno-local-sdata, so the libraries leave more room for the main program.
-mextern-sdata,-mno-extern-sdataโ Assume (or don't assume) that externally-defined data is in a small data section, as long as its size is within the-Glimit ๐.-mextern-sdatais the default for all configurations.
If you compile a module Mod with -mextern-sdata -G num -mgpopt, and Mod references a variable Var that is no bigger than num bytes, you must make sure that Var is placed in a small data section ๐. If Var is defined by another module, you must either compile that module with a high-enough -G setting or attach a "section" attribute to Var's definition. If Var is common, you must link the application with a high-enough -G setting.
The easiest way to satisfy all of this is to compile and link every module with the same -G option ๐. However, if you want to build a library that supports several different small data limits, compile the library with the highest supported -G setting and also use -mno-extern-sdata to stop the library from making assumptions about externally-defined data ๐ง.
-mgpopt,-mno-gpoptโ Use (or don't use) GP-relative accesses for symbols that are known to be in a small data section; see-G,-mlocal-sdataand-mextern-sdata๐ฆ.-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โ Allocate variables to the read-only data section first if possible, then to the small data section if possible, and otherwise to data ๐ธ. This gives slightly slower code than the default, but it reduces the amount of RAM needed while executing, so it might be your bestie for some embedded systems.-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ Put uninitialized"const"variables in the read-only data section โจ. This only means something when you're also using-membedded-data.-mcode-readable=settingโ Tell GCC whether it's allowed to generate code that reads from executable sections ๐ . There are three possible settings, and they're all very different vibes:-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 do so ๐. 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 with a dual instruction/data SRAM interface that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM.
-msplit-addresses,-mno-split-addressesโ Enable (or disable) use of the%hi()and%lo()assembler relocation operators ๐ง. This option has been superseded by-mexplicit-relocsbut is 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 when GCC itself was built.
The "base" explicit-relocs support got introduced into GAS in 2001 ๐. The "pcrel" explicit-relocs support got introduced into GAS in 2014, and it supports %pcrel_hi and %pcrel_lo โจ.
-mcheck-zero-division,-mno-check-zero-divisionโ Trap (or don'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 a break instruction ๐ซถ. Traps give you smaller code, but they're 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 with --with-divide=breaks ๐
. Divide-by-zero checks can be completely disabled with -mno-check-zero-division.
-mload-store-pairs,-mno-load-store-pairsโ Enable (or disable) an optimization that pairs consecutive load or store instructions so they can do load/store bonding ๐. This is enabled 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โ Disable (or enable) direct unaligned access for MIPS Release 6 ๐. MIPSr6 requires load/store unaligned-access support, either by hardware or by trap&emulate, so-mstrict-alignmay be needed by the kernel.
Heads up bestie: the options-munaligned-accessand-mno-unaligned-accessare obsoleted, and they're only kept for backward compatibility ๐.
-mmemcpy,-mno-memcpyโ Force (or don'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โ Disable (or don't disable) use of the"jal"instruction ๐ง. Calling functions with"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โ Enable (or disable) use of the"mad","madu", and"mul"instructions, as provided by the R4650 ISA ๐.
Okay so bestie, we're still deep in the MIPS flags ๐ฆ and these ones are a whole mood ๐
-mimadd,-mno-imaddโ Turns themaddandmsubinteger instructions on (or off) ๐ฅ Default is-mimaddon architectures that havemaddandmsub, EXCEPT the 74k, where it was found to generate slower code ๐-mfused-madd,-mno-fused-maddโ Same idea but for the floating-point multiply-accumulate instructions, when they're actually available โจ Default is-mfused-madd.
๐ On the R8000, when multiply-accumulate instructions get used, the intermediate product is calculated to infinite precision and is NOT subject to the FCSR Flush to Zero bit. This might be undesirable in some circumstances, so keep that in your back pocket ๐
On other processors, the result is numerically identical to doing the same computation with separate multiply, add, subtract and negate instructions ๐ซถ
-nocppโ Tells the MIPS assembler to NOT run its preprocessor over user assembler files (the ones with a.ssuffix) when it assembles them ๐ง-mfix-24k,-mno-fix-24kโ Works around the 24K E48 errata (lost data on stores during refill) ๐ญ The workarounds are handled by the assembler, not by GCC itself.-mfix-r4000,-mno-fix-r4000โ Works around certain R4000 CPU errata ๐ธ- A double-word or a variable shift may give an incorrect result if it's executed immediately after starting an integer division.
- A double-word or a variable shift may give an incorrect result if it's executed while an integer multiplication is in progress.
- An integer division may give an incorrect result if it's 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 it's executed immediately after starting an integer division.
-mfix-r10000,-mno-fix-r10000โ Works around certain R10000 errata ๐ll/scsequences 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, and -mno-fix-r10000 is the default otherwise.
-mfix-r5900,-mno-fix-r5900โ Basically says "don't try to schedule the preceding instruction into the delay slot of a branch" when that branch sits at the end of a short loop of six instructions or fewer ๐ โโ๏ธ Instead, it always schedules anopinstruction there. The short loop bug can make loops only run once or twice thanks to a hardware bug in the R5900 chip ๐ The workaround is handled by the assembler, not GCC.-mfix-rm7000,-mno-fix-rm7000โ Works around the RM7000dmult/dmultuerrata โจ The workarounds are implemented by the assembler rather than by GCC.-mfix-vr4120,-mno-fix-vr4120โ Works around certain VR4120 errata ๐ฆdmultudoes not always produce the correct result.divandddivdo 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 the moment, those functions are only provided by the mips64vr*-elf configurations.
Other VR4120 errata need a NOP inserted between certain pairs of instructions, and those get handled by the assembler, not by GCC itself ๐
-mfix-vr4130โ Works around the VR4130mflo/mfhierrata ๐ง The workarounds are implemented by the assembler rather than by GCC, although GCC avoids usingmfloandmfhiif the VR4130macc,macchi,dmaccanddmacchiinstructions are available instead.-mfix-sb1,-mno-fix-sb1โ Works around certain SB-1 CPU core errata ๐ (This flag currently works around the SB-1 revision 2"F1"and"F2"floating-point errata.)-mr10k-cache-barrier=setting โ Lets you specify whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors ๐ฅ
Okay so the R10K is kinda chaotic ๐ญ Like many processors, it tries to predict the outcome of a conditional branch and speculatively runs instructions from the "taken" branch. Then it aborts them if the prediction was wrong. BUT on the R10K, even aborted instructions can leave side effects behind, which is giving unreliable vibes ๐
This problem only affects kernel stores and, depending on the system, kernel loads. For example, a speculatively-executed store might load the target memory into cache and mark the cache line as dirty, even if the store itself gets aborted later. If a DMA operation writes to the same area of memory before that "dirty" line is flushed, the cached data overwrites the DMA-ed data ๐ฑ For a full description (plus other potential problems), check the R10K processor manual.
One workaround is to insert cache barrier instructions before every memory access that might be speculatively executed AND might have side effects even if aborted. -mr10k-cache-barrier=setting controls how GCC implements this workaround. It assumes that aborted accesses to any byte in the following regions do NOT have 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 the input program contains a function declaration like this:
void foo (void);
then the implementation of foo must allow j foo and jal foo to be executed speculatively. GCC honors this restriction for functions it compiles itself. It expects non-GCC functions (like hand-written assembly code) 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 might have side effects even if aborted.-mr10k-cache-barrier=storeโ Inserts a cache barrier before a store that might be speculatively executed AND 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โ Specifies the function to call to flush the I and D caches, or tells GCC to not call any such function ๐ง If it does get called, the function must take the same arguments as the common_flush_func: the address of the memory range being flushed, the size of that memory 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 roughly num "simple" instructions ๐ This cost is only a heuristic, and it's NOT 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 use of Branch Likely instructions, no matter the default for the selected architecture ๐ฆ By default, Branch Likely instructions may be generated if the selected architecture supports them. The exception is the MIPS32 and MIPS64 architectures (and processors that implement those architectures). For those, Branch Likely instructions are not generated by default, because those architectures 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=nevermakes sure compact branch instructions are NEVER generated.-mcompact-branches=alwaysmakes sure a compact branch instruction gets 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 gets used instead.- If it's used for MIPS16/microMIPS targets, it will just be ignored for now. The behaviour for MIPS16/microMIPS may change in the future, since they do have some compact branch instructions ๐
-mcompact-branches=optimalcauses a delay slot branch to be used 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 gets chosen if one is available โจ
-mfp-exceptions,-mno-fp-exceptionsโ Specifies whether FP exceptions are enabled ๐ This affects how FP instructions get scheduled for some processors. The default is that 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 enabled, GCC aligns pairs of instructions that it thinks should execute in parallel.
This option only has an effect when optimizing for the VR4130. It normally makes code faster, but at the expense 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 it ๐ง Thesynciinstructions (if enabled) get generated when__builtin___clear_cacheis compiled.
This option defaults to -mno-synci, but the default can be overridden by configuring GCC with --with-synci.
When compiling code for single processor systems, it's generally safe to use synci. However, on many multi-core (SMP) systems, it does NOT invalidate the instruction caches on all cores and may lead to undefined behaviour ๐ญ
-mrelax-pic-calls,-mno-relax-pic-callsโ Tries to turn PIC calls that are normally dispatched via register$25into direct calls ๐ This is only possible if the linker can resolve the destination at link time AND the destination is within range for a direct call.
Okay so, the -mrelax-pic-calls thing is the default if GCC was set up with an assembler and linker that support the .reloc assembly directive, and -mexplicit-relocs is in effect. ๐ง With -mno-explicit-relocs, the assembler and linker can do this optimization all by themselves, no help from the compiler needed โจ
-mmcount-ra-address,-mno-mcount-ra-addressโ okay this one is lowkey wild ๐ญ It tells GCC to emit (or not emit) code that lets_mcountchange the return address of the calling function. When it's on, the usual_mcountinterface gets a brand new ra-address parameter. It's of typeintptr_t *and gets passed in register$12. So_mcountcan rewrite the return address by doing both of these:- Returning the new address in register
$31. - Storing the new address in
*ra-address, but only if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address ๐
-mframe-header-opt,-mno-frame-header-optโ this turns frame header optimization on (or off) in the o32 ABI ๐ Here's the tea: when you're using o32, calling functions reserve 16 bytes on the stack so the called function has somewhere to write out its register arguments. With this on, GCC skips that frame header allocation if it can tell it's never used. Literally free bytes ๐ซถ
This optimization is off by default at all optimization levels.
-mlxc1-sxc1,-mno-lxc1-sxc1โ when it applies, this enables (or disables) the generation oflwxc1,swxc1,ldxc1andsdxc1instructions. It's on by default ๐ธ-mmadd4,-mno-madd4โ same energy here: when it applies, this enables (or disables) the 4-operandmadd.s,madd.dand related instructions. Also on by default โจ
๐ MMIX Options ๐
Okay bestie, these options are defined for the MMIX ๐ง
-mlibfuncs,-mno-libfuncsโ specifies that intrinsic library functions are being compiled, so ALL values get passed in registers, no matter how big they are ๐-mepsilon,-mno-epsilonโ generates floating-point comparison instructions that compare with respect to therEepsilon register ๐ฅ-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code where function parameters and return values are seen as registers$0and up (from the called function's point of view).-mabi=gnuis 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, this decides whether you get zero-extending load instructions (with-mzero-extend) or sign-extending ones by default.-mno-zero-extendmeans you do not use zero-extending loads ๐-mknuthdiv,-mno-knuthdivโ this one's about division with a remainder. With-mknuthdiv, the result's remainder has 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 that the mmix simulator uses ๐-mbranch-predict,-mno-branch-predictโ uses (or doesn't use) the probable-branch instructions, when static branch prediction says a branch is probable โญ-mbase-addresses,-mno-base-addressesโ generates (or doesn't generate) code that uses base addresses. Using a base address automatically makes a request (handled by the assembler and the linker) for a constant to be set up in a global register. That register gets used for one or more base address requests within the range 0 to 255 from the value held in the register. This generally leads to short and fast code, BUT the number of different data items you can address is limited. So if your program has lots of static data, you may need-mno-base-addresses๐ฅบ-msingle-exit,-mno-single-exitโ forces (or doesn't force) generated code to have a single exit point in each function ๐
๐ฆ MN10300 Options ๐ฆ
These -m options are defined for Matsushita MN10300 architectures ๐ธ
-mmult-bugโ generates code to avoid bugs in the multiply instructions for the MN10300 processors. This is the default ๐-mno-mult-bugโ does NOT generate that multiply-bug workaround code for the MN10300 processors ๐-mam33โ generates code using features specific to the AM33 processor โจ-mno-am33โ does not generate code using AM33-specific features. This is the default ๐-mam33-2โ generates code using features specific to the AM33/2.0 processor ๐ฅ-mam34โ generates code using features specific to the AM34 processor ๐-mtune=cpu-typeโ uses the timing characteristics of the CPU type you give when scheduling instructions. It does NOT change the targeted processor type, so don't get confused ๐ซถ The CPU type has to be one ofmn10300,am33,am33-2oram34.-mreturn-pointer-on-d0โ when generating a function that returns a pointer, the pointer gets returned in botha0andd0. Otherwise, it's only returned ina0, and trying to call those functions without a prototype gives you errors ๐ญ Heads up: this option is on by default! Use-mno-return-pointer-on-d0to turn it off.-mno-crt0โ does 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 does anything when you use it on the command line for the final link step ๐
This option makes symbolic debugging impossible. Be careful, bestie ๐
-mliwโ lets the compiler generate Long Instruction Word instructions if the target is AM33 or later. This is the default. This option defines the preprocessor macro__LIW__๐-mno-liwโ does not let the compiler generate Long Instruction Word instructions. This option defines the preprocessor macro__NO_LIW__๐-msetlbโ lets the compiler generate the SETLB and Lcc instructions if the target is AM33 or later. This is the default. This option defines the preprocessor macro__SETLB__โญ-mno-setlbโ does not let the compiler generate SETLB or Lcc instructions. This option defines 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โ generatesmul.xandumul.xinstructions. This is the default formoxiebox-*-*configurations โจ-mno-crt0โ does 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 those constants are signed decimals, but this option exists for testsuite and/or aesthetic purposes ๐ฆ-mmcu=โ selects the MCU to target ๐ง This creates a C preprocessor symbol based on the MCU name, converted to upper case and pre- and post-fixed with__. That symbol is then used by themsp430.hheader file to pick an MCU-specific supplementary header file, so it's giving organized ๐
This option also sets the ISA to use. If the MCU name is one that's known to only support the 430 ISA, then that one gets selected. Otherwise the 430X ISA is selected. A generic MCU name of msp430 can also be used to 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 appended. So specifying -mmcu=xxx on the gcc command line defines the C preprocessor symbol __XXX__ and makes the linker search for a script called xxx.ld ๐ซถ
The ISA and hardware multiply support for the different MCUs is hard-coded into GCC. BUT an external devices.csv file can be used to extend device support beyond those hard-coded ones ๐
GCC searches for devices.csv using the methods below, in the given precedence order. The first method beats the second, and the second beats the third ๐
- Include path specified with
-Iand-Lโdevices.csvis searched for in each of the directories specified by include paths and linker library search paths. - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIRโ define the value of the global environment variableMSP430_GCC_INCLUDE_DIRas the full path to the directory containingdevices.csv, and GCC will search that directory fordevices.csv. Ifdevices.csvis found there, that directory is also registered as an include path and linker library path. Header files and linker scripts in this directory can therefore be used without manually specifying-Iand-Lon the command line ๐ - The
msp430-elf{,bare}/include/devicesdirectory โ finally, GCC examinesmsp430-elf{,bare}/include/devicesfrom the toolchain root directory. This directory does NOT exist in a default installation, but if you've created it and copieddevices.csvthere, then the MCU data gets read. Just like above, 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 is used ๐
-mwarn-mcu,-mno-warn-mcuโ enables (or disables) warnings about conflicts between the MCU name given by-mmcu=and the ISA set by-mcpuand/or the hardware multiply support set by-mhwmult. It also toggles warnings about unrecognized MCU names. This option is on by default โญ-mcpu=โ specifies the ISA to use. Accepted values aremsp430,msp430xandmsp430xv2. This option is deprecated, so use the-mmcu=option to select the ISA instead ๐ฅบ-msimโ links to the simulator runtime libraries and linker script. This overrides any scripts that would be selected by the-mmcu=option ๐-mlargeโ uses large-model addressing (20-bit pointers, 20-bitsize_t) ๐ธ-msmallโ uses small-model addressing (16-bit pointers, 16-bitsize_t) ๐ฆ-mrelaxโ this one gets passed to the assembler and linker, and lets the linker do certain optimizations that can't happen until the final link โจ
โจ MSP430 Options, continued โจ
-mhwmult=โ ๐ This picks which kind of hardware multiply your MSP430 chip has. Your choices arenone(no hardware multiply at all),16bit(the original 16-bit-only multiply from the early MCUs),32bit(the 16/32-bit multiply on the later MCUs), andf5series(the 16/32-bit multiply on the F5-series MCUs). You can also sayauto, which tells GCC to figure it out from the MCU name you gave-mmcu. If you skip-mmcuor the MCU name isn't recognised, GCC assumes no hardware multiply.autois the default, so you don't have to touch it unless you want to ๐ฅ
Hardware multiplies usually happen through a library routine, which saves space in your code. But when you compile at -O3 or higher, the hardware multiplier gets invoked inline instead. That makes your code bigger but faster, so it's a trade-off, bestie ๐ง
The hardware multiply routines turn off interrupts while they run and then restore the previous interrupt state when they're done. So they're totally safe to use inside interrupt handlers as well as in regular code โจ
-minrtโ ๐ธ Turns on a minimum runtime environment, so there are no static initializers or constructors. It's made for memory-constrained devices. The compiler slips special symbols into some objects so the linker and runtime know which code fragments they need ๐ซถ-mtiny-printfโ ๐ Gives you slimmed-downprintfandputslibrary functions, which are much smaller. Heads up though: these tiny versions are not reentrant, so be careful with them in multi-threaded apps ๐ญ
Streams are gone with this option. The string you want printed is always sent to stdout through the write syscall, and it isn't buffered before it goes to write. This option needs Newlib Nano IO, so GCC has to be configured with --enable-newlib-nano-formatted-io ๐
-mmax-inline-shift=โ ๐ฆ This takes an integer from 0 to 64 inclusive and sets how many inline shift instructions can be emitted for a shift by a constant amount. Once that limit would be exceeded, an mspabi helper function is used instead. The default is4โจ
This only matters when a shift by several positions can't be done with a single instruction (for example, all shifts greater than 1 on the 430 ISA) ๐
Shifts of a 32-bit value are at least twice as expensive, so the number you pass here gets divided by 2, and that resulting value is what's actually used ๐
-mcode-region=and-mdata-region=โ ๐ These tell the compiler where to put functions and data that don't have alower,upper,eitherorsectionattribute. The options arelower,upper,eitherorany. The first three act like the matching attribute.anyis the default, and it leaves placement entirely up to the linker script and how it maps the standard sections (.text,.data, etc.) onto the memory regions ๐-msilicon-errata=โ ๐ฅ Passes a request on to the assembler to turn on the fixes for the named silicon errata ๐-msilicon-errata-warn=โ โญ Passes a request on to the assembler to turn on warning messages for when a silicon erratum might need a fix applied ๐-mwarn-devices-csvand-mno-warn-devices-csvโ ๐ Warns you ifdevices.csvcan't be found or if there's a problem parsing it. This is on by default โจ
๐ท NDS32 Options ๐ท
These options are defined for NDS32 implementations ๐ฆ
-mbig-endianโ ๐ Generates code in big-endian mode ๐ธ-mlittle-endianโ ๐ธ Generates code in little-endian mode ๐-mreduced-regsโ ๐ Uses the reduced-set registers for register allocation ๐ง-mfull-regsโ ๐ Uses the full-set registers for register allocation โจ-mcmovโ ๐ฅ Generates conditional move instructions ๐-mno-cmovโ ๐ Does not generate conditional move instructions ๐ญ-mext-perfโ โญ Generates performance extension instructions ๐ฅ-mno-ext-perfโ ๐ Does not generate performance extension instructions ๐ซถ-mext-perf2โ ๐ Generates performance extension 2 instructions ๐-mno-ext-perf2โ ๐ Does not generate performance extension 2 instructions ๐-mext-stringโ ๐ฆ Generates string extension instructions ๐-mno-ext-stringโ ๐ญ Does not generate string extension instructions ๐ธ-mv3pushโ ๐ง Generates v3push25andpop25instructions ๐-mno-v3pushโ ๐ Does not generate v3push25andpop25instructions ๐-m16-bitโ โจ Generates 16-bit instructions ๐-mno-16-bitโ ๐ Does not generate 16-bit instructions ๐-misr-vector-size=numโ ๐ Sets the size of each interrupt vector, which must be4or16๐ฅ-mcache-block-size=numโ ๐ Sets the size of each cache block, which must be a power of 2 between4and512๐ฆ-march=archโ ๐ Sets the name of the target architecture ๐-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 of addressing space. The text segment must be within 16MB of addressing space ๐ซถmediumโ ๐ The data segment must be within 512KB, while the read-only data segment can be within 4GB of addressing space. The text segment should still be within 16MB of addressing space ๐largeโ ๐ All the text and data segments can be within 4GB of addressing space โจ
-mctor-dtorโ โญ Enables the constructor/destructor feature ๐ฅ-mrelaxโ ๐ Guides the linker to relax instructions ๐ฆ
๐ Nvidia PTX Options ๐
These options are defined for Nvidia PTX ๐
-m64โ ๐ Ignored, but kept around for backward compatibility. Only the 64-bit ABI is supported ๐ซถ-march=architecture-stringโ ๐ฅ Generates code for the PTX ISA target architecture you specify. 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 was configured, so check--with-arch๐
This option sets the value of the preprocessor macro __PTX_SM__. For example, for sm_35 it has the value 350 โจ
-misa=architecture-stringโ ๐ธ Just an alias of-march=๐-march-map=architecture-stringโ ๐ง Picks the closest available-march=value that isn't more capable than what you asked for. For example,-march-map=sm_50gives you-march=sm_37, and-march-map=sm_53gives you-march=sm_53๐-mptx=version-stringโ ๐ฆ Generates code for the PTX ISA version you specify. 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 whichever one added support for your selected PTX ISA target architecture (see -march=), but it's at least 6.3, or 7.3 for -march=sm_52 and higher ๐
This option sets the values of the preprocessor macros __PTX_ISA_VERSION_MAJOR__ and __PTX_ISA_VERSION_MINOR__. For example, for 3.1 the macros have the values 3 and 1, respectively ๐
-mmainkernelโ ๐ฅ Links in code for a__mainkernel. This is for stand-alone execution instead of offloading ๐-moptimizeโ ๐ Applies partitioned execution optimizations. This is the default whenever any level of optimization is selected โจ-msoft-stackand-mno-soft-stackโ ๐ซถ With-mno-soft-stack(the default, unless-mgomphas been specified), GCC uses PTX "native" stacks. That means the code uses.localmemory or PTXallocadirectly for stack storage. Unless-mptx=7.3or higher and-march=sm_52or higher are active, variable-length arrays and dynamically allocating memory on the stack withallocaare not supported ๐ญ
With -msoft-stack (implied by -mgomp), the code doesn't use .local memory or PTX alloca directly for stack storage. Instead, a per-warp stack pointer is maintained explicitly ๐ง That makes variable-length stack allocation possible (with variable-length arrays or alloca). When global memory is the underlying storage, it also lets you 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 so you can test the compiler. To generate code suitable for linking into programs that use OpenMP offloading, use -mgomp instead ๐
-muniform-simtโ ๐ Switches to a code generation variant that lets all threads in each warp execute, while keeping memory state and side effects as if only one thread per warp were active outside of OpenMP SIMD regions ๐ All atomic operations and calls to the runtime (malloc,free,vprintf) are conditionally executed (if and only if the current lane index equals the master lane index), and the register being assigned gets copied via a shuffle instruction from the master lane ๐ฆ Outside of SIMD regions, lane 0 is the master. Inside them, each thread sees itself as the master ๐
The shared memory array int __nvptx_uni[] stores all-zeros or all-ones bitmasks for each warp, which show the current mode (0 outside of SIMD regions) ๐ฅ Each thread can bitwise-AND the bitmask at position tid.y with the current lane index to compute the master lane index โจ
-mgompโ ๐ธ Generates code for OpenMP offloading. It enables-msoft-stackand-muniform-simt, and selects the matching multilib variant ๐ซถ
๐งก OpenRISC Options ๐งก
These options are defined for OpenRISC ๐
-mboard=nameโ ๐ Configures a board-specific runtime. This gets passed to the linker for newlib board library linking. The default isor1ksim๐-mnewlibโ ๐ This option is ignored, it's only there for compatibility. It used to select linker and preprocessor options for use with newlib ๐-msoft-divand-mhard-divโ ๐ Selects software or hardware divide (l.div,l.divu) instructions. The default is hardware divide ๐ง-msoft-muland-mhard-mulโ ๐ Selects software or hardware multiply (l.mul,l.muli) instructions. The default is hardware multiply ๐-msoft-floatand-mhard-floatโ ๐ฆ Selects software or hardware for floating-point operations. The default is software ๐ธ-mdouble-floatโ ๐ฅ When-mhard-floatis selected, this 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, this turns on generation of unordered floating point compare and set flag (lf.sfun*) instructions ๐ฅ. By default, functions from libgcc handle those unordered compare and set flag operations instead ๐ .-mcmovโ ๐ Turns on generation of conditional move (l.cmov) instructions ๐ฆ. By default, the same result is generated using set and branch ๐ธ.-mrorโ ๐ Turns on generation of rotate right (l.ror) instructions ๐. By default, functions from libgcc handle rotate right operations ๐ซถ.-mroriโ โจ Turns on generation of rotate right with immediate (l.rori) instructions ๐. By default, functions from libgcc handle rotate right with immediate operations ๐ง.-msextโ ๐ Turns on generation of sign extension (l.ext*) instructions ๐. By default, memory loads are used to perform sign extension ๐.-msfimmโ ๐ธ Turns on generation of compare and set flag with immediate (l.sf*i) instructions ๐ . By default, extra instructions get generated to store the immediate into a register first ๐.-mshftimmโ โญ Turns on generation of shift with immediate (l.srai,l.srli,l.slli) instructions ๐ฅ. By default, extra instructions get generated to store the immediate into a register first ๐ญ.-mcmodel=smallโ ๐ฆ Generates OpenRISC code for the small model, where the GOT is limited to 64k ๐. This is the default model ๐.-mcmodel=largeโ ๐ Generates OpenRISC code for the large model, where the GOT may grow up to 4G in size ๐ง.
โจ PDP-11 Options โจ
okay so 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โ ๐ Does not use hardware floating point ๐ซถ.-mac0โ ๐ Returns floating-point results inac0(fr0in Unix assembler syntax) ๐.-mno-ac0โ ๐ธ Returns floating-point results in memory ๐ฆ. This is the default ๐.-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 16-bitint๐. This is the default ๐ธ.-mint32,-mno-int16โ ๐ฅ Uses 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 significantly reduce the size of the final ELF binary, but some standard C runtime features get removed ๐ญ.
๐จ This option disables support for static initializers and constructors. Beware that the compiler could still generate code with static initializers and constructors. It is up to the programmer to make sure the source program will not use those features ๐.
The minimal startup code would not pass argc and argv arguments to main, so main must be declared as int main (void) ๐ง. This is already the norm for most firmware projects โจ.
-mmcu=mcuโ ๐ Specifies the PRU hardware variant to use ๐. A correspondingly named spec file would be loaded, passing the memory region sizes to the linker and defining hardware-specific C macros ๐ฆ.
Newlib provides only the sim spec, which is meant for running regression tests using a simulator ๐. Specs for real hardware can be obtained by installing the GnuPruMcu (https://github.com/dinuxbg/gnuprumcu/) package ๐ซถ.
-mno-relaxโ ๐ Makes GCC pass the--no-relaxcommand-line option to the linker instead of the--relaxoption ๐.-mloopโ ๐ Allows (or does not allow) GCC to use the LOOP instruction ๐ธ.-mabi=variantโ ๐ Specifies 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 ๐ซถ. These are the differences ๐ฅ:
โจ Function Pointer Size โจ
The TI ABI specifies that function (code) pointers are 16-bit ๐, whereas GNU supports only 32-bit data and code pointers ๐ญ.
โจ Optional Return Value Pointer โจ
Function return values larger than 64 bits are passed by using a hidden pointer as the first argument of the function ๐ง. The TI ABI, though, mandates that the pointer can be NULL in case the caller is not using the returned value ๐. GNU always passes and expects a valid return value pointer ๐.
โ ๏ธ The current-mabi=tiimplementation simply raises a compile error when any of the above code constructs is detected ๐ญ. As a consequence, the standard C library cannot be built and it is omitted when linking with-mabi=ti๐.
Relaxation is a GNU feature, and for safety reasons it is disabled when using -mabi=ti ๐. The TI toolchain does not emit relocations for QBBx instructions, so the GNU linker cannot adjust them when shortening 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 ๐ .-mplt,-mno-pltโ ๐ซถ When generating PIC code, does or doesn't allow the use of PLTs ๐ฅ. Ignored for non-PIC ๐. The default is-mpltโจ.-mabi=ABI-stringโ ๐ Specifies the integer and floating-point calling convention ๐ง. The ABI-string has two parts: the size of integer types and the registers used for floating-point types ๐. For example,-march=rv64ifd -mabi=lp64dmeans thatlongand pointers are 64-bit (implicitly definingintto be 32-bit), and that 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-march=rv64ifd -mabi=lp64, in which no floating-point arguments get passed in registers at all ๐.
The default for this argument is system dependent, so users who want a specific calling convention should specify one explicitly ๐ญ. The valid calling conventions are: ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d ๐. Some calling conventions are impossible to implement 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 is also the ilp32e ABI, which can only be used with the rv32e architecture, and the lp64e ABI, which can only be used with rv64e ๐ง. Those ABIs are not well specified at present and are 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 ๐ฆ, which is unimplemented on some processors (including those from T-Head) ๐. If thefence.tsoinstruction is not 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โ ๐ง Specifies the version of the RISC-V Unprivileged (formerly User-Level) ISA specification to produce code conforming to ๐. The possibilities for ISA-spec-string are ๐: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-stringโ ๐ Generates code for the given RISC-V ISA (e.g.rv64im) ๐ . ISA strings must be lower-case ๐ซถ. Examples includerv64i,rv32g,rv32e, andrv32imafโจ. Additionally, a special value,help(-march=help), is accepted to list all supported extensions ๐ง.
The syntax of the ISA string is defined as follows ๐ฅ:
- The string must start with
rv32orrv64, followed byi,e, org, referred to as the base ISA ๐. - The subsequent part of the string is a list of extension names ๐ธ. Extension names can be categorized as multi-letter (e.g.
zba) and single-letter (e.g.v) ๐ฆ. Single-letter extensions can appear consecutively, 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 is used to improve readability and can act as a separator โจ.
- Extension names may include an optional version number, following the syntax
<major>p<minor>or<major>(e.g.m2p1orm2) ๐.
Supported extensions are listed below ๐:
iโ version 2.0, 2.1 โ Base integer extension ๐ .eโ version 2.0 โ Reduced base integer extension ๐ธ.gโ no version listed โ General-purpose computing base extension, wheregwill expand toi,m,a,f,d,zicsrandzifencei๐.mโ version 2.0 โ Integer multiplication and division extension ๐ฅ.aโ version 2.0, 2.1 โ Atomic extension ๐ฆ.fโ version 2.0, 2.2 โ Single-precision floating-point extension ๐ง.dโ version 2.0, 2.2 โ Double-precision floating-point extension ๐.cโ version 2.0 โ Compressed extension ๐.hโ version 1.0 โ Hypervisor extension ๐.vโ version 1.0 โ Vector extension โจ.zicsrโ version 2.0 โ Control and status register access extension ๐ซถ.zifenceiโ version 2.0 โ Instruction-fetch fence extension ๐.zicondโ version 1.0 โ Integer conditional operations extension ๐.za64rsโ version 1.0 โ Reservation set size of 64 bytes ๐ฆ.za128rsโ version 1.0 โ Reservation set size of 128 bytes ๐.zawrsโ version 1.0 โ Wait-on-reservation-set extension โญ.zbaโ version 1.0 โ Address calculation extension ๐ฅ.
zbb(1.0) โ Basic bit manipulation, bestie, the whole vibe ๐ฆzbc(1.0) โ Carry-less multiplication, very math-coded ๐งฎzbs(1.0) โ Single-bit operations, tiny but mighty โจzfinx(1.0) โ Single-precision floats living in integer registers ๐zdinx(1.0) โ Double-precision floats living in integer registers ๐zhinx(1.0) โ Half-precision floats living in integer registers ๐ธzhinxmin(1.0) โ The minimal half-precision-in-integer-registers version ๐ซถzbkb(1.0) โ Cryptography bit manipulation ๐zbkc(1.0) โ Cryptography carry-less multiply ๐zbkx(1.0) โ Cryptography crossbar permutation ๐zkne(1.0) โ AES encryption, secret agent stuff ๐ต๏ธzknd(1.0) โ AES decryption, undoing the secret agent stuff ๐ต๏ธzknh(1.0) โ Hash functions ๐งzkr(1.0) โ Entropy source, the randomness queen ๐ฒzksed(1.0) โ SM4 block cipher ๐zksh(1.0) โ SM3 hash function ๐zkt(1.0) โ Data independent execution latency, no timing drama ๐ฐ๏ธzk(1.0) โ Standard scalar cryptography, the whole package ๐ฆzkn(1.0) โ NIST algorithm suite ๐บ๐ธzks(1.0) โ ShangMi algorithm suite ๐จ๐ณzihintntl(1.0) โ Non-temporal locality hints ๐zihintpause(1.0) โ Pause hints, take a breath bestie ๐งzicboz(1.0) โ Cache-block zero ๐งzicbom(1.0) โ Cache-block management ๐งzicbop(1.0) โ Cache-block prefetch ๐งzic64b(1.0) โ Cache blocks are 64 bytes ๐ziccamoa(1.0) โ Main memory supports all the atomics in A โ๏ธziccif(1.0) โ Main memory supports instruction fetch with the atomicity requirement ๐งzicclsm(1.0) โ Main memory supports misaligned loads and stores ๐ziccrse(1.0) โ Main memory supports forward progress on LR/SC sequences ๐โโ๏ธzicntr(2.0) โ Standard base counters and timers โฐzihpm(2.0) โ Standard hardware performance counters ๐ztso(1.0) โ Total store ordering, very orderly ๐zve32x(1.0) โ Vector extensions for embedded processors ๐zve32f(1.0) โ Vector extensions for embedded processors ๐zve64x(1.0) โ Vector extensions for embedded processors ๐zve64f(1.0) โ Vector extensions for embedded processors ๐zve64d(1.0) โ Vector extensions for embedded processors ๐zvl32b(1.0) โ Minimum vector length standard extension ๐zvl64b(1.0) โ Minimum vector length standard extension ๐zvl128b(1.0) โ Minimum vector length standard extension ๐zvl256b(1.0) โ Minimum vector length standard extension ๐zvl512b(1.0) โ Minimum vector length standard extension ๐zvl1024b(1.0) โ Minimum vector length standard extension ๐zvl2048b(1.0) โ Minimum vector length standard extension ๐zvl4096b(1.0) โ Minimum vector length standard extension ๐zvbb(1.0) โ Vector basic bit manipulation ๐ฆzvbc(1.0) โ Vector carry-less multiplication ๐งฎzvkb(1.0) โ Vector cryptography bit manipulation ๐zvkg(1.0) โ Vector GCM/GMAC ๐zvkned(1.0) โ Vector AES block cipher ๐ต๏ธzvknha(1.0) โ Vector SHA-2 secure hash ๐งzvknhb(1.0) โ Vector SHA-2 secure hash ๐งzvksed(1.0) โ Vector SM4 block cipher ๐zvksh(1.0) โ Vector SM3 secure hash ๐zvkn(1.0) โ Vector NIST algorithm suite, which expands tozvkned,zvknhb,zvkbandzvkt๐zvknc(1.0) โ Vector NIST algorithm suite with carry-less multiply, which expands tozvknandzvbc๐zvkng(1.0) โ Vector NIST algorithm suite with GCM, which expands tozvknandzvkg๐zvks(1.0) โ Vector ShangMi algorithm suite, which expands tozvksed,zvksh,zvkbandzvkt๐zvksc(1.0) โ Vector ShangMi algorithm suite with carry-less multiplication, which expands tozvksandzvbc๐zvksg(1.0) โ Vector ShangMi algorithm suite with GCM, which expands tozvksandzvkg๐zvkt(1.0) โ Vector data independent execution latency ๐ฐ๏ธzfh(1.0) โ Half-precision floating point ๐ธzfhmin(1.0) โ Minimal half-precision floating point ๐ธzvfh(1.0) โ Vector half-precision floating point ๐ธzvfhmin(1.0) โ Vector minimal half-precision floating point ๐ธzvfbfmin(1.0) โ Vector BF16 converts ๐zfa(1.0) โ Additional floating point, extra spicy ๐ถ๏ธzmmul(1.0) โ Integer multiplication โ๏ธzca(1.0) โ Integer compressed instructions ๐๏ธzcf(1.0) โ Compressed single-precision floating point loads and stores ๐๏ธzcd(1.0) โ Compressed double-precision floating point loads and stores ๐๏ธzcb(1.0) โ Simple compressed instructions ๐๏ธzce(1.0) โ Compressed instruction extensions for embedded processors ๐๏ธzcmp(1.0) โ Compressed push and pop ๐๏ธzcmt(1.0) โ Table jump instructions ๐smaia(1.0) โ Advanced interrupt architecture ๐จsmepmp(1.0) โ PMP enhancements for memory access and execution prevention in Machine mode ๐ก๏ธsmstateen(1.0) โ State enable ๐ชssaia(1.0) โ Advanced interrupt architecture for supervisor mode ๐จsscofpmf(1.0) โ Count overflow and filtering ๐ขssstateen(1.0) โ State-enable for supervisor mode ๐ชsstc(1.0) โ Supervisor-mode timer interrupts โฐsvinval(1.0) โ Fine-grained address-translation cache invalidation ๐งนsvnapot(1.0) โ NAPOT translation contiguity ๐บ๏ธsvpbmt(1.0) โ Page-based memory types ๐๏ธxcvmac(1.0) โ Core-V multiply-accumulate ๐งฉxcvalu(1.0) โ Core-V miscellaneous ALU ๐งฉxcvelw(1.0) โ Core-V event load word ๐งฉxtheadba(1.0) โ T-Head address calculation ๐xtheadbb(1.0) โ T-Head basic bit manipulation ๐xtheadbs(1.0) โ T-Head single-bit instructions ๐xtheadcmo(1.0) โ T-Head cache management operations ๐xtheadcondmov(1.0) โ T-Head conditional move ๐xtheadfmemidx(1.0) โ T-Head indexed memory operations for floating-point registers ๐xtheadfmv(1.0) โ T-Head double floating-point high-bit data transmission ๐xtheadint(1.0) โ T-Head acceleration interruption ๐xtheadmac(1.0) โ T-Head multiply-accumulate ๐xtheadmemidx(1.0) โ T-Head indexed memory operations ๐xtheadmempair(1.0) โ T-Head two-GPR memory operations ๐xtheadsync(1.0) โ T-Head multi-core synchronization ๐xventanacondops(1.0) โ Ventana integer conditional operations ๐ท
When -march= is not specified, the setting from -mcpu is used, bestie ๐
If both -march and -mcpu= are left out, the default here depends on your system ๐ฅ๏ธ so if you want a specific architecture extension, you should totally name it yourself ๐
When the RISC-V specs say one extension depends on others, GCC will automatically add those dependent extensions to the enabled set, as long as you didn't add them yourself โจ
-mcpu=processor-stringโ Use the architecture of, and optimize the output for, the given processor, identified by its particular CPU name ๐ง The permitted values 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-xp450,sifive-x670,thead-c906,tt-ascalon-d8, andxiangshan-nanhu๐ฃ
Note that -mcpu does not override -march or -mtune ๐
โโ๏ธ
-mtune=processor-stringโ Optimize the output for the given processor, identified by its microarchitecture or particular CPU name ๐ฏ The permitted values are:generic-ooo,rocket,sifive-3-series,sifive-5-series,sifive-7-series,size,sifive-p400-series,sifive-p600-series, and all valid options for-mcpu=๐
When -mtune= is not specified, the setting from -mcpu is used, and if neither is given, the default is rocket ๐
The size choice is not meant for end-users, lowkey an internal thing ๐ It gets used when -Os is specified. It overrides the instruction cost info provided by -mtune=, but it does not override the pipeline info. This helps shrink the code size while still giving good performance ๐โจ
-mpreferred-stack-boundary=numโ Try to keep the stack boundary aligned to a boundary of 2 raised to num bytes ๐ If-mpreferred-stack-boundaryis not specified, the default is4(16 bytes, or 128 bits) ๐
โ ๏ธ Warning, bestie: 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 ๐ญ
-msmall-data-limit=n is my favorite way to shrink things ๐ง. It puts global and static data smaller than n bytes into a special section, but only on some targets ๐ธ
-msave-restore,-mno-save-restoreโ okay so these decide whether the prologue and epilogue code gets smaller but slower by calling library functions ๐ . The default is the fast inline prologues and epilogues โจ-mmovcc,-mno-movccโ-mmovccmakes GCC produce branchless conditional-move sequences, even on targets without dedicated conditional instructions ๐ฆ. When it's on, it builds sequences of ALU operations out of base integer ISA instructions wherever that's worth it ๐ฅ-minline-atomics,-mno-inline-atomicsโ-mno-inline-atomicsis the smaller but slower option, using subword atomic emulation that callslibatomicfunctions ๐. The default is fast inline subword atomics that don't needlibatomicat all ๐-minline-strlen,-mno-inline-strlenโ this one tries to inlinestrlencalls when it can ๐. It only happens if the string is properly aligned and the accelerated instructions are available. By default,strlencalls are not inlined ๐-minline-strcmp,-mno-inline-strcmpโ same vibe asstrlen๐ . GCC only inlinesstrcmpcalls when the strings are properly aligned and the accelerated instructions exist. The default is to not inlinestrcmpcalls โจ
The --param riscv-strcmp-inline-limit=n parameter controls the maximum number of bytes that the inlined code compares ๐ฅ. Its default value is 64 ๐ซถ
-minline-strncmp,-mno-inline-strncmpโ also thestrcmpenergy but forstrncmp๐. Inlining only happens when the strings are properly aligned and the accelerated instructions are around. The default is to not inlinestrncmpcalls ๐ โโ๏ธ
Same deal here: --param riscv-strcmp-inline-limit=n sets the maximum number of bytes compared by the inlined code, and the default is 64 ๐
-mshorten-memrefs,-mno-shorten-memrefsโ this is a sneaky one ๐ฆ. With it on, GCC tries to use more compressed load/store instructions by swapping a load/store ofbase register + large offsetfor a new load/store ofnew base + small offset. If that new base lands in a compressed register, the new load/store can be compressed too โจ. Right now it only works on 32-bit integer load/stores ๐ธ-mstrict-align,-mno-strict-alignโ okay so this is about whether unaligned memory accesses are generated. The wording in the original is a little muddled ("Do not or do generate"), but the gist is that the default depends on whether the processor you're optimizing for handles fast unaligned access ๐-mscalar-strict-align,-mno-scalar-strict-alignโ same unaligned-access drama as above ๐ . The default also depends on the processor's fast unaligned access support. This one is just an alias for-mstrict-align๐ซถ-mvector-strict-align,-mno-vector-strict-alignโ this is the vector version of the story ๐. Unaligned vector memory accesses are off by default, unless the processor you're targeting explicitly supports element-misaligned vector memory access โจ-mcmodel=medlowโ the medium-low code model ๐ง. The program and its statically defined symbols have to fit inside one 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โ the medium-any code model ๐. The program and its statically defined symbols just have to be within any single 2 GiB address range. Static or dynamic linking both work ๐
The code from medium-any is position-independent, but it is not guaranteed to work when linked into position-independent executables or libraries ๐
-mcmodel=largeโ the big boss code model ๐. It has no restrictions on the size or placement of symbols ๐ฅ-mexplicit-relocs,-mno-exlicit-relocsโ-mexplicit-relocsmeans the compiler uses assembler relocation operators when handling symbolic addresses ๐ฆ. The alternative is assembler macros, which may limit optimization ๐. (The original spells the second one-mno-exlicit-relocs, so that's exactly what's in the code here ๐ซถ)-mrelax,-mno-relaxโ this takes advantage of linker relaxations to cut down the number of instructions needed to materialize symbol addresses โจ. The default is to take advantage of linker relaxations ๐-mriscv-attribute,-mno-riscv-attributeโ-mriscv-attributeemits a RISC-V attribute that records extra info into ELF objects, and-mno-riscv-attributeskips emitting it ๐ธ. Heads up: this feature needs at least binutils 2.32 ๐ซถ-mcsr-check,-mno-csr-checkโ these enable or disable the CSR checking ๐ง-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 ๐-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โ these generate stack protection code that uses a canary atguard๐ก๏ธ. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block ๐ง
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset are the ones that get specific: they pick which register is the base for reading the canary, and what offset from that base to read at ๐ฅ. 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 to TLS variables โจ-mtls-dialect=tradโ uses traditional TLS as the thread-local storage mechanism for dynamic accesses to TLS variables ๐ธ. This is the default ๐
๐ RL78 Options ๐
-msimโ links in extra target libraries so the program can run inside a simulator ๐ง-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ picks the type of hardware multiplication and division support to use ๐ฅ. The simplest is"none", which uses software for both multiplication and division, and it's the default ๐."g13"is for the hardware multiply/divide peripheral on the RL78/G13 (S2 core) targets ๐ฆ."g14"turns on the multiplication and division instructions from the RL78/G14 (S3 core) parts ๐."rl78"is an alias for"g14", and"mg10"is an alias for"none"๐
A C preprocessor macro also gets defined based on this option. The possible values are "__RL78_MUL_NONE__", "__RL78_MUL_G13__", or "__RL78_MUL_G14__" โจ
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ specifies which RL78 core to target ๐ . The default is the G14 core, also known as an S3 core or just RL78 ๐. The G13 (S2) core doesn't have multiply or divide instructions, and uses a hardware peripheral for those operations instead ๐ฆ. The G10 (S1) core has no register banks, so it uses a different calling convention ๐
If this option is set, it also picks the 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 multiplication altogether ๐
Heads up: even though the RL78/G14 core is the default target, passing-mcpu=g14or-mcpu=rl78on the command line does change how the toolchain behaves, because it also enables G14 hardware multiply support ๐ญ. If you don't specify these on the command line, software multiplication routines get used even though the code targets the RL78 core. This is for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ฅบ
A C preprocessor macro also gets defined based on this option. The possible values are "__RL78_G10__", "__RL78_G13__", or "__RL78_G14__" ๐
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the matching-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 interrupt handlers. With this on, those registers can be used in ordinary functions too โจ-m64bit-doubles,-m32bit-doublesโ makes the"double"data type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) ๐ธ. The default is-m32bit-doubles๐-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ tells interrupt handler functions to preserve the MDUC registers ๐ซถ. You only really need this if normal code might touch the MDUC registers, like if it does multiplication and division. By default, the MDUC registers get ignored, because that makes interrupt handlers faster ๐ฅ. The target option-mg13has to be passed for this to work, since this feature only exists on the G13 target (S2 core) ๐ฆ. The MDUC registers only get saved if the interrupt handler does a multiplication or division, or calls another function ๐
๐ท IBM RS/6000 and PowerPC Options ๐ท
These -m options are defined for the IBM RS/6000 and PowerPC ๐ง
-mpowerpc-gpopt,-mno-powerpc-gpopt,-mpowerpc-gfxopt,-mno-powerpc-gfxopt,-mpowerpc64,-mno-powerpc64,-mmfcrf,-mno-mfcrf,-mpopcntb,-mno-popcntb,-mpopcntd,-mno-popcntd,-mfprnd,-mno-fprnd,-mcmpb,-mno-cmpb,-mhard-dfp,-mno-hard-dfpโ these are the options that say which instructions are available on the processor you're using ๐ . Their default value gets decided when GCC is configured ๐ธ. Specifying-mcpu=cpu_typeoverrides whatever these options say ๐. We recommend using-mcpu=cpu_typeinstead of the options listed above ๐
Okay so the PowerPC options are where things get really juicy ๐ โจ
Turning on -mpowerpc-gpopt lets GCC use the optional PowerPC instructions from the General Purpose group, including floating-point square root ๐ธ And -mpowerpc-gfxopt unlocks the optional instructions from the Graphics group, like floating-point select ๐ฆ
-mmfcrf lets GCC generate the move from condition register field instruction. It's on the POWER4 processor and other chips that speak PowerPC V2.01 ๐ฅ Then there's -mpopcntb, which gets you the popcount instruction and the double-precision FP reciprocal estimate instruction. That one's from POWER5 and other V2.02 chips ๐ -mpopcntd gives you the popcount instruction from POWER7 and other V2.06 processors ๐ -mfprnd lets GCC emit the FP round to integer instructions, found on POWER5+ and other V2.03 chips โญ -mcmpb is the compare bytes instruction from POWER6 and other V2.05 chips ๐ซถ And -mhard-dfp turns on the decimal floating-point instructions that show up on some POWER processors ๐ง
-mpowerpc64 is the big one for 64-bit energy. It lets GCC generate the extra 64-bit instructions from the full PowerPC64 architecture and treat GPRs as 64-bit doubleword quantities ๐ Heads up, GCC defaults to -mno-powerpc64, so you have to ask for it ๐
-mcpu=cpu_typeโ this sets the architecture type, register usage, and instruction scheduling parameters for the machine type you name as cpu_type. The values you can pick are401,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โจ
Okay so -mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le are the generic vibes ๐ They give you pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC. GCC assumes an appropriate generic processor model for scheduling, so nothing too specific ๐ฆ
Then there's native, which is the main character move ๐ It detects the host processor on the machine doing the compiling and picks the architecture option that matches it. Just know that -mcpu=native does nothing if GCC doesn't recognize the processor ๐
Everything else names one specific processor. Code built for that chip runs its best there, and it might not run at all on other chips ๐ญ
The -mcpu option quietly turns a bunch of other options on or off for you ๐ซถ The list is -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, and -mrop-protect ๐ธ
The exact set of options for each CPU changes between compiler versions. GCC picks whatever seems to make the best code for that chip, so it doesn't always match what the hardware can actually do ๐
Want to override one? Just put it after -mcpu, like -mcpu=970 -mno-altivec. Order matters here bestie ๐
On AIX, -maltivec and -mpowerpc64 don't get flipped by -mcpu right now, because AIX doesn't fully support them yet. You can still turn them on or off yourself if you're sure it'll work in your environment ๐
-mtune=cpu_typeโ this only sets the instruction scheduling parameters for cpu_type. It doesn't touch the architecture type or register usage like-mcpu=cpu_typedoes โจ It takes the same values as-mcpu. If you use both, the code uses the architecture and registers from-mcpu, but the scheduling comes from-mtune๐ฆ-mcmodel=smallโ generates PowerPC64 code for the small model, where the TOC is capped at 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. The TOC can be up to 4G, and other data and code is only limited by the 64-bit address space ๐-maltivec,-mno-altivecโ-maltivecgenerates code that uses AltiVec instructions and also turns on the built-in functions that give you more direct access to the AltiVec instruction set ๐ฅ-mno-altivecdoes the opposite. You might also need-mabi=altivecto adjust the current ABI with AltiVec ABI enhancements ๐
When you use-maltivec, the element order for AltiVec intrinsics like"vec_splat","vec_extract", and"vec_insert"matches the array element order for your target's endianness. So on a big-endian platform, element zero is the leftmost element in a vector register. On a little-endian platform, element zero is the rightmost one ๐
-mvrsave,-mno-vrsaveโ-mvrsavegenerates VRSAVE instructions when it's making AltiVec code.-mno-vrsaveskips them ๐ฆ-msecure-pltโ generates code that letsldandld.sobuild executables and shared libraries with non-executable".plt"and".got"sections. This one's a PowerPC 32-bit SYSV ABI option ๐ซถ-mbss-pltโ generates code that uses a BSS".plt"section, whichld.sofills in. It needs".plt"and".got"sections that are both writable and executable ๐ญ Also a PowerPC 32-bit SYSV ABI option ๐ง-msplit-patch-nopsโ when you add NOPs for a patchable area with-fpatchable-function-entry, this puts the "before" NOPs in front of the global entry point and the "after" NOPs after the local entry point. That means the NOPs aren't consecutive when a global entry point gets generated โจ Without this option, the NOPs go right before and right after the local entry point. That keeps them consecutive, but it pushes the global and local entry points further apart ๐ If only one entry point is generated, this option does nothing ๐-misel,-mno-iselโ turns the generation of ISEL instructions on or off ๐ธ-mvsx,-mno-vsxโ-mvsxgenerates code that uses vector/scalar (VSX) instructions and turns on built-in functions for more direct VSX access ๐ฅ-mno-vsxgenerates code that doesn't use them ๐-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 for the Hardware Transactional Memory (HTM) instructions, which were also added in version 2.07 of the PowerPC ISA ๐ฆ-mpower8-fusion,-mno-power8-fusionโ-mpower8-fusionkeeps some integer operations next to each other so they can get fused together on POWER8 and later processors ๐ง-mno-power8-fusiondoesn't keep them adjacent like that ๐-mquad-memory,-mno-quad-memoryโ-mquad-memorygenerates code that uses the non-atomic quad word memory instructions.-mno-quad-memoryskips them. The-mquad-memoryoption needs 64-bit mode ๐-mquad-memory-atomic,-mno-quad-memory-atomicโ-mquad-memory-atomicgenerates code that uses the atomic quad word memory instructions.-mno-quad-memory-atomicskips them. This one also needs 64-bit mode ๐-mfloat128,-mno-float128โ these turn the__float128keyword on or off for IEEE 128-bit floating point. You get either software emulation for IEEE 128-bit floating point or hardware instructions ๐
To use the IEEE 128-bit floating point support, the VSX instruction set (-mvsx) has to be enabled first. Also, IEEE 128-bit floating point is only supported on Linux ๐ญ
-mfloat128 is on by default on PowerPC Linux systems that use the VSX instruction set. On other systems it's off ๐ซถ
If you use the ISA 3.0 instruction set (-mcpu=power9) on a 64-bit system, the IEEE 128-bit floating point support also turns on the generation of ISA 3.0 IEEE 128-bit floating point instructions โญ Otherwise, if you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets done 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 on by default on PowerPC Linux systems that use the ISA 3.0 instruction set. On other systems it's off ๐
-m32,-m64โ generates code for the 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 the code runs on any PowerPC variant ๐ The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits. It generates code for PowerPC64, just like-mpowerpc64โจ-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ these all change how the TOC (Table Of Contents) gets generated, and every executable file gets one ๐ง-mfull-tocis the default. With it, GCC gives at least one TOC entry to each unique non-automatic variable reference in your program. GCC also puts floating-point constants in the TOC ๐ The catch is that only 16,384 entries fit in the TOC ๐ญ
If the linker yells that you've overflowed the available TOC space, you can shrink how much TOC space you use with -mno-fp-in-toc and -mno-sum-in-toc ๐ซถ -mno-fp-in-toc stops GCC from putting floating-point constants in the TOC. -mno-sum-in-toc makes GCC generate code that calculates the sum of an address and a constant at run time, instead of stuffing that sum into the TOC ๐ You can use one or both. Each one makes the code very slightly slower and larger, but that's the trade for saving TOC space ๐ฆ
If you still run out of space in the TOC even when you specify both of these options, bestie, try -mminimal-toc instead ๐ญ. It makes GCC create only one TOC entry for every file. The catch is that the code comes out slower and larger, but it uses extremely little TOC space ๐. Honestly, save it for files with less frequently-executed code ๐ซถ.
-maix64,-maix32โ okay so-maix64turns on the 64-bit AIX ABI and calling convention โจ. You get 64-bit pointers, a 64-bit "long" type, and all the infrastructure needed to support them. It implies-mpowerpc64.-maix32goes the other way, disabling the 64-bit ABI and implying-mno-powerpc64. GCC defaults to-maix32๐.-mxl-compat,-mno-xl-compatโ this one is giving IBM XL compiler vibes ๐. It makes the code match XL semantics more closely when you're using the AIX-compatible ABI. Floating-point args to prototyped functions beyond the register save area (RSA) get passed on the stack too, on top of the argument FPRs. It also stops assuming the most significant double in a 128-bit long double value is properly rounded when comparing and converting to double, and it uses XL symbol names for long double support routines.
The AIX calling convention got extended without being documented at first, to handle an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than it declared ๐. IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine is compiled without optimization. Always storing floating-point arguments on the stack is inefficient and rarely needed, so this option isn't on by default. You only need it when calling subroutines compiled by IBM XL compilers without optimization.
-mpeโ this one's for the IBM RS/6000 SP Parallel Environment (PE) ๐ง. It links an app that uses message passing with special startup code so it can actually run. The system needs PE installed in the standard location (/usr/lpp/ppe.poe/). If it isn't there, you can override the specs file with-specs=and point it to the right directory.
The Parallel Environment doesn't support threads, so-mpeand-pthreadare incompatible. Don't pair them up, bestie ๐.
-malign-natural,-malign-powerโ on AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux,-malign-naturaloverrides the ABI-defined alignment of bigger types, like floating-point doubles, and puts them on their natural size-based boundary ๐.-malign-powertells GCC to follow the ABI-specified alignment rules instead. GCC defaults to the standard alignment defined in the ABI.
On 64-bit Darwin, natural alignment is already the default, and -malign-power isn't supported there ๐
โโ๏ธ.
-msoft-float,-mhard-floatโ-msoft-floatgenerates code that doesn't use the floating-point register set, so you don't touch those registers at all. Software floating-point emulation is provided, but you have to pass the option to GCC when linking too.-mhard-floatis the opposite: it lets the code use the floating-point register set ๐ฅ.-mmultiple,-mno-multipleโ these generate (or don't generate) the load multiple word and store multiple word instructions ๐. They're generated by default on POWER systems and aren't generated on PowerPC systems. Don't use-mmultipleon little-endian PowerPC systems, because those instructions don't work in little-endian mode. The exceptions are PPC740 and PPC750, which let these instructions work in little-endian mode.-mupdate,-mno-updateโ these control whether the load or store instructions that update the base register to the address of the calculated memory location get used. They're generated by default. If you use-mno-update, there's a small window between the time the stack pointer gets updated and the time 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โ these make the code try to avoid (or not avoid) indexed load or store instructions ๐ฆ. Those can cause a performance penalty on Power6 processors in certain situations, like stepping through large arrays that cross a 16M boundary. It's enabled by default when targeting Power6 and disabled otherwise.-mfused-madd,-mno-fused-maddโ these generate (or don't generate) the floating-point multiply and accumulate instructions โจ. They're generated by default if hardware floating point is used. The machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fast, and-mno-fused-maddis mapped to-ffp-contract=off.-mmulhw,-mno-mulhwโ these generate (or don't generate) the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors ๐ธ. They're generated by default when you target those processors.-mdlmzb,-mno-dlmzbโ these generate (or don't generate) the string-searchdlmzbinstruction on the IBM 405, 440, 464 and 476 processors ๐. It's generated by default when targeting those processors.-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems,-mno-bit-alignstops structures and unions that contain bit-fields from being forced to align to the base type of the bit-field.-mbit-aligndoes force that alignment.
Here's the tea ๐: by default, a structure 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 structure gets aligned to a 1-byte boundary and is only 1 byte in size.
-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems, these decide whether GCC assumes unaligned memory references get handled by the system.-mno-strict-alignassumes they do, and-mstrict-aligndoesn't ๐ .-mrelocatable,-mno-relocatableโ these generate code that allows (or doesn't allow) a static executable to be relocated to a different address at run time ๐ฆ. A simple embedded PowerPC system loader should relocate the entire contents of.got2and the 4-byte locations listed in the.fixupsection, which is 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.-mrelocatable-lib,-mno-relocatable-libโ like-mrelocatable,-mrelocatable-libgenerates a.fixupsection so static executables can be relocated at run time. The difference is that-mrelocatable-libdoesn't use the smaller stack alignment of-mrelocatable. Objects compiled with-mrelocatable-libcan be linked with objects compiled with any combination of the-mrelocatableoptions ๐ค.-mno-toc,-mtocโ on System V.4 and embedded PowerPC systems, these decide whether GCC assumes register 2 contains a pointer to a global area with the addresses the program uses ๐ง .-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 isn't relocatable itself, but its external references are relocatable ๐. The result is good for applications, but not for 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 that register with an appropriate value before execution begins.-mprioritize-restricted-insns=priorityโ this controls the priority given to dispatch-slot restricted instructions during the second scheduling pass ๐. The argumentprioritytakes the value0,1, or2, which assigns no, highest, or second-highest priority (respectively) to dispatch-slot restricted instructions.-msched-costly-dep=dependence_typeโ this controls which dependences the target considers costly during instruction scheduling ๐. The argumentdependence_typetakes 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 for which the latency is greater than or equal tonumberis costly.
-minsert-sched-nops=schemeโ this controls which NOP insertion scheme gets used during the second scheduling pass ๐ซง. The argumentschemetakes 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. Insert exactly as many NOPs as needed to force an insn to a new group, according to the estimated processor grouping.numberโ Insert NOPs to force costly dependent insns into separate groups. InsertnumberNOPs to force an insn to 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โ these specify both-mcall-sysvand-meabi๐ .-mcall-sysv-noeabiโ this specifies 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โ okay so this one is for System V.4 and embedded PowerPC systems, and it makes the compiler build code for the OpenBSD operating system ๐ง-mtraceback=traceback_typeโ pick which kind of traceback table you want ๐ The valid values for traceback_type arefull,part, andno.-maix-struct-returnโ every structure gets returned in memory, as the AIX ABI says ๐ฆ-msvr4-struct-returnโ structures smaller than 8 bytes come back in registers instead, which is what the SVR4 ABI wants ๐-mabi=abi-typeโ this lets you extend the current ABI with a particular extension, or remove one ๐ The valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1, andelfv2. And for AIX, you also getvec-extabiandvec-defaultโจ-mabi=ibmlongdoubleโ switches the current ABI over to IBM extended-precision long double ๐ซถ Heads up bestie, this is not likely to work if your system already defaults to IEEE extended-precision long double. If you change the long double type away from IEEE extended-precision, the compiler gives you a warning unless you use the-Wno-psabioption. You also need-mlong-double-128turned on for this one.-mabi=ieeelongdoubleโ the opposite move: it changes the current ABI to IEEE extended-precision long double ๐ Same deal here, this is not likely to work if your system defaults to IBM extended-precision long double. Switching away from IBM extended-precision gets you a warning unless you use-Wno-psabi, and-mlong-double-128has to be enabled too.-mabi=elfv1โ changes the current ABI to the ELFv1 ABI ๐ This is the default for big-endian PowerPC 64-bit Linux. Overriding the default needs special system support, and honestly it is likely to fail in spectacular ways ๐
Overriding the default ABI with -mabi=elfv1 requires special system support and is likely to fail in spectacular ways.
-mabi=elfv2โ changes the current ABI to the ELFv2 ABI ๐ธ This is the default for little-endian PowerPC 64-bit Linux. Overriding the default also requires special system support and is likely to fail in spectacular ways.
Overriding the default ABI with -mabi=elfv2 requires special system support and is likely to fail in spectacular ways.
-mgnu-attribute,-mno-gnu-attributeโ this makes the compiler emit.gnu_attributeassembly directives ๐ฆ Those set tag/value pairs in a.gnu.attributessection that describe the ABI variations used in function parameters or return values.-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems,-mprototypetells the compiler to assume that all calls to variable argument functions are properly prototyped โจ Without it, the compiler has to insert an instruction before every non-prototyped call to set or clear bit 6 of the condition code register ("CR"), so the function knows whether floating-point values are passed in the floating-point registers, 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.oand the standard C libraries arelibsim.aandlibc.a๐งธ This is the default forpowerpc-*-eabisimconfigurations.-mmvmeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibmvme.aandlibc.a๐ญ-madsโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibads.aandlibc.a๐ท-myellowknifeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibyk.aandlibc.a๐-mvxworksโ on System V.4 and embedded PowerPC systems, this tells the compiler you are compiling for a VxWorks system ๐ธ-membโ on embedded PowerPC systems, this sets the"PPC_EMB"bit in the ELF flags header, which indicates that eabi extended relocations are used ๐ช-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems,-meabimeans you adhere to the Embedded Applications Binary Interface (EABI), which is a set of modifications to the System V.4 specifications ๐-mno-eabimeans you do not. Choosing-meabialigns the stack to an 8-byte boundary, calls a function"__eabi"from"main"to set up the EABI environment, and lets the-msdataoption use both"r2"and"r13"to point to two separate small data areas. Choosing-mno-eabialigns the stack to a 16-byte boundary, does not call any EABI initialization function from"main", and makes the-msdataoption use only"r13"to point to a single small data area. The-meabioption is on by default if you configured GCC using one of thepowerpc*-*-eabi*options ๐-msdata=eabiโ on System V.4 and embedded PowerPC systems, small initialized"const"global and static data goes in the".sdata2"section, which is pointed to by register"r2"๐ Small initialized non-"const"global and static data goes in the".sdata"section, pointed to by register"r13". Small uninitialized global and static data goes in the".sbss"section, which sits right next to".sdata". Heads up,-msdata=eabiis incompatible with the-mrelocatableoption, and it also turns on the-memboption.-msdata=sysvโ on System V.4 and embedded PowerPC systems, small global and static data goes in the".sdata"section, pointed to by register"r13"๐ Small uninitialized global and static data goes in the".sbss"section, next to".sdata". This one is 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 gets compiled the same as-msdata=sysv๐ซง-msdata=dataโ on System V.4 and embedded PowerPC systems, small global data goes in the".sdata"section, and small uninitialized global data goes in the".sbss"section ๐ธ The twist is that register"r13"is not used to address small data. This is the default behavior unless other-msdataoptions are used.-msdata=none,-mno-sdataโ on embedded PowerPC systems, all initialized global and static data goes in the".data"section, and all uninitialized data goes in the".bss"section ๐ง-mreadonly-in-sdataโ read-only objects get put in the".sdata"section as well ๐ This is the default.-mblock-move-inline-limit=numโ inlines all block moves (like calls to"memcpy"or structure copies) that are less than or equal to num bytes โจ The minimum value for num is 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default value is target-specific.-mblock-compare-inline-limit=numโ generates non-looping inline code for all block compares (like calls to"memcmp"or structure compares) that are less than or equal to num bytes ๐ฅ If num is0, all inline expansion of block compare, both non-loop and loop, is disabled. The default value is target-specific.-mblock-compare-inline-loop-limit=numโ generates an inline expansion using loop code for all block compares that are less than or equal to num bytes, but greater than the limit for non-loop inline block compare expansion ๐ If the block length is not constant, at most num bytes get compared before"memcmp"is called to compare the rest of the block. The default value is target-specific.-mstring-compare-inline-limit=numโ compares at most num string bytes with inline code ๐งต If the difference or end of string is not found by the end of the inline compare, a call to"strcmp"or"strncmp"takes care of the rest. The default is 64 bytes.-G numโ on embedded PowerPC systems, global and static items less than or equal to num bytes go into the small data or BSS sections instead of the normal data or BSS section ๐ฃ By default, num is 8. The-G numswitch also gets passed to the linker, and all modules should be compiled with the same-G numvalue.-mregnames,-mno-regnamesโ on System V.4 and embedded PowerPC systems,-mregnamesmakes the compiler emit register names in the assembly output using symbolic forms, and-mno-regnamesmeans it does not ๐-mlongcall,-mno-longcallโ by default, the compiler 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 cannot be that far away. You can override this setting with the"shortcall"function attribute, or with#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 is 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). PowerPC with -mbss-plt and PowerPC64 ELFv1 (big-endian) do not support inline PLT calls.
On Darwin/PPC systems, #pragma longcall generates "jbsr 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 it generates a "bl callee" if the PPC "bl" instruction reaches the callee directly. Otherwise, the linker generates "bl L42" to call the branch island. The branch island gets 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 tells 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 longcall specifications when the linker is known to generate glue ๐
-mpltseq,-mno-pltseqโ-mpltseqimplements-fno-pltand long calls using an inline PLT call sequence, while-mno-pltseqdoes not ๐ That sequence supports lazy linking and long calls to functions indlopen'd shared libraries. Inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers. They're enabled by default if the support is detected when configuring GCC, and, in the case of 32-bit PowerPC, if GCC is configured with--enable-secureplt. Also be careful bestie:-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together ๐ซ
Okay bestie, we're still deep in the powerpc flags, so let's keep going ๐ฆโจ
-mtls-markers,-mno-tls-markersโ okay so-mtls-markerstags calls to__tls_get_addrwith a relocation that spells out the function argument ๐-mno-tls-markersskips the tagging. The tag lets the linker reliably match each call with its argument setup instructions for TLS optimization, and that means GCC can schedule the whole sequence better ๐-mrecip,-mno-recipโ this one turns on the reciprocal estimate and reciprocal square root estimate instructions, plus extra Newton-Raphson steps to get back the precision. Instead of doing a divide (or a square root and then a divide) for floating-point arguments, the chip just does the quick estimate-and-refine thing ๐ง You should pair-mrecipwith-ffast-math, or at least with-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math๐ซถ The throughput is usually higher than the non-reciprocal instruction, but the precision can drop by up to 2 ulp (so the inverse of 1.0 can come out as 0.99999994), especially for reciprocal square roots ๐ญ-mrecip=optโ this one controls exactly which reciprocal estimate instructions are allowed.optis a comma-separated list, and any item can get a!in front to flip it ๐allโ enables every estimate instruction ๐ฅdefaultโ enables the default instructions, same as-mrecipโจnoneโ disables every estimate instruction, same as-mno-recip๐divโ enables the reciprocal approximation instructions for both single and double precision ๐divfโ enables just the single-precision reciprocal approximation instructions ๐ธdivdโ enables just the double-precision reciprocal approximation instructions ๐rsqrtโ enables the reciprocal square root approximation instructions for both single and double precision ๐rsqrtfโ enables just the single-precision reciprocal square root approximation instructions โญrsqrtdโ enables just the double-precision reciprocal square root approximation instructions ๐ฆ
So, for example, -mrecip=all,!rsqrtd turns on every estimate instruction except FRSQRTE, XSRSQRTEDP, and XVRSQRTEDP, which are the ones handling double-precision reciprocal square roots ๐
-mrecip-precision,-mno-recip-precisionโ-mrecip-precisionassumes the reciprocal estimate instructions are more precise than the PowerPC ABI requires, and-mno-recip-precisionrefuses to assume that ๐ง Picking-mcpu=power6,-mcpu=power7or-mcpu=power8turns-mrecip-precisionon automatically โจ The double-precision square root estimate instructions aren't generated by default on low-precision machines, because they don't converge after three steps ๐-mveclibabi=typeโ picks 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 ๐ When generating code for power7, GCC currently emits calls toacosd2,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, andtanhf4๐ญ Both-ftree-vectorizeand-funsafe-math-optimizationsmust also be enabled, and the MASS libraries have to be specified at link time ๐ฅ-mfriz,-mno-frizโ-mfrizgenerates thefrizinstruction when-funsafe-math-optimizationsis used to optimize rounding floating-point values to 64-bit integer and back to floating point.-mno-frizdoesn't generate it ๐ Heads up though:frizdoesn't give 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โ-mpointers-to-nested-functionsgenerates code that loads the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems, where a function pointer points to a 3-word descriptor holding the function address, the TOC value to load intor2, and the static chain value to load intor11๐ง This one is on by default. 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โ-msave-toc-indirectsaves the TOC value in the reserved stack location in the function prologue when the function calls through a pointer on AIX and 64-bit Linux systems. If it isn't saved in the prologue, it gets saved right before the call through the pointer โจ-mno-save-toc-indirectis the default ๐ธ-mcompat-align-parm,-mno-compat-align-parmโ-mcompat-align-parmgenerates 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 didn't align a structure parameter on a 128-bit boundary when that structure had a member needing 128-bit alignment. Newer versions fixed that. This option lets you make code that works with functions compiled by the older GCC ๐ซถ
-mno-compat-align-parm 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 areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default with GNU libc version 2.4 or later) ๐ฅ Withtls,-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsetalso decide which register is the base register for reading the canary, and what offset from that base it's read at ๐ Both default to whatever the relevant ABI specifies โจ-mpcrel,-mno-pcrelโ-mpcrelgenerates pc-relative addressing, and-mno-pcreldoesn't ๐ฆ Using-mpcrelrequires that the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) are both enabled ๐-mprefixed,-mno-prefixedโ-mprefixedgenerates addressing modes that use prefixed load and store instructions, and-mno-prefixeddoesn't ๐ง-mprefixedneeds-mcpu=power10(or later) enabled ๐-mmma,-mno-mmaโ-mmmagenerates the MMA instructions, and-mno-mmadoesn't ๐-mmmaneeds-mcpu=power10(or later) enabled ๐-mrop-protect,-mno-rop-protectโ-mrop-protectgenerates ROP protection instructions when the target processor supports them, and-mno-rop-protectdoesn't ๐ก๏ธ Right now this option disables the shrink-wrap optimization (-fshrink-wrap) ๐ญ-mprivileged,-mno-privilegedโ-mprivilegedgenerates code that runs in privileged state, and-mno-privilegeddoesn't ๐-mblock-ops-unaligned-vsx,-mno-block-ops-unaligned-vsxโ-mblock-ops-unaligned-vsxgenerates unaligned vsx loads and stores for inline expansion ofmemcpyandmemmove, and-mno-block-ops-unaligned-vsxdoesn't ๐ธ--param rs6000-vect-unroll-limit=โ the vectorizer checks with target information to figure out whether unrolling the main vectorized loop would be worth it, and by how much. This parameter sets the upper bound on how much the vectorizer will unroll that main loop. The default value isfourโจ
๐ RX Options ๐
These command-line options are defined for RX targets ๐ง
-m64bit-doubles,-m32bit-doublesโ 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โ-fpuenables the use of RX floating-point hardware, and-nofpudisables it ๐ 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 isn't used for doubles if -m64bit-doubles is used ๐ญ
Note: if-fpuis enabled, then-funsafe-math-optimizationsis also enabled automatically. That's because the RX FPU instructions are themselves unsafe ๐
-mcpu=nameโ 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 doesn't support the MVTIPL instruction ๐ฆ
The RX200 series doesn't have a hardware floating-point unit, so -nofpu is enabled by default when this type is selected ๐ธ
-mbig-endian-data,-mlittle-endian-dataโ stores data (but not code) in the big-endian format with-mbig-endian-data. The default is-mlittle-endian-data, which stores data in the little-endian format ๐ง-msmall-data-limit=Nโ 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 area is limited, and it's up to the programmer to make sure it doesn't overflow ๐ญ Also, when the small data area is used, one of the RX's registers (usuallyr13) is reserved to point at this area, so the compiler can't use it anymore. That can make code slower and/or larger if variables get pushed onto the stack instead of being held in that register ๐
Note: common variables (variables that haven't been initialized) and constants aren't placed into the small data area, because they get assigned to other sections in the output executable ๐
So the default value is zero, which means this feature is switched off ๐ Heads up: it's not turned on by default at higher optimization levels (-O2 and friends) because reserving a register can be kinda detrimental. It's on you to experiment and figure out whether it actually helps your program ๐งช For how the register holding the small data area pointer gets picked, check out the -mpid option โจ
-msim,-mno-simโ Uses the simulator runtime ๐ฅ๏ธ The default is the libgloss board-specific runtime.-mas100-syntax,-mno-as100-syntaxโ When GCC spits out assembler, this makes it use a syntax that plays nicely with Renesas's AS100 assembler ๐ The GAS assembler can handle this syntax too, but it comes with some restrictions, so it isn't generated by default.-mmax-constant-size=Nโ Sets the biggest size, in bytes, that a constant can be and still be used as an operand in an RX instruction ๐ The RX instruction set can handle constants up to 4 bytes, but bigger values make the instruction longer, so sometimes it's smart to limit this. Constants that are too big get tucked into a constant pool and reached through register indirection ๐ง
The value N can be anywhere from 0 to 4. A value of 0 (the default) or 4 means constants of any size are allowed ๐
-mrelaxโ Turns on linker relaxation ๐ฆ That's when the linker tries to shrink your program by finding shorter versions of various instructions. It's disabled by default.-mint-register=Nโ Reserves a number of registers for fast interrupt handler functions ๐Ncan be between 0 and 4. A value of 1 reserves register "r13" for the exclusive use of fast interrupt handlers. A value of 2 reserves "r13" and "r12". A value of 3 reserves "r13", "r12" and "r11", and a value of 4 reserves "r13" through "r10". The default, 0, doesn't reserve anything at all ๐ธ-msave-acc-in-interruptsโ Tells interrupt handler functions to preserve the accumulator register ๐ซถ You only need this if your normal code might touch the accumulator, like if it does 64-bit multiplications. By default the accumulator gets ignored, which keeps the interrupt handlers faster โก-mpid,-mno-pidโ Turns on the generation of position independent data ๐ With it enabled, any access to constant data goes through 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 big win for embedded apps with tight memory constraints ๐ Data that can be modified isn't affected by this option.
Heads up though, this reserves a register (usually "r13") for the constant data base address, which can make code slower and/or bigger, especially in complicated functions ๐ญ
Which register actually gets chosen depends on whether -msmall-data-limit and/or -mint-register are enabled. Starting at "r13" and working downwards, registers are allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. So the small data area register can end up being "r8" if both -mint-register=4 and -mpid are on the command line ๐
By default this feature is not enabled. You can restore that default with the -mno-pid option โจ
-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 ๐ By default it warns about each extra one, because the RX only supports one such interrupt.-mallow-string-insns,-mno-allow-string-insnsโ Turns the string manipulation instructions on or off ๐งต That's "SMOVF", "SCMPU", "SMOVB", "SMOVU", "SUNTIL" "SWHILE", and also the "RMPA" instruction. These instructions may prefetch data, which is not safe if you're accessing an I/O register ๐ (Check out section 12.2.7 of the RX62N Group User's Manual for more info ๐)
These are allowed by default, but GCC can't reliably detect every case where a string instruction might touch an I/O register, so it can't turn them off automatically. It's up to you to use -mno-allow-string-insns if your program accesses I/O space ๐ซฃ
When the instructions are enabled, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. Otherwise it defines __RX_DISALLOW_STRING_INSNS__ ๐
-mjsr,-mno-jsrโ Uses only (or not only) "JSR" instructions to access functions ๐ This can help when your code size goes past the range of "BSR" instructions. Fun fact:-mno-jsrdoesn't mean "don't use JSR" ๐ It just means any type of branch may be used.
Note: the generic GCC command-line option-ffixed-reghas special meaning for the RX port when it's paired with the "interrupt" function attribute. That attribute marks a function meant to process fast interrupts. GCC makes sure it only uses "r10", "r11", "r12" and/or "r13", and only if the normal use of those registers has been restricted through-ffixed-regor-mint-register๐ซถ
โจ S/390 and zSeries Options โจ
These are the -m options defined for the S/390 and zSeries architecture ๐ง
-mhard-float,-msoft-floatโ Lets you use (or not 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, GCC generates IEEE floating-point instructions. This is the default ๐-mhard-dfp,-mno-hard-dfpโ Lets you use (or not use) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐ข With-mno-hard-dfp, functions inlibgcc.ahandle the decimal-floating-point stuff. With-mhard-dfp, GCC generates the 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 for debugging 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 ๐งต
Generally, code compiled with -mbackchain is call-compatible with code compiled with -mno-backchain. But using the backchain for debugging usually means the whole binary needs to be built with -mbackchain ๐ Also, the combo of -mbackchain, -mpacked-stack and -mhard-float is not supported ๐ If you want to build a linux kernel, use -msoft-float instead.
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 ๐ธ However, when-mbackchainis 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: 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 combo 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๐-mzarch,-mesaโ With-mzarch, GCC generates code using the instructions available on z/Architecture โจ With-mesa, it uses 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. For the GNU/Linux for zSeries ABI, the default is-mzarch๐-mhtm,-mno-htmโ The-mhtmoption turns on a set of builtins that use instructions from the transactional execution facility, which was introduced with the IBM zEnterprise EC12 machine generation. These are the S/390 System z Built-in Functions ๐ง-mhtmis enabled by default when using-march=zEC12๐ฅ-mvx,-mno-vxโ okay so-mvxtells GCC to generate code using the vector extension facility instructions that came with 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 are used somewhere the ABI cares about, GCC adds a GAS.gnu_attributecommand so the finished binary is marked with the ABI it used. And-mvxis turned on by default when you use-march=z13โจ-mzvector,-mno-zvectorโ bestie,-mzvectorunlocks vector language extensions and builtins, using those same z13 vector instructions ๐ It lets you usevectoras a keyword to define vector type variables and arguments. Butvectoronly works when GNU extensions are on, so it won't expand if you ask for strict standard compliance, like with-std=c99. On top of the GCC low-level builtins,-mzvectoralso adds a set of builtins made for compatibility with AltiVec-style implementations like Power and Cell ๐ To use them, you need to include the header filevecintrin.h.-mzvectoris disabled by default, so you have to ask for it ๐-mmvcle,-mno-mvcleโ-mmvclemakes GCC generate code that uses the "mvcle" instruction for block moves, and-mno-mvcleswaps that out for a "mvc" loop instead ๐ The default is the "mvcle" version, unless you're optimizing for size.-mdebug,-mno-debugโ-mdebugmakes the compiler print extra debug information while it's compiling, and-mno-debugkeeps it quiet. By default, no debug info gets printed ๐ง-march=cpu-typeโ this tells GCC to generate code that runs on cpu-type, which is just 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.
Picking native as your cpu type lets GCC choose the best architecture option for the host processor ๐ Heads up, though: -march=native does nothing if GCC doesn't recognize the processor.
-mtune=cpu-typeโ this tunes everything applicable about the generated code to cpu-type, except for the ABI and the set of available instructions โจ The list of cpu-type values is the same as for-march. The default is whatever value you used for-march.-mtpf-trace,-mno-tpf-traceโ-mtpf-tracemakes the code add TPF OS specific branches to trace routines in the operating system, and-mno-tpf-tracemeans it doesn't add them ๐ฆ This one is off by default, even when you're compiling for the TPF OS.-mtpf-trace-skip,-mno-tpf-trace-skipโ with-mtpf-trace-skip, the generated code changes the default branch targets enabled by-mtpf-traceso they point to specialized trace routines. That gives you the power to selectively skip function trace entries for the TPF OS ๐ With-mno-tpf-trace-skip, those targets stay the same. This is off by default, even when you're compiling for the TPF OS and specifying-mtpf-trace.-mfused-madd,-mno-fused-maddโ-mfused-maddlets the code use the floating-point multiply and accumulate instructions, and-mno-fused-maddtells it not to ๐ These instructions get generated by default when hardware floating point is used.-mwarn-framesize=framesizeโ this makes GCC emit a warning if the current function goes over the given frame size ๐ฅ It's a compile-time check, so it doesn't mean your program is actually broken when it runs. It's meant to spot functions that will most likely cause a stack overflow, so it's super useful in environments with a limited stack size, like the Linux kernel.-mwarn-dynamicstackโ emits a warning if the function callsallocaor uses dynamically-sized arrays ๐ That's generally a bad idea when the stack size is limited, so this one's giving caution.-mstack-guard=stack-guard,-mstack-size=stack-sizeโ okay this one is lowkey intense ๐ญ If you give these options, the S/390 back end adds extra instructions to the function prologue that trigger a trap when the stack size goes stack-guard bytes above the stack-size (remember, the stack on S/390 grows downward). If you leave out-mstack-guard, GCC picks the smallest power of 2 that's bigger 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's fine for production-like systems without a big performance hit. The 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. And-mstack-guardcan only be used together with-mstack-size๐-mhotpatch=pre-halfwords,post-halfwordsโ if the hotpatch option 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, maximum 1000000). After the label, 2 * post-halfwords bytes get appended, using the largest NOP-like instructions the architecture allows (maximum 1000000).
If both arguments are zero, hotpatching is disabled.
You can override this for individual functions with the "hotpatch" attribute โจ
โจ 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โ generates code for the SH2a without an FPU, or for a SH2a-FPU in a way that the floating-point unit isn't used ๐ฆ-m2a-single-onlyโ generates code for the SH2a-FPU so that no double-precision floating-point operations are used ๐ฆ-m2a-singleโ generates code for the SH2a-FPU, assuming the floating-point unit is in single-precision mode by default ๐ฆ-m2aโ generates code for the SH2a-FPU, assuming the floating-point unit is in double-precision mode by default ๐ฆ-m3โ generates code for the SH3 ๐-m3eโ generates code for the SH3e ๐-m4-nofpuโ generates code for the SH4 without a floating-point unit ๐ธ-m4-single-onlyโ generates code for the SH4 with a floating-point unit that only supports single-precision arithmetic ๐ธ-m4-singleโ generates code for the SH4, assuming the floating-point unit is in single-precision mode by default ๐ธ-m4โ generates code for the SH4 ๐ธ-m4-100โ generates code for SH4-100 ๐-m4-100-nofpuโ generates code for SH4-100 in a way that the floating-point unit isn't used ๐-m4-100-singleโ generates code for SH4-100, assuming the floating-point unit is in single-precision mode by default ๐-m4-100-single-onlyโ generates code for SH4-100 so that no double-precision floating-point operations are used ๐-m4-200โ generates code for SH4-200 ๐ซถ-m4-200-nofpuโ generates code for SH4-200 without, like, in a way that the floating-point unit isn't used ๐ซถ-m4-200-singleโ generates code for SH4-200, assuming the floating-point unit is in single-precision mode by default ๐ซถ-m4-200-single-onlyโ generates code for SH4-200 so that no double-precision floating-point operations are used ๐ซถ-m4-300โ generates code for SH4-300 ๐ง-m4-300-nofpuโ generates code for SH4-300 without, again, the floating-point unit being used ๐ง-m4-300-singleโ generates code for SH4-300 so that no double-precision floating-point operations are used ๐ง-m4-300-single-onlyโ generates code for SH4-300 so that no double-precision floating-point operations are used ๐ง-m4-340โ generates code for SH4-340 (no MMU, no FPU) ๐-m4-500โ generates code for SH4-500 (no FPU). It also passes-isa=sh4-nofputo the assembler ๐-m4a-nofpuโ generates code for the SH4al-dsp, or for a SH4a in a way that the floating-point unit isn't used ๐-m4a-single-onlyโ generates code for the SH4a so that no double-precision floating-point operations are used ๐-m4a-singleโ generates code for the SH4a, assuming the floating-point unit is in single-precision mode by default ๐-m4aโ generates code for the SH4a โญ-m4alโ same as-m4a-nofpu, except it implicitly passes-dspto the assembler. GCC doesn't generate any DSP instructions at the moment, so don't expect them ๐-mbโ compiles code for the processor in big-endian mode ๐-mlโ compiles code for the processor in little-endian mode ๐-mdalignโ aligns doubles at 64-bit boundaries ๐ซถ
Heads up, bestie: this changes the calling conventions, so some functions from the standard C library won't work unless you recompile them first with -mdalign ๐ญ
-mrelaxโ shortens some address references at link time, when it's possible. It uses the linker option-relaxโจ-mbigtableโ uses 32-bit offsets in "switch" tables. The default is 16-bit offsets ๐-mbitopsโ enables the use of bit manipulation instructions on SH2A ๐-mfmovdโ enables the use of the instruction "fmovd". Check-mdalignfor the alignment constraints ๐-mrenesasโ makes the code comply with the calling conventions defined by Renesas ๐-mno-renesasโ makes the code comply with the calling conventions GCC used before the Renesas conventions were available. This is the default for all targets of the SH toolchain ๐-mnomacsaveโ marks the "MAC" register as call-clobbered, even if-mrenesasis given ๐ฆ-mieee,-mno-ieeeโ these control the IEEE compliance of floating-point comparisons, which affects how cases where a comparison result is unordered get handled ๐ฅ By default,-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled,-mno-ieeeis implicitly set, which makes floating-point greater-equal and less-equal comparisons faster โญ The implicit settings can be overridden by specifying either-mieeeor-mno-ieee๐
โจ MACHINE-DEPENDENT OPTIONS โจ
-minline-ic_invalidate๐ง โ okay so this one inlines code that invalidates instruction cache entries right after the compiler sets up nested function trampolines. It does nothing if-musermodeis on and your chosen code generation option (like-m4) doesn't allow theicbiinstruction. If your code generation option doesn't allowicbiand-musermodeisn't on, the inlined code pokes the instruction cache address array directly with an associative write. That needs privileged mode at run time, and it breaks if the cache line was mapped through the TLB and got unmapped. ๐-misize๐ โ dumps the instruction size and location into the assembly code. Very useful if you're a size-obsessed girlie ๐-mpadstruct๐ โ this one is deprecated, so please don't start new projects with it ๐ญ. It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI.-matomic-model=model๐ โ sets the model of atomic operations, plus extra parameters, as a comma separated list. For the full tea on atomic built-in functions, check out __atomic Builtins. These are the models and parameters you can pick from:none๐ซฅ โ disables compiler generated atomic sequences and emits library calls for atomic operations instead. This is the default if the target is notsh*-*-linux*.soft-gusaโจ โ generates GNU/Linux compatible gUSA software atomic sequences for the atomic built-in functions. These sequences need extra help from the interrupt/exception handling code of the system, and they're only suitable for SH3* and SH4* single-core systems. This option is on by default when the target issh*-*-linux*and SH3* or SH4*. When the target is SH4A, it also partially uses the hardware atomic instructionsmovli.landmovco.lto make the code more efficient, unlessstrictis specified.soft-tcb๐ โ generates software atomic sequences that use a variable in the thread control block. It's a variation of the gUSA sequences that can also run on SH1* and SH2* targets. These sequences also need extra support from the interrupt/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 disable interrupts by settingSR.IMASK = 1111. This model only works when the program runs in privileged mode and is only suitable for single-core systems. It doesn't need extra support from the interrupt/exception handling code. It's on by default when the target issh*-*-linux*and SH1* or SH2*.hard-llcs๐ฅ โ generates hardware atomic sequences using only themovli.landmovco.linstructions. This is only available on SH4A and is suitable for multi-core systems. The hardware instructions only support 32 bit atomic variables, so 8 or 16 bit variables get emulated with 32 bit accesses. Code compiled with this is also compatible with other software atomic model interrupt/exception handling systems if it runs on an SH4A system. This model doesn't need any extra support from the interrupt/exception handling code.gbr-offset=๐ฆ โ specifies the offset in bytes of the variable in the thread control block structure that the generated atomic sequences should use when thesoft-tcbmodel is selected. For other models this parameter is ignored. The value must be an integer multiple of four and in the range 0-1020.strict๐ โ prevents mixing multiple atomic models, even if they're compatible, and makes the compiler generate atomic sequences of the specified model only.
-mtas๐ โ generates thetas.bopcode for__atomic_test_and_set. Heads up: depending on your hardware and software setup, this can tank overall performance because of the operand cache line flushes that thetas.binstruction implies. On multi-core SH4A processors,tas.bhas to be used with caution, since it can corrupt data for certain cache configurations. ๐ฌ-mprefergot๐ธ โ when generating position-independent code, emits function calls through the Global Offset Table instead of the Procedure Linkage Table.-musermode,-mno-usermode๐ โโ๏ธ โ-mno-usermodemeans the compiler is not allowed to generate privileged mode code, and-musermodemeans it is not allowed... wait, babe, let me be precise:-musermodesays don't allow the compiler to generate privileged mode code, and-mno-usermodeallows it.-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, since there is no user mode there.-multcost=numberโ๏ธ โ sets the cost the compiler assumes for a multiply instruction.-mdiv=strategyโ โ sets the division strategy for integer division operations.strategycan be one of these:call-div1๐ โ calls a library function that uses the single-step division instructiondiv1to do the operation. 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 FPU. If you pick this for targets without a double precision FPU, it falls back tocall-div1.call-table๐๏ธ โ calls a library function that uses a lookup table for small divisors, and thediv1instruction with case distinction for bigger divisors. Dividing by zero gives an unspecified result and doesn't trap. This is the default for SH4. If you pick this for targets without dynamic shift instructions, it falls back tocall-div1.
When you don't specify a division strategy, the compiler picks a default 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๐ฆ โ reserves space once for outgoing arguments in the function prologue, instead of around each call. This is usually great for performance and size. It's also needed for unwinding, so the stack frame doesn't change around conditional code.-mdivsi3_libfunc=name๐ท๏ธ โ sets the name of the library function used for 32-bit signed division toname. This only changes the name used in the call division strategies. The compiler still expects the same sets of input/output/clobbered registers as if this option weren't there.-mfixed-range=register-range๐งฑ โ makes the compiler treat the given register range as fixed registers. A fixed register is one the register allocator isn't allowed to use. This is handy when you're compiling kernel code. A register range is two registers separated by a dash, and you can list multiple ranges separated by a comma.-mbranch-cost=num๐ฟ โ assumesnumis the cost of a branch instruction. Higher numbers make the compiler try harder to generate branch-free code when it can. If you don't specify it, the value is picked based on the processor type you're compiling for.-mzdcbranch,-mno-zdcbranchโก โ-mzdcbranchassumes zero displacement conditional branch instructionsbtandbfare fast, so the compiler prefers zero displacement branch code sequences.-mno-zdcbranchsays that assumption doesn't hold. This is on by default for SH4 and SH4A, and you can turn it off explicitly with-mno-zdcbranch.-mcbranch-force-delay-slot๐ข โ forces the use of delay slots for conditional branches. If no suitable instruction is found, the delay slot gets stuffed with anop. This option is disabled by default. Turn it on to work around hardware bugs like the ones found in the original SH7055.-mfused-madd,-mno-fused-madd๐ง โ-mfused-maddgenerates code that uses the floating-point multiply and accumulate instructions, and-mno-fused-maddgenerates code that doesn't. These instructions are generated by default if hardware floating point is used. The machine-dependent-mfused-maddoption is now mapped to the machine-independent-ffp-contract=fastoption, and-mno-fused-maddis mapped to-ffp-contract=off.-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.-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 together with-funsafe-math-optimizationsand-ffinite-math-only. It's enabled by default when generating code for SH4A.-mno-fsrradisables reciprocal square root approximations even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect.-mpretend-cmove๐ญ โ prefers zero-displacement conditional branches for conditional move instruction patterns. This can make code run faster on the SH4 processor.-mfdpic๐ โ generates code using the FDPIC ABI.
๐ Solaris 2 Options ๐
These -m options are supported on Solaris 2 ๐
-mclear-hwcap๐งน โ tells the compiler to remove the hardware capabilities that the Solaris assembler generated. You only need this when object files use ISA extensions the current machine doesn't support, but they check at runtime whether or not to use them.-mimpure-text๐ฆ โ used together with-shared, this tells 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.
Okay so, -mimpure-text is the one that silences the "relocations remain against allocatable but non-writable sections" linker error ๐ but bestie, it's a trap. The relocations trigger copy-on-write, so the shared object isn't actually shared across processes anymore ๐ The move is to compile all your source with -fpic or -fPIC instead โจ
These switches also work on Solaris 2, on top of everything above:
-pthreadsโ literally just a synonym for-pthread๐ง
โจ SPARC Options โจ
These -m options are supported on the SPARC ๐
-mno-app-regs,-mapp-regsโ-mapp-regsis the default and it's giving reserved vibes ๐ซถ It makes the compiler use global registers 2 through 4, which the SPARC SVR4 ABI sets aside for applications. Just like global register 1, each of 2 through 4 is treated as an allocable register that function calls are allowed to clobber. If you want to be fully SVR4 ABI-compliant and you don't mind a bit of performance loss, go with-mno-app-regs. Libraries and system software should be compiled with this one ๐-mflat,-mno-flatโ With-mflat, the compiler skips the save/restore instructions and uses a "flat" single register window model ๐ฆ That's compatible with the regular register window model. The local registers and the input registers (0--5) are still treated as "call-saved" and get saved on the stack when needed.-mno-flatis the default, and it generates save/restore instructions everywhere except leaf functions. That's the normal operating mode ๐-mfpu,-mhard-floatโ generates output with floating-point instructions. This is the default ๐ฅ-mno-fpu,-msoft-floatโ generates output that calls library functions for floating point instead ๐ญ
Heads up: the required libraries aren't available for every SPARC target. Normally GCC borrows the facilities of the machine's usual C compiler, but that can't be done directly when cross-compiling, so you need to sort out your own suitable library functions for cross-compilation. The embedded targetssparc-*-aoutandsparclite-*-*do come with software floating-point support.
-msoft-float changes the calling convention in the output file, so it only makes sense if you compile the whole program with it. Specifically, libgcc.a, the library that ships with GCC, has to be built with -msoft-float for this to work ๐
-mhard-quad-floatโ generates output with quad-word (long double) floating-point instructions ๐-msoft-quad-floatโ generates output that calls library functions for quad-word (long double) floating-point instructions. Those functions are the ones defined in the SPARC ABI, and this is the default ๐
As of this writing, no SPARC implementations have hardware support for the quad-word floating-point instructions ๐ Every one of them hits a trap handler for these instructions, and then the trap handler emulates what the instruction would have done. Because of that trap handler overhead it's way slower than calling the ABI library routines, which is exactly why -msoft-quad-float is the default โจ
-mno-unaligned-doubles,-munaligned-doublesโ-mno-unaligned-doublesis the default, and it assumes doubles have 8-byte alignment ๐
With -munaligned-doubles, GCC only assumes 8-byte alignment for doubles if they're contained in another type or have an absolute address. Otherwise it assumes 4-byte alignment. Using this option helps dodge some rare compatibility problems with code from other compilers, but it's not the default because it costs performance, especially in floating-point code ๐ฅบ
-muser-mode,-mno-user-modeโ-mno-user-modeis the default, and it means no code that can only run in supervisor mode gets generated ๐ This only matters for the "casa" instruction emitted for the LEON3 processor.-mfaster-structs,-mno-faster-structsโ With-mfaster-structs, the compiler assumes structures should have 8-byte alignment. That unlocks pairs of "ldd" and "std" instructions for copies in structure assignment, instead of twice as many "ld" and "st" pairs โก BUT the changed alignment directly violates the SPARC ABI, so it's only meant for targets where the developer knows and accepts that the code doesn't follow the ABI rules ๐-mstd-struct-return,-mno-std-struct-returnโ With-mstd-struct-return, the compiler generates checking code in functions that return structures or unions, so it can catch size mismatches between the two sides of a function call, as the 32-bit ABI requires ๐ The default is-mno-std-struct-return, and this option does nothing in 64-bit mode.-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for the machine type cpu_type โจ The supported values arev7,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 accept native, which picks the best architecture option for your host processor ๐ง If GCC doesn't recognise the processor, -mcpu=native does nothing.
For values that name an architecture rather than a specific implementation (v7, v8, sparclite, sparclet, v9), GCC uses the default instruction scheduling parameters ๐
Here's the full breakdown of each architecture and the implementations it covers:
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3,leon5sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless it's been configured otherwise), GCC generates V7 code ๐ธ With -mcpu=cypress, it also optimises for the Cypress CY7C602 chip, the one in the SPARCStation/SPARCServer 3xx series. That's also a good fit for the older SPARCStation 1, 2, IPX and friends.
With -mcpu=v8, GCC generates V8 code. The only real difference from V7 is that it emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not SPARC-V7 โก With -mcpu=supersparc, it also optimises for the SuperSPARC chip, found in the SPARCStation 10, 1000 and 2000 series.
With -mcpu=sparclite, GCC generates code for the SPARClite variant. That adds the integer multiply, integer divide step and scan ("ffs") instructions, which SPARClite has but SPARC-V7 doesn't ๐ฆ With -mcpu=f930, it also optimises for the Fujitsu MB86930, the original SPARClite, which has no FPU. With -mcpu=f934, it optimises for the Fujitsu MB86934, the newer SPARClite that does have an FPU.
With -mcpu=sparclet, GCC generates code for the SPARClet variant. That adds integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions, all things SPARClet has and SPARC-V7 doesn't ๐ With -mcpu=tsc701, it also optimises for the TEMIC SPARClet chip.
With -mcpu=v9, GCC generates V9 code, which adds 64-bit integer and floating-point move instructions, 3 extra floating-point condition code registers and conditional move instructions ๐ With -mcpu=ultrasparc, it also optimises for the Sun UltraSPARC I/II/IIi chips. -mcpu=ultrasparc3 targets the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips. -mcpu=niagara targets Sun UltraSPARC T1 chips, -mcpu=niagara2 targets Sun UltraSPARC T2 chips, -mcpu=niagara3 targets Sun UltraSPARC T3 chips, and -mcpu=niagara4 targets Sun UltraSPARC T4 chips. -mcpu=niagara7 optimises for Oracle SPARC M7 chips, and -mcpu=m8 optimises for Oracle M8 chips ๐
-mtune=cpu_typeโ sets the instruction scheduling parameters for the machine type cpu_type, but leaves alone the instruction set and register set that-mcpu=cpu_typewould set ๐
The same values work for -mtune=cpu_type as for -mcpu=cpu_type, but only the ones that pick a specific 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. On native Solaris and GNU/Linux toolchains you can use native here too ๐ง
-mv8plus,-mno-v8plusโ-mv8plusmakes GCC generate 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 on by default on Solaris in 32-bit mode for all SPARC-V9 processors.-mvis,-mno-visโ-mvismakes GCC generate code that takes advantage of the UltraSPARC Visual Instruction Set extensions โจ The default is-mno-vis.-mvis2,-mno-vis2โ-mvis2makes GCC use version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐ฆ The default is-mvis2when you're targeting a CPU that supports those instructions, like UltraSPARC-III and later. Setting-mvis2also sets-mvis.-mvis3,-mno-vis3โ-mvis3makes GCC use version 3.0 of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mvis3when you're targeting a CPU that supports those, like niagara-3 and later. Setting-mvis3also sets-mvis2and-mvis.-mvis3b,-mno-vis3bโ okay bestie,-mvis3btells GCC to write code that uses version 3.0 of the UltraSPARC Visual Instruction Set extensions, plus the extra VIS instructions from the Oracle SPARC Architecture 2011 ๐ฆ. It's on by default when you target a cpu that supports them, like niagara-7 and later. Turning it on also turns on-mvis3,-mvis2and-mvisโจ.-mvis4,-mno-vis4โ-mvis4gets GCC generating code for version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐ . It's the default when targeting a cpu that supports them, such as niagara-7 and later. Setting-mvis4also sets-mvis3b,-mvis3,-mvis2and-mvis๐ธ.-mvis4b,-mno-vis4bโ-mvis4bis giving version 4.0 of the UltraSPARC Visual Instruction Set extensions, plus the additional VIS instructions from the Oracle SPARC Architecture 2017 ๐ฅ. It's the default when targeting a cpu that supports them, such as m8 and later. Setting-mvis4balso sets-mvis4,-mvis3b,-mvis3,-mvis2and-mvis๐.-mcbcond,-mno-cbcondโ-mcbcondmakes GCC use the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ง. It's on by default when targeting a CPU that has them, like Niagara-4 and later.-mfmaf,-mno-fmafโ-mfmaflets GCC use the UltraSPARC Fused Multiply-Add Floating-point instructions ๐. Default when targeting a CPU that supports them, such as Niagara-3 and later.-mfsmuld,-mno-fsmuldโ-mfsmuldhas GCC take advantage of the Floating-point Multiply Single to Double (FsMULd) instruction ๐. It's the default when targeting a CPU supporting the architecture versions V8 or V9 with FPU, except-mcpu=leon.-mpopc,-mno-popcโ-mpopchas GCC using the UltraSPARC Population Count instruction ๐. Default when targeting a CPU that has one, such as Niagara-2 and later.-msubxc,-mno-subxcโ-msubxcopts into the UltraSPARC Subtract-Extended-with-Carry instruction ๐. It's the default when targeting a CPU that supports it, such as Niagara-7 and later.-mfix-at697fโ turns on the documented workaround for the single erratum of the Atmel AT697F processor, which is erratum #13 of the AT697E processor ๐.-mfix-ut699โ turns on the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor โจ.-mfix-ut700โ turns on the documented workaround for the back-to-back store errata of the UT699E/UT700 processor ๐ซถ.-mfix-gr712rcโ turns on 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 one setsint,longand pointer to 32 bits. The 64-bit one setsintto 32 bits andlongand pointer to 64 bits.-mcmodel=whichโ sets the code model to one of these: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 ๐ฅ. 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 on the processor to one of these: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, and they're set in the processor's "PSTATE.MM" field ๐ซถ.
-mstack-bias,-mno-stack-biasโ-mstack-biastells GCC to assume the stack pointer, and the frame pointer if there is one, are offset by-2047, which has to be added back when making stack frame references ๐. This is the default in 64-bit mode. Otherwise, GCC 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's recommended to use-symbolicor-sharedinstead.-Qyโ identifies the versions of each tool used by the compiler, in a".ident"assembler directive in the output ๐ง.-Qnโ refrains from adding".ident"directives to the output file, which is the default ๐ธ.-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โ-mno-epmeans do not optimize basic blocks that use the same index pointer 4 or more times to copy the pointer into the"ep"register, and use the shorter"sld"and"sst"instructions ๐.-mepmeans do optimize them. The-mepoption is on by default if you optimize โจ.-mno-prolog-function,-mprolog-functionโ-mno-prolog-functionmeans do not use external functions to save and restore registers at the prologue and epilogue of a function ๐.-mprolog-functionmeans do use them. The external functions are slower, but they use less code space if more than one function saves the same number of registers. The-mprolog-functionoption is on by default if you optimize ๐.-mspaceโ tries to make the code as small as possible ๐. At present, this just turns on the-mepand-mprolog-functionoptions.-mtda=nโ puts static or global variables whose size isnbytes or less into the tiny data area that register"ep"points to ๐ง. The tiny data area can hold up to 256 bytes in total (128 bytes for byte references).-msda=nโ puts static or global variables whose size isnbytes or less into the small data area that register"gp"points to ๐ธ. The small data area can hold up to 64 kilobytes.-mzda=nโ puts static or global variables whose size isnbytes or less into the first 32 kilobytes of memory ๐ฆ.-mv850โ specifies that the target processor is the V850 ๐ฅ.-mv850e3v5โ specifies that the target processor is the V850E3V5 ๐. The preprocessor constant"__v850e3v5__"is defined if this option is used.-mv850e2v4โ specifies that the target processor is the V850E3V5 ๐ . This is an alias for the-mv850e3v5option.-mv850e2v3โ specifies that the target processor is the V850E2V3 ๐. The preprocessor constant"__v850e2v3__"is defined if this option is used.-mv850e2โ specifies that the target processor is the V850E2 ๐. The preprocessor constant"__v850e2__"is defined if this option is used.-mv850e1โ specifies that the target processor is the V850E1 โจ. The preprocessor constants"__v850e1__"and"__v850e__"are defined if this option is used.-mv850esโ specifies that the target processor is the V850ES ๐ซถ. This is an alias for the-mv850e1option.-mv850eโ specifies that the target processor is the V850E ๐. The preprocessor constant"__v850e__"is defined if this option is used.
If neither -mv850 nor -mv850e nor -mv850e1 nor -mv850e2 nor -mv850e2v3 nor -mv850e3v5 are defined, then a default target processor is chosen and the relevant __v850*__ preprocessor constant is defined ๐ง.
The preprocessor constants "__v850" and "__v851__" are always defined, regardless of which processor variant is the target ๐.
-mdisable-callt,-mno-disable-calltโ-mdisable-calltsuppresses generation of the"CALLT"instruction for the v850e, v850e1, v850e2, v850e2v3 and v850e3v5 flavors of the v850 architecture ๐ธ.
This option is enabled by default when the RH850 ABI is in use (see -mrh850-abi), and disabled by default when the GCC ABI is in use ๐ฆ. If "CALLT" instructions are being generated, then the C preprocessor symbol "__V850_CALLT__" is defined.
-mrelax,-mno-relaxโ passes on (or does not pass on) the-mrelaxcommand-line option to the assembler ๐ฅ.-mlong-jumps,-mno-long-jumpsโ-mlong-jumpsdisables the generation of PC-relative jump instructions, and-mno-long-jumpsre-enables them ๐.-msoft-float,-mhard-floatโ-msoft-floatdisables the generation of hardware floating point instructions, and-mhard-floatre-enables them ๐ . This option is only significant when the target architecture is V850E2V3 or higher. If hardware floating point instructions are being generated, then the C preprocessor symbol"__FPU_OK__"is defined; otherwise the symbol"__NO_FPU__"is defined ๐.-mloopโ enables the use of the e3v5LOOPinstruction ๐. The use of this instruction is not enabled by default when the e3v5 architecture is selected, because its use is still experimental โ ๏ธ.-mrh850-abi,-mghsโ enables support for the RH850 version of the V850 ABI โจ. This is the default. With this version of the ABI, the following rules apply:- Integer sized structures and unions are returned via a memory pointer rather than a register ๐ซถ.
- Large structures and unions (more than 8 bytes in size) are passed by value. ๐
- Functions are 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 version of the ABI is enabled, the C preprocessor symbol "__V850_RH850_ABI__" gets defined. ๐
-mgcc-abiโ okay so this one turns on the old GCC version of the V850 ABI ๐ฐ๏ธ ๐ With this version, these rules apply:- Integer sized structures and unions are returned in register
"r10". ๐ - Large structures and unions (more than 8 bytes in size) are passed by reference. ๐ฆ
- Functions are 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. โญ
- Integer sized structures and unions are returned in register
When this version of the ABI is enabled, the C preprocessor symbol "__V850_GCC_ABI__" gets defined. ๐ง
-m8byte-align,-mno-8byte-alignโ enables"double"and"long long"types to be aligned on 8-byte boundaries, bestie ๐ The default is to keep the alignment of all objects to at most 4-bytes. When-m8byte-alignis in effect, the C preprocessor symbol"__V850_8BYTE_ALIGN__"gets defined. โจ-mbig-switchโ generates code that's suitable for big switch tables. Only use this one if the assembler/linker complains about out of range branches within a switch table. ๐ญ-mapp-regsโ makesr2andr5get used in the code the compiler generates. This is the default, so you're already set ๐-mno-app-regsโ makesr2andr5get treated as fixed registers. ๐
๐ท VAX Options ๐ท
These -m options are defined for the VAX. ๐ฆ
-munixโ don't output certain jump instructions ("aobleq"and so on) that the Unix assembler for the VAX can't handle across long ranges. ๐ โโ๏ธ-mgnuโ do output those jump instructions, on the assumption that the GNU assembler is being used. ๐ง-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. This is still experimental for the VAX, so by default the compiler uses standard reload. ๐งช
๐ธ Visium Options ๐ธ
-mdebugโ a program that does file I/O and is destined to run on an MCM target should be linked with this option. It causes the librarieslibc.aandlibdebug.ato be linked. The program should be run on the target under the control of the GDB remote debugging stub. ๐ง-msimโ a program that does file I/O and is destined to run on the simulator should be linked with option. This causes the librarieslibc.aandlibsim.ato be linked. ๐ฎ-mfpu,-mhard-floatโ generates code containing floating-point instructions. This is the default. ๐ฅ-mno-fpu,-msoft-floatโ generates code containing library calls for floating-point. ๐งฎ
โ ๏ธ bestie,-msoft-floatchanges 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 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 machine type cpu_type. Supported values for cpu_type aremcm,gr5andgr6. ๐mcmis a synonym ofgr5, 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 machine type cpu_type, but does not 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, registersr24tor31cannot 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 from"main". The default is to return POSIX-style condition (e.g. error) codes. ๐งพ-mdebug-main=prefixโ flags the first routine whose name starts with prefix as the main routine for the debugger. ๐-mmalloc64โ defaults to 64-bit memory allocation routines. ๐ง-mpointer-size=sizeโ sets the default size of pointers. Possible options for size are32orshortfor 32 bit pointers,64orlongfor 64 bit pointers, andnofor supporting only 32 bit pointers. The latter option disables"pragma 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โ GCC can generate code for both VxWorks kernels and real time processes (RTPs). This option switches from the former to the latter. It also defines the preprocessor macro"__RTP__". ๐ฆ-msmpโ selects SMP runtimes for linking. Not available on architectures other than PowerPC, nor on VxWorks version 7 or later, where the selection is part of the VxWorks build configuration and the library paths are the same for either choice. ๐ โโ๏ธ-non-staticโ links an RTP executable against shared libraries rather than static libraries. The options-staticand-sharedcan also be used for RTPs;-staticis the default. ๐-Bstatic,-Bdynamicโ these options are passed down to the linker. They're defined for compatibility with Diab. ๐ค-Xbind-lazyโ enables lazy binding of function calls. This option is equivalent to-Wl,-z,nowand is defined for compatibility with Diab. ๐ข-Xbind-nowโ disables lazy binding of function calls. This option is the default and is defined for compatibility with Diab. โก
๐ฆ x86 Options ๐ฆ
These -m options are defined for the x86 family of computers. ๐ป
-march=cpu-typeโ generates instructions for the machine type cpu-type. Unlike-mtune=cpu-type, which merely tunes the generated code for the specified cpu-type,-march=cpu-typeallows GCC to generate code that may not run at all on processors other than the one indicated. Specifying-march=cpu-typeimplies-mtune=cpu-type, except where noted otherwise. ๐๏ธ
The choices for cpu-type are:
nativeโ selects the CPU to generate code for at compilation time by figuring out the processor type of the compiling machine. Using-march=nativeenables all instruction subsets supported by the local machine (so the result might not run on different machines). Using-mtune=nativeproduces 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 choices 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 as the x86-64 psABI documents for the particular micro-architecture level.
Since these cpu-type values don't have a corresponding -mtune setting, using -march with these values enables generic tuning. Specific tuning can be enabled using the -mtune=other-cpu-type option with an appropriate other-cpu-type value. ๐ฏ
i386โ the original Intel i386 CPU. ๐ฆi486โ the Intel i486 CPU. (No scheduling is implemented for this chip.) ๐i586,pentiumโ the Intel Pentium CPU with no MMX support. ๐ฟlakemontโ the Intel Lakemont MCU, based on the Intel Pentium CPU. ๐ฌpentium-mmxโ the Intel Pentium MMX CPU, based on the Pentium core with MMX instruction set support. ๐ตpentiumproโ the 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โ the Intel Pentium II CPU, based on the Pentium Pro core with MMX and FXSR instruction set support. ๐pentium3,pentium3mโ the Intel Pentium III CPU, based on the Pentium Pro core with MMX, FXSR and SSE instruction set support. ๐ปpentium-mโ the Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE, SSE2 and FXSR instruction set support. Used by Centrino notebooks. ๐ผpentium4,pentium4mโ the Intel Pentium 4 CPU with MMX, SSE, SSE2 and FXSR instruction set support. ๐ฉทprescottโ an improved version of the Intel Pentium 4 CPU with MMX, SSE, SSE2, SSE3 and FXSR instruction set support. ๐ทnoconaโ an improved version of the Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and FXSR instruction set support. ๐บcore2โ the Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, CX16, SAHF and FXSR instruction set support. โnehalem,corei7โ the 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โ the 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โ the 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, bestie! It comes 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. Vintage but still iconic โจ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. The AVX2 glow-up is so real ๐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. Lowkey underrated ๐ซถ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. It's giving a whole upgrade ๐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. Server girlies, this one's for you ๐ซถ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. Serving VNNI realness โจ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. Okay, the list is giving main character ๐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. BF16 is so cute, no cap ๐ฅน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. The feature drop is literally unreal ๐ญ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. Server edition with all the extras ๐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. Tiger Lake is a whole roar ๐ฅ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. Blast off, periodt ๐alderlake,raptorlake,meteorlake,gracemontโญ Intel Alder Lake/Raptor Lake/Meteor Lake/Gracemont 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 and AVX-VNNI instruction set support. Hybrid-core era, and it's so serious ๐ง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. Arrow sharp, bestie ๐ซarrowlake-s,lunarlake๐ Intel Arrow Lake S/Lunar 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, CMPCCXADD, AVXVNNIINT16, SHA512, SM3 and SM4 instruction set support. Two names, one slay ๐ฆpantherlake๐ Intel Panther 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 and PREFETCHI instruction set support. The ext list is literally endless โจsapphirerapids,emeraldrapids๐ Intel Sapphire Rapids/Emerald 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 and AVX512BF16 instruction set support. Sapphire and emerald, both gorgeous ๐ฅฐ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. Granite? More like granite-level strong ๐ช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. The D variant is the final boss ๐๐งdiamondrapidsโ Intel Diamond Rapids ๐ CPU, the full glam package: 64-bit extensions plusMOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,CX16,SAHF,FXSR,AVX,XSAVE,PCLMUL,FSGSBASE,RDRND,F16C,AVX2,BMI,BMI2,LZCNT,FMA,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,AMX-TRANSPOSE,MOVRS,AMX-MOVRSandUSER_MSRinstruction set support. โจbonnell,atomโ Intel Bonnell ๐ธ CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3andSSSE3instruction 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,PREFETCHWandRDRNDinstruction 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,CLFLUSHOPTandFSGSBASEinstruction 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,RDPIDandSGXinstruction 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,CLDEMOTEandWAITPKGinstruction 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,ENQCMDandUINTRinstruction 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,ENQCMDandUINTRinstruction 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_MSRandPREFETCHIinstruction set support.k6โ AMD K6 ๐ CPU, withMMXinstruction set support.k6-2,k6-3โ Upgraded versions of the AMD K6 CPU, withMMXand3DNow!instruction set support. ๐athlon,athlon-tbirdโ AMD Athlon CPU withMMX,3dNOW!, enhanced3DNow!and SSE prefetch instructions support. ๐ฅathlon-4,athlon-xp,athlon-mpโ The glow-up of the AMD Athlon CPU, withMMX,3DNow!, enhanced3DNow!and full SSE instruction set support. โจk8,opteron,athlon64,athlon-fxโ Processors built on the AMD K8 core withx86-64instruction set support, including the AMD Opteron, Athlon 64 and Athlon 64 FX processors. (This supersetsMMX,SSE,SSE2,3DNow!, enhanced3DNow!and 64-bit instruction set extensions.) ๐k8-sse3,opteron-sse3,athlon64-sse3โ Upgraded versions of the AMD K8 cores, withSSE3instruction set support. ๐ธamdfam10,barcelonaโ CPUs built on AMD Family 10h cores, withx86-64instruction set support. (This supersetsMMX,SSE,SSE2,SSE3,SSE4A,3DNow!, enhanced3DNow!,ABMand 64-bit instruction set extensions.) ๐ฆbdver1โ CPUs built on AMD Family 15h cores, withx86-64instruction set support. (This supersetsFMA4,AVX,XOP,LWP,AES,PCLMUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.) ๐ฅbdver2โ AMD Family 15h core based CPUs, withx86-64instruction set support. (This supersetsBMI,TBM,F16C,FMA,FMA4,AVX,XOP,LWP,AES,PCLMUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.) ๐bdver3โ AMD Family 15h core based CPUs, withx86-64instruction set support. (This supersetsBMI,TBM,F16C,FMA,FMA4,FSGSBASE,AVX,XOP,LWP,AES,PCLMUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.) ๐bdver4โ AMD Family 15h core based CPUs, withx86-64instruction set support. (This supersetsBMI,BMI2,TBM,F16C,FMA,FMA4,FSGSBASE,AVX,AVX2,XOP,LWP,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.) ๐znver1โ AMD Family 17h core based CPUs, withx86-64instruction set support. (This supersetsBMI,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 based CPUs, withx86-64instruction set support. (This supersetsBMI,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 based CPUs, withx86-64instruction set support. (This supersetsBMI,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 based CPUs, withx86-64instruction set support. (This supersetsBMI,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,GFNIand 64-bit instruction set extensions.) ๐ธznver5โ AMD Family 1ah core based CPUs, withx86-64instruction set support. (This supersetsBMI,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,PREFETCHIand 64-bit instruction set extensions.) ๐งbtver1โ CPUs built on AMD Family 14h cores, withx86-64instruction set support. (This supersetsMMX,SSE,SSE2,SSE3,SSSE3,SSE4A,CX16,ABMand 64-bit instruction set extensions.) ๐ทbtver2โ CPUs built on AMD Family 16h cores, withx86-64instruction set support. This includesMOVBE,F16C,BMI,AVX,PCLMUL,AES,SSE4.2,SSE4.1,CX16,ABM,SSE4A,SSSE3,SSE3,SSE2,SSE,MMXand 64-bit instruction set extensions. ๐winchip-c6โ IDT WinChip C6 CPU ๐งธ, handled the same way asi486, with additionalMMXinstruction set support.winchip2โ IDT WinChip 2 CPU ๐ผ, handled the same way asi486, with additionalMMXand3DNow!instruction set support.c3โ VIA C3 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.) ๐c3-2โ VIA C3-2 (Nehemiah/C5XL) CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.) ๐ซงc7โ VIA C7 (Esther) CPU withMMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) ๐samuel-2โ VIA Eden Samuel 2 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.) ๐ฆnehemiahโ VIA Eden Nehemiah CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.) ๐estherโ VIA Eden Esther CPU withMMX,SSE,SSE2andSSE3instruction 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 and RDSEED instruction set support. The chips do support AVX and F16C, but-march=lujiazuidoesn't turn those 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 and 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 and LZCNT instruction set support. ๐geodeโ ๐ธ AMD Geode embedded processor with MMX and 3DNow! instruction set support.
-mtune=cpu-typeโ ๐ Tunes everything that can be tuned in the generated code to cpu-type, except for the ABI and the set of available instructions. Picking a specific cpu-type schedules things for that exact chip, but the compiler won't generate anything that can't run on the default machine type, unless you also use a-march=cpu-typeoption. For example, if GCC is configured fori686-pc-linux-gnu, then-mtune=pentium4makes 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 that,-mtunehas 2 extra choices: genericโ Produces code optimized 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 CPU your users will have, this is the one to pick. โจ- As new processors hit the market, what this option does will change. So if you upgrade to a newer GCC, the code generated under this option will shift to match whatever processors are most common when that GCC version is released. ๐ฆ
- There's no
-march=generic, because-marchis about the instruction set the compiler can use, and there's no generic instruction set that works on every processor.-mtune, on the other hand, is about which processor (or, in this case, group of processors) the code is optimized for. ๐
intelโ Produces code optimized for the most current Intel processors, which for this version of GCC are Haswell and Silvermont. If you know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=intel. But if you want your application to perform well on both Haswell and Silvermont, this is your option. ๐- As new Intel processors come out, this option's behaviour will change. So if you upgrade to a newer GCC, the code generated will shift to reflect the most current Intel processors at the time that GCC version is released. ๐
- There's no
-march=intel, because-marchis about the instruction set, and there's no common instruction set shared by all Intel processors.-mtuneis about the processor (or group of processors) the code is optimized for. ๐ง
- The choices for cpu-type are the same as for
-mcpu=cpu-typeโ ๐ฅ A deprecated synonym for-mtune. Honestly, just use-mtuneinstead. ๐-mfpmath=unitโ ๐ฅ Generates floating-point arithmetic using the selected unit. The choices for unit are:387โ Uses the standard 387 floating-point coprocessor found on most chips, and emulates it where there isn't one. Code built with this runs almost everywhere. Temporary results are computed in 80-bit precision instead of the precision the type specifies, so the results can differ slightly from most other chips. Check-ffloat-storefor a more detailed explanation. ๐ซ- This is the default choice for non-Darwin x86-32 targets.
sseโ Uses the scalar floating-point instructions from the SSE instruction set. This is supported by Pentium III and newer chips, and on the AMD side by Athlon-4, Athlon XP and Athlon MP chips. The earlier version of SSE only does single-precision arithmetic, so double and extended-precision maths still go through 387. A later version, found only in Pentium 4 and AMD x86-64 chips, handles double-precision arithmetic too. ๐- For the x86-32 compiler, you need
-march=cpu-type,-msseor-msse2to turn on SSE extensions and make this option work. For the x86-64 compiler, those extensions are on by default. - The result should be a lot faster in most cases and dodges the numerical instability problems of 387 code. But it may 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 for x86-32 targets with the SSE2 instruction set when
-ffast-mathis enabled.
- For the x86-32 compiler, you need
sse,387,sse+387,bothโ Tries to use both instruction sets at once. That 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. ๐
-masm=dialectโ ๐ Outputs assembly instructions in the selected dialect. This also decides which dialect is used for basicasmand extendedasm. The supported choices (in dialect order) areattorintel. The default isatt. Darwin doesn't supportintel. ๐ธ-mieee-fp,-mno-ieee-fpโ ๐ฆ Controls whether or not the compiler uses IEEE floating-point comparisons. These handle the case where a comparison result 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 instead.- > Warning: the libraries you need are not part of GCC. Normally the facilities of the machine's usual C compiler get used, but that can't be done directly when cross-compiling. You have to sort out your own 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 get emitted even when
-msoft-floatis used. ๐
-mno-fp-ret-in-387โ ๐ซถ Doesn't use the FPU registers for function return values.- The usual calling convention has functions return
floatanddoublevalues in an FPU register, even if there's no FPU. The idea is that the operating system should emulate the FPU. -mno-fp-ret-in-387makes those values come back in ordinary CPU registers instead. ๐
- The usual calling convention has functions return
-mno-fancy-math-387โ ๐ Some 387 emulators don't support thesin,cosandsqrtinstructions for the 387. Use this option to avoid generating those instructions. It gets overridden when-marchsays the target CPU always has an FPU, so the instruction doesn't need emulating. These instructions also aren't generated unless you use the-funsafe-math-optimizationsswitch too. โญ-malign-double,-mno-align-doubleโ ๐ Controls whether GCC alignsdouble,long doubleandlong longvariables on a two-word boundary or a one-word boundary. Aligningdoublevariables on a two-word boundary makes code run a bit faster on a Pentium, at the cost of more memory. ๐- On x86-64,
-malign-doubleis enabled by default. - > Warning: if you use
-malign-double, structures containing the types above get aligned differently from the published application binary interface specifications for x86-32. They won't be binary compatible with structures in code compiled without that switch. ๐
- On x86-64,
-m96bit-long-double,-m128bit-long-doubleโ ๐ฅ These switches control the size of thelong doubletype. The x86-32 application binary interface specifies 96 bits, so-m96bit-long-doubleis the default in 32-bit mode. ๐
Okay so, the "long double" alignment situation is actually kind of wild ๐
. Modern chips (Pentium and newer) really want "long double" sitting on an 8- or 16-byte boundary, but inside arrays and structures that follow the ABI, that just isn't possible ๐ญ. So -m128bit-long-double lines things up on a 16-byte boundary by tacking on an extra 32-bit zero of padding ๐ซถ.
On the x86-64 compiler, -m128bit-long-double is already the default, because its ABI says "long double" is aligned on a 16-byte boundary โจ.
Quick heads up, though: neither of these options gives you any extra precision over the x87 standard of 80 bits for a "long double" ๐.
Warning: if you override the default for your target ABI, the size of structures and arrays holding "long double" variables changes, and the function calling convention for functions taking "long double" gets modified too ๐. That means your code is not binary-compatible with code compiled without that switch, so be careful bestie ๐ฅบ.
-mlong-double-64โ makes the "long double" type equivalent to "double" ๐. This is the default for the 32-bit Bionic C library.-mlong-double-80โ one of the three switches that control the size of the "long double" type ๐. The original page doesn't give it any extra detail beyond that.-mlong-double-128โ makes the "long double" type equivalent to "__float128" ๐. This is the default for the 64-bit Bionic C library.
Warning: same deal here. Overriding the default for your target ABI changes the size of structures and arrays containing "long double" variables, and it modifies the function calling convention for functions taking "long double". So it's not binary-compatible with code compiled without that switch ๐ญ.
-malign-data=typeโ controls how GCC aligns variables ๐ง. The supported values for type arecompat, which uses an increased alignment value that's compatible with GCC 4.8 and earlier;abi, which uses the alignment value specified by the psABI; andcacheline, which uses an increased alignment value to match the cache line size ๐.compatis the default.-mlarge-data-threshold=thresholdโ when-mcmodel=mediumor-mcmodel=largeis specified, any data objects bigger than threshold get placed into large data sections ๐ฆ. The default is65535.-mrtdโ switches to a different function-calling convention ๐ฅ. Functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments on the way out, so the caller saves one instruction since it doesn't have to pop them itself โจ.
You can make one specific function use this calling sequence with the function attribute "stdcall" ๐
. You can also override -mrtd for a function with the function attribute "cdecl" ๐.
Warning: this calling convention is incompatible with the one normally used on Unix, so you cannot 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 ๐ญ. And seriously incorrect code results if you call a function with too many arguments ๐. Normally, extra arguments just get harmlessly ignored, but not here, bestie.
-mregparm=numโ controls how many registers are used to pass integer arguments ๐ธ. By default, no registers are used for passing arguments, and at most 3 registers can be used. You can control this for a specific function with the function attribute "regparm" ๐ซถ.
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 for float and double arguments and return values โญ. You can control this for a specific function with the function attribute "sseregparm" ๐.
Warning: if you use this switch, you must build all modules with the same value, including any libraries, the system libraries, and startup modules too ๐ญ.
-mvect8-ret-in-memโ returns 8-byte vectors in memory instead of MMX registers ๐ง. This is the default on VxWorks, so it matches the ABI of the Sun Studio compilers up until version 12 ๐. Only use this if you need to stay compatible with existing code made by those older compiler versions or older versions of GCC ๐ฅน.-mpc32,-mpc64,-mpc80โ set the 80387 floating-point precision to 32, 64, or 80 bits ๐ฆ.-mpc32rounds the significands of floating-point results to 24 bits (single precision) ๐ธ.-mpc64rounds them to 53 bits (double precision) ๐.-mpc80rounds them to 64 bits (extended double precision), and this is the default โจ.
When one of these is used, floating-point operations in higher precisions aren't available to you unless you set the FPU control word explicitly ๐.
Rounding to less than the default 80 bits can speed some programs up by 2% or more ๐ฅ. But heads up: some math libraries assume extended-precision (80-bit) floating-point operations are on by default. Routines in those libraries could lose a bunch of accuracy, typically through so-called "catastrophic cancellation", when this option drops the precision below extended precision ๐.
-mdaz-ftzโ the flush-to-zero (FTZ) and denormals-are-zero (DAZ) flags in the MXCSR register are what control floating-point calculations ๐. SSE and AVX instructions, including scalar and vector ones, could benefit from enabling the FTZ and DAZ flags when you pass-mdaz-ftzโญ. Don't set the FTZ/DAZ flags when-mno-daz-ftzor-sharedis specified. And-mdaz-ftzwill set the FTZ/DAZ flags even with-shared, so keep that in mind ๐.-mstackrealignโ realigns the stack at entry ๐. On x86, this generates an alternate prologue and epilogue that realigns the runtime stack when necessary ๐ซถ. It's super useful for mixing legacy code that keeps 4-byte stack alignment with modern code that keeps 16-byte stack alignment for SSE compatibility ๐. See also the attribute "force_align_arg_pointer", which you can apply to individual functions ๐ฆ.-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐ธ. If you don't specify-mpreferred-stack-boundary, the default is4(16 bytes or 128 bits) โจ.
Warning: 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 ๐. But since the x86-64 ABI requires 16-byte stack alignment, this is ABI incompatible. It's only meant for controlled environments where stack space is a seriously important limitation ๐ฅบ. This option leads to wrong code when functions compiled with 16-byte stack alignment (like functions from a standard library) get called with a misaligned stack. In that case, SSE instructions may lead to misaligned memory access traps ๐. On top of that, variable arguments are handled incorrectly for 16-byte aligned objects (including x87 long double and__int128), which leads to wrong results ๐ญ. You must build all modules with-mpreferred-stack-boundary=3, including any libraries, 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-mincoming-stack-boundary, the one specified 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 they'll suffer significant run time performance penalties ๐ข. On Pentium III, the Streaming SIMD Extension (SSE) data type "__m128" may not work properly if it isn't 16-byte aligned ๐ญ.
To make sure these values are aligned properly on the stack, the stack boundary has to be as aligned as whatever value stored on the stack requires ๐ซถ. Also, every function has to be generated so it keeps the stack aligned ๐. So calling a function compiled with a higher preferred stack boundary from a function compiled with a lower one most likely misaligns the stack ๐. It's recommended that libraries that use callbacks always stick with the default setting ๐ธ.
This extra alignment does eat up extra stack space and generally increases code size ๐ฅน. Code that's sensitive to stack space usage, like embedded systems and operating system kernels, may want to reduce the preferred alignment to -mpreferred-stack-boundary=2 โจ.
-mmmx๐ unlocks the MMX instructions-msse๐ธ unlocks SSE-msse2๐ธ unlocks SSE2-msse3๐ธ unlocks SSE3-mssse3๐ธ unlocks SSSE3-msse4โจ unlocks SSE4.1 and SSE4.2 together-msse4a๐ฆ unlocks SSE4A, which is controlled separately from-msse4-msse4.1โจ unlocks SSE4.1-msse4.2โจ unlocks SSE4.2-mavx๐ง unlocks AVX-mavx2๐ง unlocks AVX2-mavx512f๐ unlocks AVX512F-mavx512cd๐ unlocks AVX512CD-mavx512vl๐ unlocks AVX512VL-mavx512bw๐ unlocks AVX512BW-mavx512dq๐ unlocks AVX512DQ-mavx512ifma๐ unlocks AVX512IFMA-mavx512vbmi๐ unlocks AVX512VBMI-msha๐ unlocks SHA-maes๐ unlocks AES-mpclmul๐ unlocks PCLMUL-mclflushopt๐งน unlocks CLFLUSHOPT-mclwb๐งน unlocks CLWB-mfsgsbase๐ unlocks FSGSBASE-mptwrite๐ unlocks PTWRITE-mrdrnd๐ฒ unlocks RDRND-mf16c๐ unlocks F16C-mfma๐ฅ unlocks FMA-mpconfig๐ unlocks PCONFIG-mwbnoinvd๐ unlocks WBNOINVD-mfma4๐ฅ unlocks FMA4-mprfchw๐ unlocks PREFETCHW-mrdpid๐ unlocks RDPID-mrdseed๐ฒ unlocks RDSEED-msgx๐ unlocks SGX-mxop๐ unlocks XOP-mlwp๐ unlocks LWP-m3dnow๐ unlocks 3DNow!-m3dnowa๐ unlocks enhanced 3DNow!-mpopcnt๐ unlocks POPCNT-mabm๐ unlocks ABM-madx๐ unlocks ADX-mbmi๐ unlocks BMI-mbmi2๐ unlocks BMI2-mlzcnt๐ unlocks LZCNT-mfxsr๐ unlocks FXSR-mxsave๐ unlocks XSAVE-mxsaveopt๐ unlocks XSAVEOPT-mxsavec๐ unlocks XSAVEC-mxsaves๐ unlocks XSAVES-mrtm๐ unlocks RTM-mhle๐ unlocks HLE-mtbm๐ unlocks TBM-mmwaitx๐ unlocks MWAITX-mclzero๐ unlocks CLZERO-mpku๐ unlocks PKU-mavx512vbmi2๐ unlocks AVX512VBMI2-mavx512bf16๐ unlocks AVX512BF16-mavx512fp16๐ unlocks AVX512-FP16-mgfni๐ unlocks GFNI-mvaes๐ unlocks VAES-mwaitpkg๐ unlocks WAITPKG-mvpclmulqdq๐ unlocks VPCLMULQDQ-mavx512bitalg๐ unlocks AVX512BITALG-mmovdiri๐ unlocks MOVDIRI-mmovdir64b๐ unlocks MOVDIR64B-menqcmd๐ unlocks ENQCMD-muintr๐ unlocks UINTR-mtsxldtrk๐ unlocks TSXLDTRK-mavx512vpopcntdq๐ unlocks AVX512VPOPCNTDQ-mavx512vp2intersect๐ unlocks AVX512VP2INTERSECT-mavx512vnni๐ unlocks AVX512VNNI-mavxvnni๐ง unlocks AVXVNNI-mcldemote๐งน unlocks CLDEMOTE-mserialize๐ unlocks SERIALIZE-mamx-tile๐ unlocks AMXTILE-mamx-int8๐ unlocks AMXINT8-mamx-bf16๐ unlocks AMXBF16-mhreset๐ unlocks HRESET-mkl๐ unlocks KL-mwidekl๐ unlocks WIDEKL-mavxifma๐ง unlocks AVXIFMA-mavxvnniint8๐ง unlocks AVXVNNIINT8-mavxneconvert๐ง unlocks AVXNECONVERT-mcmpccxadd๐ unlocks CMPCCXADD-mamx-fp16๐ unlocks AMX-FP16-mprefetchi๐ unlocks PREFETCHI-mraoint๐ unlocks RAOINT-mamx-complex๐ unlocks AMX-COMPLEX-mavxvnniint16๐ง unlocks AVXVNNIINT16-msm3๐ unlocks SM3-msha512๐ unlocks SHA512-msm4๐ unlocks SM4-mapxf๐ unlocks APX_F-musermsr๐ unlocks USER_MSR-mavx10.1๐ unlocks AVX10.1-mavx10.1-256๐ unlocks AVX10.1 at the 256-bit width-mavx10.1-512๐ unlocks AVX10.1 at the 512-bit width-mavx10.2๐ unlocks AVX10.2-mamx-avx512๐ unlocks AMX-AVX512-mamx-tf32๐ unlocks AMX-TF32-mamx-transpose๐ unlocks AMX-TRANSPOSE-mamx-fp8๐ unlocks AMX-FP8-mmovrs๐ unlocks MOVRS-mamx-movrs๐ unlocks AMX-MOVRS
These switches are basically your permission slip to use all these fancy instruction sets: MMX, SSE, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA, AES, PCLMUL, CLFLUSHOPT, CLWB, FSGSBASE, PTWRITE, RDRND, F16C, FMA, PCONFIG, WBNOINVD, FMA4, PREFETCHW, RDPID, RDSEED, SGX, XOP, LWP, 3DNow!, enhanced 3DNow!, POPCNT, ABM, ADX, BMI, BMI2, LZCNT, FXSR, XSAVE, XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2, GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16, ENQCMD, AVX512VPOPCNTDQ, AVX512VNNI, SERIALIZE, UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI, AVX512-FP16, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, AMX-FP16, PREFETCHI, RAOINT, AMX-COMPLEX, AVXVNNIINT16, SM3, SHA512, SM4, APX_F, USER_MSR, AVX10.1, AVX10.2, AMX-AVX512, AMX-TF32, AMX-TRANSPOSE, AMX-FP8, MOVRS, AMX-MOVRS, or CLDEMOTE extended instruction sets. Every one of them has a matching -mno- option that turns its use back off. ๐
These extensions are also available as built-in functions, so check out x86 Built-in Functions to see which functions get enabled and disabled by these switches. ๐ง
Heads up: -msse4 turns on both SSE4.1 and SSE4.2 support, and -mno-sse4 turns both off. Neither form touches SSE4A, which is handled on its own by -msse4a. ๐ซถ
If you want SSE/SSE2 instructions generated automatically from floating-point code (instead of 387 instructions), look at -mfpmath=sse. โจ
Fun fact that's kind of a plot twist: GCC suppresses SSEx instructions when -mavx is used. Instead, it generates new AVX instructions, or AVX equivalents for all the SSEx instructions, whenever they're needed. ๐ฆ
These options let GCC use those extended instructions in the code it generates, even without -mfpmath=sse. Apps that do run-time CPU detection need to compile separate files for each supported architecture, using the right flags. Specifically, the file with the CPU detection code should be compiled without these options. ๐
-mdump-tune-features๐ makes GCC dump the names of the x86 performance tuning features along with their default settings. You can use those names with-mtune-ctrl=feature-list.-mtune-ctrl=feature-list๐๏ธ gives you fine-grained control over x86 code generation features.feature-listis a comma-separated list of feature names. See also-mdump-tune-features. A feature gets turned on if its name has no^in front of it, and turned off if it does.
This one is really meant for GCC developers. Using it may lead to code paths that testing never covered, and it can potentially cause compiler ICEs or runtime errors. Proceed with caution, bestie. ๐
-mno-default๐งผ makes GCC turn off every tunable feature. See also-mtune-ctrl=feature-listand-mdump-tune-features.-mcld๐งญ tells GCC to emit acldinstruction in the prologue of functions that use string instructions. String instructions rely on the DF flag to choose between autoincrement and autodecrement mode. The ABI says DF should be cleared on function entry, but some operating systems break that rule by not clearing DF in their exception dispatchers. So the exception handler can get invoked with DF set, and then string instructions go in 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 ofcldinstructions with the-mno-cldcompiler option. ๐ท-mvzeroupper๐งน tells GCC to emit avzeroupperinstruction before control flow transfers out of the function. This cuts down the AVX-to-SSE transition penalty, and it also removes unnecessaryzeroupperintrinsics.-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 useopt-bit vector width in instructions instead of the default for the selected platform. The choices are:none๐ซ๏ธ no extra limits on GCC beyond whatever the selected platform already defines128๐ธ prefers 128-bit vector width for instructions256๐บ prefers 256-bit vector width for instructions512๐ prefers 512-bit vector width for instructions
-mpartial-vector-fp-math๐งฎ lets GCC generate floating-point operations that might affect the floating-point status flags on partial vectors, meaning vectors whose elements live in the low part of a 128-bit SSE register. Unless-fno-trapping-mathis specified, the compiler keeps things correct 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 values, 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 soften this 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,256, and512.-mstore-max=bits๐ฆ sets the maximum number of bits that can be stored to memory efficiently to bits. The valid values are128,256, and512.-mnoreturn-no-callee-saved-registers๐ optimizes functions with thenoreturnattribute or the_Noreturnspecifier. It does this by not saving, in the function prologue, the callee-saved registers the function uses (except theBPregister).
This one can mess with debugging the caller of the noreturn function, or any function further up the call stack, so it is not enabled by default. ๐
-mcx16๐ lets GCC generateCMPXCHG16Binstructions in 64-bit code to do compare-and-exchange operations on 16-byte aligned 128-bit objects. This is great 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 ofSAHFinstructions in 64-bit code. Early Intel Pentium 4 CPUs with Intel 64 support (before the Pentium 4 G1 step arrived in December 2005) didn't have theLAHFandSAHFinstructions that AMD64 supports. These are load and store instructions, respectively, for certain status flags. In 64-bit mode, theSAHFinstruction is used to optimize thefmod,drem, andremainderbuilt-in functions. See Other Builtins for details.-mmovbe๐ enables use of themovbeinstruction to optimize byte swapping of four- and eight-byte entities.-mshstk๐ก๏ธ makes the shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) available.-mcrc32๐งฎ enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32si, and__builtin_ia32_crc32dito generate thecrc32machine instruction.-mmwaitโณ enables the built-in functions__builtin_ia32_monitorand__builtin_ia32_mwaitto generate themonitorandmwaitmachine instructions.-mrecipโก enables use ofRCPSSandRSQRTSSinstructions (plus their vectorized variantsRCPPSandRSQRTPS) with an extra Newton-Raphson step for more precision. They're used instead ofDIVSSandSQRTSS(and their vectorized variants) for single-precision floating-point arguments. These instructions are only generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math. 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). ๐ซ
Also, GCC already implements 1.0f/sqrtf(x) using RSQRTSS (or RSQRTPS) with -ffast-math, or with the option combination above, so you don't need -mrecip for that. ๐
And GCC emits that same sequence, with the extra Newton-Raphson step, for vectorized single-float division and vectorized sqrtf(x) with -ffast-math (or the option combination above). So again, -mrecip isn't needed for that either. โจ
-mrecip=opt ๐ this one controls which reciprocal estimate instructions are allowed to get used. opt is a comma-separated list, and you can slap a ! in front of any option to flip it ๐ฆ
allโจ turns on every estimate instructiondefault๐ธ turns on the default instructions, same as-mrecipnone๐ turns off all estimate instructions, same as-mno-recipdiv๐ turns on the approximation for scalar divisionvec-div๐ฅ turns on the approximation for vectorized divisionsqrt๐ turns on the approximation for scalar square rootvec-sqrt๐ง turns on the approximation for vectorized square root
So, for example, -mrecip=all,!sqrt turns on all of the reciprocal approximations except square root. Main character energy ๐
-mveclibabi=type ๐ this sets the ABI type for vectorizing intrinsics through an external library. The type can be svml for the Intel short vector math library, aocl for the math library (LibM) from AMD Optimizing CPU Libraries (AOCL), or acml for the end-of-life AMD core math library, which AOCL-LibM succeeded. To use this option you need both -ftree-vectorize and -funsafe-math-optimizations enabled, plus an SVML or ACML ABI-compatible library specified at link time. Not skipping that part, bestie ๐ซถ
GCC currently emits calls to these names when -mveclibabi=svml is used, for the matching function types: "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" and "vmlsAcos4" ๐ง
When -mveclibabi=aocl is used, it goes for these: "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" and "amd_vrs16_tanhf" ๐
And when -mveclibabi=acml is used, you get these for the matching function types: "__vrd2_sin", "__vrd2_cos", "__vrd2_exp", "__vrd2_log", "__vrd2_log2", "__vrd2_log10", "__vrs4_sinf", "__vrs4_cosf", "__vrs4_expf", "__vrs4_logf", "__vrs4_log2f", "__vrs4_log10f" and "__vrs4_powf" ๐ฆ
-mabi=name โจ this generates code for the calling convention you pick. The valid values are sysv, which is the ABI used on GNU/Linux and other systems, and ms, which is the Microsoft ABI. The default is the Microsoft ABI when you're targeting Microsoft Windows, and the SysV ABI everywhere else. You can override this for specific functions with the function attributes "ms_abi" and "sysv_abi" ๐ซถ
-mforce-indirect-call ๐ฅ forces every function call to be indirect. This is handy with Intel Processor Trace, since it gives more precise timing info for function calls ๐ง
-mmanual-endbr ๐ only inserts the ENDBR instruction at function entry when you ask for it through the "cf_check" function attribute. It's useful alongside -fcf-protection=branch, letting you control ENDBR insertion at the function entry ๐
-mcet-switch ๐ by default, CET instrumentation is off for switch statements that use a jump table, and indirect branch track is disabled. Jump tables live in read-only memory, so this doesn't directly cost you any hardening. But if the jump table index is attacker-controlled, CET might not constrain the indirect jump.
This option turns on CET instrumentation 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 64-bit ABIs differ, 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 that saves and restores these registers is emitted inline, which makes the prologues and epilogues pretty lengthy. Using -mcall-ms2sysv-xlogues makes the prologues and epilogues use stubs in the static portion of libgcc to do 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 the gnu or gnu2 conventions. gnu is the conservative default. gnu2 is more efficient, but it may add compile- and run-time requirements that can't be satisfied on all systems ๐
-mpush-args -mno-push-args ๐ these use PUSH operations to store outgoing parameters. That's shorter and usually just as fast as the SUB/MOV method, and it's enabled by default. In some cases, turning it off may improve performance thanks to better scheduling and fewer dependencies โจ
-maccumulate-outgoing-args ๐ when enabled, the maximum amount of space needed for outgoing arguments is computed in the function prologue. This is faster on most modern CPUs thanks to reduced dependencies, better scheduling and less stack usage when the preferred stack boundary isn't equal to 2. The catch is a notable jump in code size ๐ This switch implies -mno-push-args.
-mthreads ๐ supports thread-safe exception handling on MinGW. Programs that rely on thread-safe exception handling must compile and link all their code with -mthreads. When compiling, -mthreads defines -D_MT. When linking, it pulls in the special thread helper library -lmingwthrd, which cleans up per-thread exception-handling data ๐ง
-mms-bitfields -mno-ms-bitfields ๐ฆ these enable or disable bit-field layout that's compatible with the native Microsoft Windows compiler ๐
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 moving packed data between functions compiled with GCC and the native Microsoft compiler, either through a function call or as data in a file, you might need to access either format ๐ญ
This option is on by default for Microsoft Windows targets. You can also control it locally with variable or type attributes. For more info, see x86 Variable Attributes and x86 Type Attributes ๐ธ
The Microsoft structure layout algorithm is pretty simple, except for the bit-field packing. Whether a bit-field can straddle a storage-unit boundary, and the padding and alignment of structure members, come down to 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
"aligned"attribute or the"pack"pragma), whichever is less. For structures, unions, and arrays, the alignment requirement is the largest alignment requirement of any of its members. Every object gets an offset so that:
offset % alignment_requirement == 0
- Adjacent bit-fields get packed into the same 1-, 2-, or 4-byte allocation unit, as long as the integral types are the same size and 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 would normally be 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. ๐
- If a zero-length bit-field is inserted after a bit-field,
"foo", and the alignment of the zero-length bit-field is greater than that of the member that follows it,"bar", then"bar"is aligned as the type of the 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" is placed at offset 2, rather than offset 1. So the size of "t2" is 4. For "t3", the zero-length bit-field doesn't affect the alignment of "bar" or, as a result, the size of the structure. ๐ซถ
Taking this into account, it is important to note the following: โจ
Okay so bestie, the zero-length bit-field stuff is lowkey wild ๐ Here's how it goes:
- Zero-length bit-fields that follow a normal bit-field can change the alignment of the whole struct, depending on their type ๐ For example,
t2is 4 bytes, because its zero-length bit-field comes right after a normal bit-field and is of typeshortโจ - Even when a zero-length bit-field doesn't follow a normal bit-field, it can still mess with the struct's alignment ๐
struct
{
char foo : 6;
long : 0;
} t4;
Here, t4 takes up 4 bytes ๐
- Zero-length bit-fields that come after non-bit-field members just get ignored ๐ฆ
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes ๐ธ
-mno-align-stringopsโ Don't align the destination of inlined string operations ๐ This makes the code smaller and can speed things up when the destination is already aligned but GCC doesn't realize it ๐ซถ-minline-all-stringopsโ By default, GCC only inlines string operations when the destination is known to be aligned to at least a 4-byte boundary ๐ This option inlines more, which makes the code bigger, but it might help code that leans on fastmemcpyandmemsetfor short lengths ๐ฅ It also turns on inline expansion ofstrlenfor all pointer alignments โจ-minline-stringops-dynamicallyโ For string operations with an unknown size, use run-time checks ๐ง Small blocks get inline code and big blocks get a library call ๐-mstringop-strategy=algโ Overrides the internal heuristic that picks the algorithm used to inline string operations ๐ The allowed values for alg are:rep_byte,rep_4byte,rep_8byteโ Expand using the i386repprefix of the specified size ๐byte_loop,loop,unrolled_loopโ Expand into an inline loop ๐libcallโ Always use a library call ๐
-mmemcpy-strategy=strategyโ Overrides the heuristic that decides whether__builtin_memcpygets inlined and which inline algorithm to use when the expected size of the copy is known ๐ 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 alg is allowed to handle ๐ The last triplet has to use a max_size of-1๐ The max_size values in the list must go in increasing order ๐ฆ The minimum byte size for alg is0for the first triplet, andmax_size + 1of the range before it for every other triplet ๐ธ-mmemset-strategy=strategyโ Pretty much the same as-mmemcpy-strategy=, except it controls__builtin_memsetexpansion instead ๐-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions ๐ซถ This skips the instructions that save, set up, and restore frame pointers, and frees up an extra register in leaf functions ๐ฅ The option-fomit-leaf-frame-pointeralso drops the frame pointer for leaf functions, but that 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 the operating system, and on whether it maps the segment so it covers the whole 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 the VEX prefix ๐ฆ The option-mavxturns this on by default ๐-mfentry,-mno-fentryโ If profiling is active (-pg), put the profiling counter call before the prologue ๐ง Note: on x86, the attributems_hook_prologueisn't possible at the moment for-mfentryand-pg๐-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), generate a__mcount_locsection that holds pointers to each profiling call ๐ This is super useful for automatically patching out calls ๐ซถ-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), generate the calls to the profiling functions as NOPs ๐ This is handy when they should be patched in later on, dynamically ๐ฅ It's probably only useful together with-mrecord-mcountโจ-minstrument-return=typeโ Instruments function exit in-pg -mfentryinstrumented functions with a call to the specified function ๐ It only instruments true returns that end withret, not sibling calls that end with a jump ๐ฆ Valid types arenoneto not instrument,callto generate a call to__return__, ornop5to generate a 5-byte nop ๐ธ-mrecord-return,-mno-record-returnโ Generates a__return_locsection pointing to all of 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 when no variable arguments get passed in vector registers ๐
โ ๏ธ Warning: RAX is used to avoid saving vector registers on the stack needlessly when passing variable arguments ๐ญ So if you use this option, callees may waste some stack space, misbehave, or jump to a random location ๐ GCC 4.4 or newer doesn't have those issues, no matter what the RAX register value is ๐ซถ
-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 the divisor are between 0 and 255, it uses the 8-bit unsigned divide instead of the 32-bit/64-bit one โจ-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Splits 32-byte AVX unaligned loads and stores ๐ฆ-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 areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default) ๐ This option only does something when-fstack-protectoror-fstack-protector-allis specified ๐ธ
With the tls choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also 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 come from the relevant ABI โจ
-mstack-protector-guard-symbol=symbol overrides the offset with a symbol reference to a canary in the TLS block ๐
-mgeneral-regs-onlyโ Generate 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 highly 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 into call and return thunks ๐งthunk-inlineconverts them into inlined call and return thunks ๐thunk-externconverts them into external call and return thunks, provided in a separate object file ๐ You can control this for a specific function with the function attribute"indirect_branch"๐
โ ๏ธ-mcmodel=largeis incompatible with-mindirect-branch=thunkand-mindirect-branch=thunk-extern, since the thunk function may not be reachable in the large code model ๐ญ
-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 call and return thunks ๐ฅthunk-inlineconverts them to inlined call and return thunks ๐thunk-externconverts them to external call and return thunks, provided in a separate object file ๐ You can control this for a specific function with the function attribute"function_return"๐ธ
-mindirect-return=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐ฆ
โ ๏ธ-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โ Generates code to mitigate straight line speculation (SLS) according to choice ๐ก๏ธ The default isnone, which disables all SLS hardening ๐returnenables SLS hardening for function returns ๐indirect-jmpenables it for indirect jumps ๐allenables all SLS hardening โจ-mindirect-branch-cs-prefixโ Adds a CS prefix to calls and jmps to an indirect thunk, with the branch target in the r8-r15 registers ๐ฆ This makes the call and jmp instructions 6 bytes long, so they can be swapped at run-time forlfence; call *%r8-r15orlfence; jmp *%r8-r15๐-mapx-inline-asm-use-gpr32โ For inline asm support with APX, the EGPR feature is disabled by default so you don't get a sneaky illegal instruction from EGPR ๐ To turn on EGPR usage in inline asm, use this new compiler option, but you need to make sure the instruction actually supports EGPR ๐ซถ
โจ x86 Options (continued) โจ
okay so these -m switches work on top of the ones above, but only on x86-64 processors in 64-bit environments ๐ฆ
-mevex512,-mno-evex512โ okay this one's about 512-bit vectors ๐-mevex512turns them on and-mno-evex512turns them off. It's on by default if AVX512F is enabled, so you usually don't have to think about it ๐ง-m32,-m64,-mx32,-m16,-miamcuโ these pick your environment ๐ธ-m32makesint,long, and pointer types 32 bits and generates code that runs in 32-bit mode ๐-m64makesint32 bits butlongand pointers 64 bits, and generates code for the x86-64 architecture. bestie, on Darwin, only-m64also turns off-fno-picand-mdynamic-no-pic๐-mx32makesint,long, and pointers 32 bits, but still generates x86-64 code ๐-m16is basically-m32with one extra twist: it outputs the.code16gccassembly directive at the start of the assembly output, so the binary can run in 16-bit mode ๐-miamcugenerates code that follows the Intel MCU psABI. it requires-m32to be turned on, so don't skip that part ๐ญ
-mno-red-zoneโ the red zone is this 128-byte area just past the stack pointer that's mandated by the x86-64 ABI. signal or interrupt handlers won't touch it, so you can stash temporary data there without adjusting the stack pointer โจ this flag turns that red zone off ๐-mcmodel=smallโ 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. this is the default code model, so it's the one you get if you don't pick anything ๐-mcmodel=kernelโ generates code for the kernel code model. the kernel runs in the negative 2 GB of the address space, and this model has to be used for Linux kernel code ๐ฅ-mcmodel=mediumโ the program is linked in the lower 2 GB of the address space, and small symbols get placed there too. symbols bigger than-mlarge-data-thresholdgo into large data or BSS sections and can live above 2GB. programs can be statically or dynamically linked ๐-mcmodel=largeโ makes no assumptions at all about addresses and section sizes. very chill, very flexible ๐ฆ-maddress-mode=longโ generates code for long address mode. this is 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. this is only supported for 32-bit and x32 environments, and it's the default address mode for 32-bit and x32 environments too ๐ง-mneeded,-mno-neededโ-mneededemits theGNU_PROPERTY_X86_ISA_1_NEEDEDGNU property for Linux targets. it's how the binary says which micro-architecture ISA level it needs to run ๐ซถ-mno-direct-extern-accessโ without-fpicor-fPIC, this always uses the GOT pointer to reach external symbols. with-fpicor-fPIC, access to protected symbols gets treated like local symbols. the default is-mdirect-extern-access๐
โ ๏ธ 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 with that one, bestie ๐ญ
-munroll-only-small-loopsโ this is conservative small loop unrolling. it's enabled by default with O2, and it unrolls loops with fewer than 4 insns by 1 time. if you explicitly use-f[no-]unroll-[all-]loops, this flag gets disabled, so you don't get unrolling you didn't ask for ๐ธ-mlam=choiceโ LAM (linear-address masking) lets special bits in a pointer hold metadata. the default is none. withu48, pointer bits in positions 62:48 can be used for metadata, and withu57, pointer bits in positions 62:57 can be used ๐ฅ
โจ x86 Windows Options โจ
โจ Xstormy16 Options โจ
these options are defined for Xstormy16:
-msimโ picks startup files and a linker script that work with the simulator ๐ง
โจ Xtensa Options โจ
these options are supported for Xtensa targets ๐
-mconst16,-mno-const16โ enables or disables the use ofCONST16instructions for loading constant values. fair warning,CONST16isn't a standard Tensilica option right now. when it's enabled,CONST16gets used in place of the standardL32Rinstructions every time. it's on by default only ifL32Risn't available ๐-mfused-madd,-mno-fused-maddโ enables or disables fused multiply/add and multiply/subtract instructions in the floating-point option. this does nothing if the floating-point option isn't also enabled. turning fused instructions off forces the compiler to use separate instructions for the multiply and the add/subtract. that's useful when you need strict IEEE 754-compliant results, because fused instructions don't round the intermediate result. so they can give you more bits of precision than IEEE says you should get. turning them off also makes sure your output doesn't depend on the compiler's ability to combine multiply and add/subtract operations ๐ฆ-mserialize-volatile,-mno-serialize-volatileโ when enabled, GCC insertsMEMWinstructions beforevolatilememory references so that sequential consistency is guaranteed. the default is-mserialize-volatile. use-mno-serialize-volatileif you want to leave out theMEMWinstructions ๐-mforce-no-picโ for targets like GNU/Linux, where all user-mode Xtensa code has to be position-independent code (PIC), this turns PIC off for compiling kernel code ๐ฅ-mtext-section-literals,-mno-text-section-literalsโ these control how literal pools are handled. the default is-mno-text-section-literals, which puts literals in a separate section of the output file. that lets the literal pool sit in data RAM/ROM, and it lets the linker merge literal pools from separate object files to kill redundant literals and shrink code size ๐ธ with-mtext-section-literals, literals get interspersed in the text section so they stay as close as possible to their references. that might be necessary for big assembly files. literals for each function go right before that function ๐ง-mauto-litpools,-mno-auto-litpoolsโ also about literal pools ๐ the default is-mno-auto-litpools, which puts literals in a separate section unless-mtext-section-literalsis used. with-mauto-litpools, the assembler interleaves the literals into the text section itself. the compiler doesn't produce explicit.literaldirectives and loads literals into registers withMOVIinstead ofL32R, so the assembler can do relaxation and place literals wherever they're needed. this lets the assembler make several literal pools per function, which helps assemble very big functions that might not be possible with-mtext-section-literalsโญ-mtarget-align,-mno-target-alignโ when enabled, GCC tells the assembler to automatically align instructions to cut branch penalties, at the cost of a bit of code density ๐ the assembler tries to widen density instructions so branch targets and the instructions right after call instructions are aligned. if there aren't enough safe density instructions before a target to align it, no widening happens. the default is-mtarget-align. these options don't change how auto-aligned instructions likeLOOPare treated, since the assembler always aligns those, either by widening density instructions or by insertingNOPinstructions ๐-mlongcalls,-mno-longcallsโ when enabled, GCC tells the assembler to turn direct calls into indirect calls, unless it can prove the target of the direct call is in range for the call instruction. this usually happens for calls to functions in other source files. specifically, the assembler turns a directCALLinto anL32Rfollowed by aCALLX. the default is-mno-longcalls. use this in programs where the call target could be out of range ๐ this option lives in the assembler, not the compiler, so the assembly GCC generates still shows direct call instructions. look at the disassembled object code to see what really runs. also, the assembler uses an indirect call for every cross-file call, not just the ones that are actually out of range ๐ญ-mabi=nameโ generates code for the specified ABI. the permissible values arecall0andwindowed. the default ABI gets picked by the Xtensa core configuration ๐-mabi=call0โ function parameters get passed in registersa2througha7, registersa12througha15are caller-saved, and registera15may be used as a frame pointer. when this ABI is enabled, the C preprocessor symbol__XTENSA_CALL0_ABI__is defined ๐ฆ-mabi=windowedโ function parameters get passed in registersa10througha15. the called function rotates the register window by 8 registers on entry, so its arguments show up in registersa2througha7. registera7may be used as a frame pointer. the register window gets rotated 8 registers back on return. when this ABI is enabled, the C preprocessor symbol__XTENSA_WINDOWED_ABI__is defined ๐-mextra-l32r-costs=nโ specifies an extra cost, in clock cycles, for instruction RAM/ROM access onL32Rinstructions. when you're optimizing for speed, this affects whether a constant gets loaded from the literal pool withL32Ror synthesized from a smaller constant using a couple of arithmetic instructions ๐ง the default value is0.
The -mstrict-align and -mno-strict-align flags are a vibe check on memory alignment ๐ซถ They decide whether GCC avoids or allows memory accesses that might not be aligned on a natural object boundary, as the architecture specification describes. By default it's -mno-strict-align for cores that handle both unaligned loads and stores in hardware, and -mstrict-align for all other cores ๐ธ
๐ฆ zSeries Options ๐ฆ
These are listed under
โจ ENVIRONMENT โจ
okay so this section is all about the environment variables that change how GCC works ๐ Some of them tell GCC which directories or prefixes to search when it's hunting for files, and others set up other parts of the compilation environment. Iconic behaviour, honestly ๐
Also, you can name places to search with options like -B, -I and -L. Those take precedence over anything set in environment variables, and environment variables take precedence over whatever the configuration of GCC says. The hierarchy is real ๐
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL
These environment variables control how GCC uses localisation information, which lets it work with different national conventions ๐ GCC checks the locale categories LC_CTYPE and LC_MESSAGES if it has been configured to do so. These categories can be set to any value your installation supports. A typical value is en_GB.UTF-8 for English in the United Kingdom, encoded in UTF-8 ๐
The LC_CTYPE variable specifies character classification. GCC uses it to work out the character boundaries in a string. This matters for some multibyte encodings that contain quote and escape characters which would otherwise be read as the end of a string or an escape ๐
The LC_MESSAGES variable specifies the language used in diagnostic messages โจ
If LC_ALL is set, it overrides the values of LC_CTYPE and LC_MESSAGES. Otherwise, LC_CTYPE and LC_MESSAGES default to the value of the LANG environment variable. If none of these variables are set, GCC defaults to traditional C English behaviour. Main character energy ๐
TMPDIR
If TMPDIR is set, it specifies the directory to use for temporary files ๐ง GCC uses temporary files to hold the output of one stage of compilation, which then becomes the input to the next stage. For example, the output of the preprocessor is the input to the compiler proper ๐
GCC_COMPARE_DEBUG
Setting GCC_COMPARE_DEBUG is nearly the same as passing -fcompare-debug to the compiler driver. Check the documentation for that option for more details ๐ฅ
GCC_EXEC_PREFIX
If GCC_EXEC_PREFIX is set, it specifies a prefix to use in the names of the subprograms that the compiler executes. No slash is added when this prefix is combined with the name of a subprogram, but you can make your prefix end with a slash if you want one ๐
If GCC_EXEC_PREFIX is not set, GCC tries to figure out a sensible prefix based on the pathname it was invoked with ๐
If GCC can't find the subprogram using the specified prefix, it tries looking in 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 many cases, prefix is the value of "prefix" you used when you ran the configure script ๐ธ
Other prefixes specified with -B take precedence over this prefix โจ
This prefix is also used to find files such as crt0.o that are used for linking ๐ฆ
The prefix also gets used in an unusual way when finding the directories to search for header files. For each standard directory whose name normally begins with /usr/local/lib/gcc (more precisely, with the value of GCC_INCLUDE_DIR), GCC tries replacing that beginning with the specified 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 begins with the configured prefix, then the value of prefix is 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, much like PATH. GCC tries these directories when searching for subprograms, if it can't find them using GCC_EXEC_PREFIX ๐ซถ
LIBRARY_PATH
The value of LIBRARY_PATH is a colon-separated list of directories, much 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. Directories specified with -L still come first ๐
LANG
This variable is used to pass locale information to the compiler. One thing it affects is which character set gets used when character literals, string literals and comments are parsed in C and C++ ๐ When the compiler is configured to allow multibyte characters, these values for LANG are recognised:
C-JISโ recognise JIS characters ๐C-SJISโ recognise SJIS characters ๐C-EUCJPโ recognise EUCJP characters ๐
If LANG is not defined, or it has some other value, then the compiler uses mblen and mbtowc as defined by the default locale to recognise and translate multibyte characters ๐
GCC_EXTRA_DIAGNOSTIC_OUTPUT
If GCC_EXTRA_DIAGNOSTIC_OUTPUT is set to one of the following values, extra text gets printed 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, the same as-fdiagnostics-parseable-fixits. Columns are counted in bytes, starting at byte 1 for the initial column ๐ฆfixits-v2โ the same asfixits-v1, except columns are counted as display columns, as per-fdiagnostics-column-unit=display๐
Some additional environment variables affect how the preprocessor behaves ๐ง
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, and GCC looks in those directories for header files. The special character, PATH_SEPARATOR, depends on the target and is decided when GCC is built. For Microsoft Windows-based targets it's a semicolon, and for almost every other target it's a colon ๐
CPATH specifies a list of directories to be searched as if they were given with -I, but after any paths given with -I options on the command line. This environment variable gets 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 they were given with -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 appear at the beginning or 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 processed by the compiler. System header files are 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 have 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, so that 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-15/README.Bugs> ๐
๐ฆ FOOTNOTES ๐ฆ
- On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work. On multi-libbed systems,gcc -sharedmust select the correct support libraries to link against. Failing to supply the correct flags may lead to subtle defects. Supplying them in cases where they are not necessary is innocuous.-sharedsuppresses the addition of startup code that alters the floating-point environment, as done with-ffast-math,-Ofastor-funsafe-math-optimizationson some targets. ๐
๐ SEE ALSO ๐
gpl(7), gfdl(7), fsf-funding(7), cpp(1), gcov(1), as(1), ld(1), gdb(1) and the Info entries for gcc, cpp, as, ld, binutils and gdb ๐
๐ง AUTHOR ๐ง
See the Info entry for gcc, or <https://gcc.gnu.org/onlinedocs/gcc/Contributors.html>, for contributors to GCC ๐ซถ
โจ COPYRIGHT โจ
okay bestie, the legal bit. don't skip it ๐
Copyright (c) 1988-2025 Free Software Foundation, Inc. ๐ The FSF owns the copyright, and it's been keeping this manual glowing since 1988 ๐
You're allowed 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 ๐ฆ The two Invariant Sections are "GNU General Public License" and "Funding Free Software" ๐ซถ You also get Front-Cover Texts and Back-Cover Texts, and those are spelled out below. A copy of the license lives in the gfdl(7) man page, so go check it out if you're curious ๐ง
(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 the whole manual, bestie!! ๐ This page was made for gcc-15, dated 2025-09-17, and it's all GCC(1) ๐
Now go compile something iconic โจ๐ธ
๐ฆ where this page comes from
- ubuntu questing: gcc-15-x86-64-linux-gnu 15.2.0-4ubuntu4
- ๐ girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms