GCC(1)
โจ GCC(1) โจ
Manual name: GNU ๐ This is the GNU project's page for gcc, and it's honestly such a classic ๐
โจ NAME โจ
Okay so the name is gcc, and it's 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...
Only the most useful options are listed up there ๐ Check below for the rest ๐ฆ And g++ accepts mostly the same options as gcc, so you're basically set ๐
โจ DESCRIPTION โจ
When you invoke GCC, it normally does preprocessing, compilation, assembly, and linking, all in one go ๐ง The "overall options" let you stop that process at an intermediate stage. For example, -c says don't run the linker, so what you get back is object files from the assembler ๐
Other options get passed along to one or more stages. Some control the preprocessor, some control the compiler itself, and some control the assembler and linker. Most of those last ones aren't documented here, since you rarely need them ๐ญ
Most of the command-line options you can use with GCC are built for C programs. If an option is only useful with another language (usually C++), the explanation will say so out loud. If the description doesn't mention a source language, you can use that option with all supported languages โจ
The usual move is to run the executable called gcc. When you're cross-compiling, it's machine-gcc instead, and if you want one specific version, it's machine-gcc-version. When you compile C++ programs, invoke GCC as g++ instead ๐
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so you can't bundle single-letter options together. -dv is very different from -d -v, so don't try to be clever ๐
You can mix options and other arguments. For the most part, the order doesn't matter ๐ซถ But 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 ๐ฅ
Lots of options have long names that start with -f or with -W---for โ for example, -fmove-loop-invariants, -Wformat, and so on ๐ธ Most of these have both positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one isn't the default ๐ง
Some options take one or more arguments, usually separated from the option name by either a space or an equals sign (=). Unless 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 can be arbitrarily large decimal or hexadecimal integers, followed by a byte size suffix for a multiple of bytes. That includes kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, and GB and GiB for gigabyte and gigibyte, and so on ๐ These get called byte-size in the rest of the text. If you want the full scoop on the binary and decimal byte size prefixes, check the NIST, IEC, and other relevant national and international standards ๐ค
โจ OPTIONS โจ
๐ Option Summary ๐
Here's a quick glance at all the options, grouped by type ๐ The explanations come in the sections that follow.
๐ฆ 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 -foffload=arg -foffload-options=arg -fopenacc
-fopenacc-dim=geom -fopenmp -fopenmp-simd
-fopenmp-target-simd-clone[=device-type]
-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
-fargs-in-order=n -fchar8_t -fcheck-new -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-ts -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 -fno-rtti
-fsized-deallocation -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-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-id-cdtor -Wno-terminate -Wno-vexing-parse
-Wvirtual-inheritance -Wno-virtual-move-assign -Wvolatile
-Wzero-as-null-pointer-constant
๐ง 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
๐ 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]
-fno-diagnostics-json-formatting
-fno-diagnostics-show-option -fno-diagnostics-show-caret
-fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers
-fno-diagnostics-show-cwe -fno-diagnostics-show-rule
-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 bestie, this is the whole gossip squad ๐ฃ๏ธ๐ every single warning option lives here, and I'm not cutting a single one ๐ญ๐ซถ
-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 -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 -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
-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 -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-prio-ctor-dtor -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=[pure|const|noreturn|format|malloc] -Wswitch
-Wno-switch-bool -Wswitch-default -Wswitch-enum
-Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand
-Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs
-Wtrivial-auto-var-init -Wno-tsan -Wtype-limits -Wundef
-Wuninitialized -Wunknown-pragmas -Wunsuffixed-float-constants
-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-length-bounds
๐ฌ Static Analyzer Options ๐ฌ
the analyzer crew ๐๐ฆ here's the full roster, flags exactly as they appear, no skipping ๐
-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-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 for the C and Objective-C crowd only ๐ here they are, all of them โจ
-Wbad-function-cast -Wmissing-declarations -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 the debugging section is giving detective energy ๐ต๏ธโโ๏ธ๐ every flag, exactly as written ๐ซถ
-g -glevel -gdwarf -gdwarf-version -gbtf -gctf -gctflevel -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 glow-up squad ๐ The page doesn't describe these ones, so I'm keeping every flag exactly as written ๐ซถ
-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-stack-alignment-fipa-icf-fira-algorithm=algorithm-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-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-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-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 โจ
this squad is all about watching the code so you can see what it's up to ๐๐ฆ
-p-pg-fprofile-arcs--coverage-ftest-coverage-fcondition-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=[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 the pre-game warm-up before the compiler even shows up ๐ธ
-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-flarge-source-files-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 โจ
a quick stop at the assembler, bestie ๐ง
-Wa,option-Xassembler option
โจ Linker Options โจ
the linker is where everything gets tied together ๐
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 GCC goes looking for stuff, the treasure map era ๐บ๏ธ๐
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--sysroot=dir
โจ Code Generation Options โจ
the code generation crew, where the machine code gets made ๐ ๐ฅ
-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
โจ Developer Options โจ
last stop, the developer zone, for when you want to see what's happening behind the curtain ๐๐งช
-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 bestie, this is the chaotic part ๐ Every chip family gets its own squad of flags, so I'll go target by target. Don't worry, I'm just listing them out so you can find your fave ๐
๐ฆ AArch64 Options
AArch64 is absolutely stacked with flags ๐ญ๐ฅ
-mabi=name -mbig-endian -mlittle-endian
-mgeneral-regs-only -mcmodel=tiny -mcmodel=small -mcmodel=large
-mstrict-align -mno-strict-align -momit-leaf-frame-pointer
-mtls-dialect=desc -mtls-dialect=traditional -mtls-size=size
-mfix-cortex-a53-835769 -mfix-cortex-a53-843419
-mlow-precision-recip-sqrt -mlow-precision-sqrt
-mlow-precision-div -mpc-relative-literal-loads
-msign-return-address=scope -mbranch-protection=none|standard|pac-ret[+leaf +b-key]|bti -mharden-sls=opts -march=name -mcpu=name
-mtune=name -moverride=string -mverbose-cost-dump
-mstack-protector-guard=guard -mstack-protector-guard-reg=sysreg
-mstack-protector-guard-offset=offset -mtrack-speculation
-moutline-atomics -mearly-ldp-fusion -mlate-ldp-fusion
๐ Adapteva Epiphany Options
Buzzing in with the Epiphany crew ๐โจ
-mhalf-reg-file -mprefer-short-insn-regs
-mbranch-cost=num -mcmove -mnops=num -msoft-cmpsf -msplit-lohi
-mpost-inc -mpost-modify -mstack-offset=num -mround-nearest
-mlong-calls -mshort-calls -msmall16 -mfp-mode=mode -mvect-double
-max-vect-align=num -msplit-vecmove-early -m1reg-reg
๐ฎ AMD GCN Options
Only three, but they're iconic ๐
-march=gpu -mtune=gpu -mstack-size=bytes
๐ธ ARC Options
The ARC section is giving main character energy, and it goes on for ages ๐๐ธ
-mbarrel-shifter -mjli-always -mcpu=cpu -mA6 -mARC600
-mA7 -mARC700 -mdpfp -mdpfp-compact -mdpfp-fast -mno-dpfp-lrsr
-mea -mno-mpy -mmul32x16 -mmul64 -matomic -mnorm -mspfp
-mspfp-compact -mspfp-fast -msimd -msoft-float -mswap -mcrc
-mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape
-mtelephony -mxy -misize -mannotate-align -marclinux
-marclinux_prof -mlong-calls -mmedium-calls -msdata
-mirq-ctrl-saved -mrgf-banked-regs -mlpc-width=width -G num
-mvolatile-cache -mtp-regno=regno -malign-call -mauto-modify-reg
-mbbit-peephole -mno-brcc -mcase-vector-pcrel -mcompact-casesi
-mno-cond-exec -mearly-cbranchsi -mexpand-adddi -mindexed-loads
-mlra -mlra-priority-none -mlra-priority-compact
-mlra-priority-noncompact -mmillicode -mmixed-code -mq-class
-mRcq -mRcw -msize-level=level -mtune=cpu -mmultcost=num
-mcode-density-frame -munalign-prob-threshold=probability
-mmpy-option=multo -mdiv-rem -mcode-density -mll64 -mfpu=fpu
-mrf16 -mbranch-index
๐ช ARM Options
ARM is the OG and it's still serving ๐ฅ
-mapcs-frame -mno-apcs-frame -mabi=name
-mapcs-stack-check -mno-apcs-stack-check -mapcs-reentrant
-mno-apcs-reentrant -mgeneral-regs-only -msched-prolog
-mno-sched-prolog -mlittle-endian -mbig-endian -mbe8 -mbe32
-mfloat-abi=name -mfp16-format=name -mthumb-interwork
-mno-thumb-interwork -mcpu=name -march=name -mfpu=name -mtune=name
-mprint-tune-info -mstructure-size-boundary=n -mabort-on-noreturn
-mlong-calls -mno-long-calls -msingle-pic-base
-mno-single-pic-base -mpic-register=reg -mnop-fun-dllimport
-mpoke-function-name -mthumb -marm -mflip-thumb -mtpcs-frame
-mtpcs-leaf-frame -mcaller-super-interworking
-mcallee-super-interworking -mtp=name -mtls-dialect=dialect
-mword-relocations -mfix-cortex-m3-ldrd -mfix-cortex-a57-aes-1742098
-mfix-cortex-a72-aes-1655431 -munaligned-access -mneon-for-64bits
-mslow-flash-data -masm-syntax-unified -mrestrict-it
-mverbose-cost-dump -mpure-code -mcmse -mfix-cmse-cve-2021-35465
-mstack-protector-guard=guard -mstack-protector-guard-offset=offset
-mfdpic -mbranch-protection=none|standard|pac-ret[+leaf] [+bti]|bti[+pac-ret[+leaf]]
โก AVR Options
Tiny chips, big energy โจ
-mmcu=mcu -mabsdata -maccumulate-args
-mbranch-cost=cost -mfuse-add=level -mcall-prologues
-mgas-isr-prologues -mint8 -mflmap -mdouble=bits
-mlong-double=bits -mn_flash=size -mno-interrupts -mmain-is-OS_task
-mrelax -mrmw -mstrict-X -mtiny-stack -mrodata-in-ram
-mfract-convert-truncate -mshort-calls -mskip-bug -nodevicelib
-nodevicespecs -Waddr-space-convert -Wmisspelled-isr
๐ต Blackfin Options
Vibing with the Blackfin set ๐ต
-mcpu=cpu[-sirevision] -msim
-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer
-mspecld-anomaly -mno-specld-anomaly -mcsync-anomaly
-mno-csync-anomaly -mlow-64k -mno-low64k -mstack-check-l1
-mid-shared-library -mno-id-shared-library -mshared-library-id=n
-mleaf-id-shared-library -mno-leaf-id-shared-library -msep-data
-mno-sep-data -mlong-calls -mno-long-calls -mfast-fp -minline-plt
-mmulticore -mcorea -mcoreb -msdram -micplb
๐ง C6X Options
Small list, sweet vibes ๐ง
-mbig-endian -mlittle-endian -march=cpu -msim
-msdata=sdata-type
๐ CRIS Options
Ooh, CRIS is full of little details ๐
-mcpu=cpu -march=cpu -mtune=cpu -mmax-stack-frame=n
-metrax4 -metrax100 -mpdebug -mcc-init -mno-side-effects
-mstack-align -mdata-align -mconst-align -m32-bit -m16-bit
-m8-bit -mno-prologue-epilogue -melf -maout -sim -sim2
-mmul-bug-workaround -mno-mul-bug-workaround
๐ C-SKY Options
The C-SKY list is serving a whole buffet ๐
-march=arch -mcpu=cpu -mbig-endian -EB
-mlittle-endian -EL -mhard-float -msoft-float -mfpu=fpu
-mdouble-float -mfdivdu -mfloat-abi=name -melrw -mistack -mmp
-mcp -mcache -msecurity -mtrust -mdsp -medsp -mvdsp -mdiv
-msmart -mhigh-registers -manchor -mpushpop -mmultiple-stld
-mconstpool -mstack-size -mccrt -mbranch-cost=n -mcse-cc
-msched-prolog -msim
๐ Darwin Options
Darwin is the longest list here and it's not even close ๐ญ๐
-all_load -allowable_client -arch
-arch_errors_fatal -arch_only -bind_at_load -bundle
-bundle_loader -client_name -compatibility_version
-current_version -dead_strip -dependency-file -dylib_file
-dylinker_install_name -dynamic -dynamiclib -exported_symbols_list
-filelist -flat_namespace -force_cpusubtype_ALL
-force_flat_namespace -headerpad_max_install_names -iframework
-image_base -init -install_name -keep_private_externs
-multi_module -multiply_defined -multiply_defined_unused
-noall_load -no_dead_strip_inits_and_terms -nodefaultrpaths
-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 -F -gused -gfull -mmacosx-version-min=version
-mkernel -mone-byte-bool
๐ฟ DEC Alpha Options
Retro queen energy, no cap ๐๐ฟ
-mno-fp-regs -msoft-float -mieee
-mieee-with-inexact -mieee-conformant -mfp-trap-mode=mode
-mfp-rounding-mode=mode -mtrap-precision=mode -mbuild-constants
-mcpu=cpu-type -mtune=cpu-type -mbwx -mmax -mfix -mcix
-mfloat-vax -mfloat-ieee -mexplicit-relocs -msmall-data
-mlarge-data -msmall-text -mlarge-text -mmemory-latency=time
๐ eBPF Options
eBPF is literally so cute ๐๐
-mbig-endian -mlittle-endian -mframe-limit=bytes -mxbpf
-mco-re -mno-co-re -mjmpext -mjmp32 -malu32 -mv3-atomics -mbswap
-msdiv -msmov -mcpu=version -masm=dialect
-minline-memops-threshold=bytes
๐ง FR30 Options
Sweet and simple ๐ง
-msmall-model -mno-lsim
๐ FT32 Options
Bow on top ๐
-msim -mlra -mnodiv -mft32b -mcompress -mnopm
๐บ FRV Options
FRV is a whole mood ๐บ
-mgpr-32 -mgpr-64 -mfpr-32 -mfpr-64 -mhard-float
-msoft-float -malloc-cc -mfixed-cc -mdword -mno-dword -mdouble
-mno-double -mmedia -mno-media -mmuladd -mno-muladd -mfdpic
-minline-plt -mgprel-ro -multilib-library-pic -mlinked-fp
-mlong-calls -malign-labels -mlibrary-pic -macc-4 -macc-8 -mpack
-mno-pack -mno-eflags -mcond-move -mno-cond-move
-moptimize-membar -mno-optimize-membar -mscc -mno-scc -mcond-exec
-mno-cond-exec -mvliw-branch -mno-vliw-branch -mmulti-cond-exec
-mno-multi-cond-exec -mnested-cond-exec -mno-nested-cond-exec
-mtomcat-stats -mTLS -mtls -mcpu=cpu
๐ง GNU/Linux Options
Penguin pride ๐ง๐ซถ
-mglibc -muclibc -mmusl -mbionic -mandroid
-tno-android-cc -tno-android-ld
๐น๏ธ H8/300 Options
Retro gaming era ๐น๏ธ
-mrelax -mh -ms -mn -mexr -mno-exr -mint32
-malign-300
๐๏ธ HPPA Options
HPPA is so detailed it's giving architect ๐๏ธ
-march=architecture-type -matomic-libcalls
-mbig-switch -mcaller-copies -mdisable-fpregs -mdisable-indexing
-mordered -mfast-indirect-calls -mgas -mgnu-ld -mhp-ld
-mfixed-range=register-range -mcoherent-ldcw -mjump-in-delay
-mlinker-opt -mlong-calls -mlong-load-store -mno-atomic-libcalls
-mno-disable-fpregs -mno-disable-indexing -mno-fast-indirect-calls
-mno-gas -mno-jump-in-delay -mno-long-load-store
-mno-portable-runtime -mno-soft-float -mno-space-regs -msoft-float
-mpa-risc-1-0 -mpa-risc-1-1 -mpa-risc-2-0 -mportable-runtime
-mschedule=cpu-type -mspace-regs -msoft-mult -msio -mwsio
-munix=unix-std -nolibdld -static -threads
๐ง IA-64 Options
The IA-64 list is a full brain workout ๐ง ๐ฅ
-mbig-endian -mlittle-endian -mgnu-as -mgnu-ld
-mno-pic -mvolatile-asm-stop -mregister-names -msdata -mno-sdata
-mconstant-gp -mauto-pic -mfused-madd
-minline-float-divide-min-latency
-minline-float-divide-max-throughput -mno-inline-float-divide
-minline-int-divide-min-latency -minline-int-divide-max-throughput
-mno-inline-int-divide -minline-sqrt-min-latency
-minline-sqrt-max-throughput -mno-inline-sqrt -mdwarf2-asm
-mearly-stop-bits -mfixed-range=register-range -mtls-size=tls-size
-mtune=cpu-type -milp32 -mlp64 -msched-br-data-spec
-msched-ar-data-spec -msched-control-spec -msched-br-in-data-spec
-msched-ar-in-data-spec -msched-in-control-spec -msched-spec-ldc
-msched-spec-control-ldc -msched-prefer-non-data-spec-insns
-msched-prefer-non-control-spec-insns
-msched-stop-bits-after-every-cycle
-msched-count-spec-in-critical-path
-msel-sched-dont-check-control-spec -msched-fp-mem-deps-zero-cost
-msched-max-memory-insns-hard-limit -msched-max-memory-insns=max-insns
๐ท LM32 Options
And last but not least, the LM32 finale ๐ท๐
-mbarrel-shift-enabled -mdivide-enabled
-mmultiply-enabled -msign-extend-enabled -muser-enabled
๐ฆ LoongArch Options
-march=cpu-typeโ pick the CPU type to target ๐-mtune=cpu-typeโ tune for a CPU type โจ-mabi=base-abi-typeโ choose the base ABI type ๐-mfpu=fpu-typeโ pick the FPU type ๐ธ-msimd=simd-typeโ pick the SIMD type ๐ฅ-msoft-floatโ soft float vibes ๐ง-msingle-floatโ single float ๐ฆ-mdouble-floatโ double float ๐-mlsxโ turn on LSX ๐-mno-lsxโ the opposite of-mlsx๐-mlasxโ turn on LASX โญ-mno-lasxโ the opposite of-mlasx๐-mbranch-cost=nโ set the branch cost ton๐-mcheck-zero-divisionโ check for zero division ๐ซถ-mno-check-zero-divisionโ skip that check ๐-mcond-move-intโ conditional move for ints ๐-mno-cond-move-intโ the opposite of-mcond-move-int๐-mcond-move-floatโ conditional move for floats ๐ฆ-mno-cond-move-floatโ the opposite of-mcond-move-float๐ธ-memcpyโ use memcpy โจ-mno-memcpyโ the opposite of-memcpy๐-mstrict-alignโ strict alignment ๐ฅ-mno-strict-alignโ the opposite of-mstrict-align๐ง-mmax-inline-memcpy-size=nโ set the max inline memcpy size ton๐-mexplicit-relocs=styleโ pick an explicit relocs style ๐-mexplicit-relocsโ explicit relocs on โญ-mno-explicit-relocsโ explicit relocs off ๐-mdirect-extern-accessโ direct extern access ๐-mno-direct-extern-accessโ the opposite of-mdirect-extern-access๐ซถ-mcmodel=code-modelโ pick the code model ๐-mrelaxโ relax it ๐-mpass-mrelax-to-asโ pass the relax toas๐ฆ-mrecipโ reciprocal approximations ๐ธ-mrecip=optโ reciprocal approximations, with options โจ-mfrecipeโ frecipe on ๐ฅ-mno-frecipeโ frecipe off ๐-mdiv32โ 32-bit div ๐ง-mno-div32โ the opposite of-mdiv32๐-mlam-bhโ lam-bh on ๐-mno-lam-bhโ lam-bh off โญ-mlamcasโ lamcas on ๐-mno-lamcasโ lamcas off ๐-mld-seq-saโ ld-seq-sa on ๐ซถ-mno-ld-seq-saโ ld-seq-sa off ๐-mtls-dialect=optโ pick the TLS dialect ๐
๐ฆ M32R/D Options
-m32r2โ target M32R2 ๐ธ-m32rxโ target M32RX โจ-m32rโ target M32R ๐ฅ-mdebugโ debug mode ๐ง-malign-loopsโ align loops ๐-mno-align-loopsโ don't align loops ๐-missue-rate=numberโ set the issue rate tonumberโญ-mbranch-cost=numberโ set the branch cost tonumber๐-mmodel=code-size-model-typeโ pick the code-size model type ๐-msdata=sdata-typeโ pick the sdata type ๐ซถ-mno-flush-funcโ no flush function ๐-mflush-func=nameโ flush function namedname๐-mno-flush-trapโ no flush trap ๐ฆ-mflush-trap=numberโ flush trap numbernumber๐ธ-G numโ the-Gsize limit, set tonumโจ
๐ฆ M32C Options
-mcpu=cpuโ pick the CPU ๐ฅ-msimโ simulator mode ๐ง-memregs=numberโ set the number of memregs ๐
๐ฆ M680x0 Options
-march=archโ pick the arch ๐-mcpu=cpuโ pick the CPU โญ-mtune=tuneโ tune it ๐-m68000โ 68000 ๐-m68020โ 68020 ๐ซถ-m68020-40โ 68020-40 ๐-m68020-60โ 68020-60 ๐-m68030โ 68030 ๐ฆ-m68040โ 68040 ๐ธ-m68060โ 68060 โจ-mcpu32โ CPU32 ๐ฅ-m5200โ 5200 ๐ง-m5206eโ 5206e ๐-m528xโ 528x ๐-m5307โ 5307 โญ-m5407โ 5407 ๐-mcfv4eโ ColdFire v4e ๐-mbitfieldโ bitfield on ๐ซถ-mno-bitfieldโ bitfield off ๐-mc68000โ C68000 ๐-mc68020โ C68020 ๐ฆ-mnobitfieldโ bitfield off (the no-bitfield spelling) ๐ธ-mrtdโ rtd on โจ-mno-rtdโ rtd off ๐ฅ-mdivโ div on ๐ง-mno-divโ div off ๐-mshortโ short ints ๐-mno-shortโ no short ints โญ-mhard-floatโ hard float ๐-m68881โ 68881 FPU ๐-msoft-floatโ soft float ๐ซถ-mpcrelโ PC-relative ๐-malign-intโ align ints ๐-mstrict-alignโ strict alignment ๐ฆ-msep-dataโ separate data ๐ธ-mno-sep-dataโ the opposite of-msep-dataโจ-mshared-library-id=nโ shared library IDn๐ฅ-mid-shared-libraryโ ID shared library on ๐ง-mno-id-shared-libraryโ ID shared library off ๐-mxgotโ xgot on ๐-mno-xgotโ xgot off โญ-mlong-jump-table-offsetsโ long jump table offsets ๐
๐ฆ MCore Options
-mhardlitโ hardlit on ๐-mno-hardlitโ hardlit off ๐ซถ-mdivโ div on ๐-mno-divโ div off ๐-mrelax-immediatesโ relax immediates ๐ฆ-mno-relax-immediatesโ the opposite of-mrelax-immediates๐ธ-mwide-bitfieldsโ wide bitfields โจ-mno-wide-bitfieldsโ no wide bitfields ๐ฅ-m4byte-functionsโ 4-byte functions ๐ง-mno-4byte-functionsโ no 4-byte functions ๐-mcallgraph-dataโ callgraph data ๐-mno-callgraph-dataโ no callgraph data โญ-mslow-bytesโ slow bytes ๐-mno-slow-bytesโ no slow bytes ๐-mno-lsimโ no simulator ๐ซถ-mlittle-endianโ little endian ๐-mbig-endianโ big endian ๐-m210โ 210 ๐ฆ-m340โ 340 ๐ธ-mstack-incrementโ stack increment โจ
๐ฆ MicroBlaze Options
-msoft-floatโ soft float ๐ฅ-mhard-floatโ hard float ๐ง-msmall-dividesโ small divides ๐-mcpu=cpuโ pick the CPU ๐-mmemcpyโ memcpy โญ-mxl-soft-mulโ XL soft mul ๐-mxl-soft-divโ XL soft div ๐-mxl-barrel-shiftโ XL barrel shift ๐ซถ-mxl-pattern-compareโ XL pattern compare ๐-mxl-stack-checkโ XL stack check ๐-mxl-gp-optโ XL GP opt ๐ฆ-mno-clearbssโ no clearbss ๐ธ-mxl-multiply-highโ XL multiply high โจ-mxl-float-convertโ XL float convert ๐ฅ-mxl-float-sqrtโ XL float sqrt ๐ง-mbig-endianโ big endian ๐-mlittle-endianโ little endian ๐-mxl-reorderโ XL reorder โญ-mxl-mode-app-modelโ XL mode app model ๐-mpic-data-is-text-relativeโ PIC data is text-relative ๐
๐ฆ MIPS Options
-ELโ little endian ๐ซถ-EBโ big endian ๐-march=archโ pick the arch ๐-mtune=archโ tune for the arch ๐ฆ-mips1โ MIPS I ๐ธ-mips2โ MIPS II โจ-mips3โ MIPS III ๐ฅ-mips4โ MIPS IV ๐ง-mips32โ MIPS32 ๐-mips32r2โ MIPS32 Release 2 ๐-mips32r3โ MIPS32 Release 3 โญ-mips32r5โ MIPS32 Release 5 ๐-mips32r6โ MIPS32 Release 6 ๐-mips64โ MIPS64 ๐ซถ-mips64r2โ MIPS64 Release 2 ๐-mips64r3โ MIPS64 Release 3 ๐-mips64r5โ MIPS64 Release 5 ๐ฆ-mips64r6โ MIPS64 Release 6 ๐ธ-mips16โ MIPS16 โจ-mno-mips16โ no MIPS16 ๐ฅ-mflip-mips16โ flip MIPS16 ๐ง-minterlink-compressedโ interlink compressed ๐-mno-interlink-compressedโ no interlink compressed ๐-minterlink-mips16โ interlink MIPS16 โญ-mno-interlink-mips16โ no interlink MIPS16 ๐-mabi=abiโ pick the ABI ๐-mabicallsโ abicalls on ๐ซถ-mno-abicallsโ abicalls off ๐-msharedโ shared on ๐-mno-sharedโ shared off ๐ฆ-mpltโ PLT on ๐ธ-mno-pltโ PLT off โจ-mxgotโ xgot on ๐ฅ-mno-xgotโ xgot off ๐ง-mgp32โ GP32 ๐-mgp64โ GP64 ๐-mfp32โ FP32 โญ-mfpxxโ FPXX ๐-mfp64โ FP64 ๐-mhard-floatโ hard float ๐ซถ-msoft-floatโ soft float ๐-mno-floatโ no float ๐-msingle-floatโ single float ๐ฆ-mdouble-floatโ double float ๐ธ-modd-spregโ odd single regs on โจ-mno-odd-spregโ odd single regs off ๐ฅ-mabs=modeโ pick the abs mode ๐ง-mnan=encodingโ pick the NaN encoding ๐-mdspโ DSP on ๐-mno-dspโ DSP off โญ-mdspr2โ DSP Rev 2 on ๐-mno-dspr2โ DSP Rev 2 off ๐-mmcuโ MCU on ๐ซถ-mmno-mcuโ MCU off ๐-mevaโ EVA on ๐-mno-evaโ EVA off ๐ฆ-mvirtโ virt on ๐ธ-mno-virtโ virt off โจ-mxpaโ XPA on ๐ฅ-mno-xpaโ XPA off ๐ง-mcrcโ CRC on ๐-mno-crcโ CRC off ๐-mginvโ ginv on โญ-mno-ginvโ ginv off ๐-mmicromipsโ microMIPS on ๐-mno-micromipsโ microMIPS off ๐ซถ-mmsaโ MSA on ๐-mno-msaโ MSA off ๐-mloongson-mmiโ Loongson MMI on ๐ฆ-mno-loongson-mmiโ Loongson MMI off ๐ธ-mloongson-extโ Loongson EXT on โจ-mno-loongson-extโ Loongson EXT off ๐ฅ-mloongson-ext2โ Loongson EXT2 on ๐ง-mno-loongson-ext2โ Loongson EXT2 off ๐-mfpu=fpu-typeโ pick the FPU type ๐-msmartmipsโ SmartMIPS on โญ-mno-smartmipsโ SmartMIPS off ๐-mpaired-singleโ paired single on ๐-mno-paired-singleโ paired single off ๐ซถ-mdmxโ DMX on ๐-mno-mdmxโ DMX off ๐-mips3dโ MIPS-3D on ๐ฆ-mno-mips3dโ MIPS-3D off ๐ธ-mmtโ MT on โจ-mno-mtโ MT off ๐ฅ-mllscโ LLSC on ๐ง-mno-llscโ LLSC off ๐-mlong64โ long is 64-bit ๐-mlong32โ long is 32-bit โญ-msym32โ sym32 on ๐-mno-sym32โ sym32 off ๐-Gnumโ the-Gsize limit, set tonum๐ซถ-mlocal-sdataโ local sdata on ๐-mno-local-sdataโ local sdata off ๐-mextern-sdataโ extern sdata on ๐ฆ-mno-extern-sdataโ extern sdata off ๐ธ-mgpoptโ gpopt on โจ-mno-goptโ gopt off ๐ฅ-membedded-dataโ embedded data on ๐ง-mno-embedded-dataโ embedded data off ๐-muninit-const-in-rodataโ uninit const in rodata on ๐-mno-uninit-const-in-rodataโ uninit const in rodata off โญ-mcode-readable=settingโ pick the code-readable setting ๐-msplit-addressesโ split addresses on ๐-mno-split-addressesโ split addresses off ๐ซถ-mexplicit-relocsโ explicit relocs on ๐-mno-explicit-relocsโ explicit relocs off ๐-mexplicit-relocs=releaseโ explicit relocs withrelease๐ฆ-mcheck-zero-divisionโ check for zero division ๐ธ-mno-check-zero-divisionโ skip that check โจ-mdivide-trapsโ divide traps ๐ฅ-mdivide-breaksโ divide breaks ๐ง-mload-store-pairsโ load-store pairs on ๐-mno-load-store-pairsโ load-store pairs off ๐-mstrict-alignโ strict alignment โญ-mno-strict-alignโ no strict alignment ๐-mno-unaligned-accessโ no unaligned access ๐-munaligned-accessโ unaligned access ๐ซถ-mmemcpyโ memcpy on ๐-mno-memcpyโ memcpy off ๐-mlong-callsโ long calls on ๐ฆ-mno-long-callsโ long calls off ๐ธ-mmadโ MAD on โจ-mno-madโ MAD off ๐ฅ-mimaddโ imadd on ๐ง-mno-imaddโ imadd off ๐-mfused-maddโ fused madd on ๐-mno-fused-maddโ fused madd off โญ-nocppโ no preprocessing ๐-mfix-24kโ fix the 24K ๐-mno-fix-24kโ don't fix the 24K ๐ซถ-mfix-r4000โ fix the R4000 ๐-mno-fix-r4000โ don't fix the R4000 ๐-mfix-r4400โ fix the R4400 ๐ฆ-mno-fix-r4400โ don't fix the R4400 ๐ธ-mfix-r5900โ fix the R5900 โจ-mno-fix-r5900โ don't fix the R5900 ๐ฅ-mfix-r10000โ fix the R10000 ๐ง-mno-fix-r10000โ don't fix the R10000 ๐-mfix-rm7000โ fix the RM7000 ๐-mno-fix-rm7000โ don't fix the RM7000 โญ-mfix-vr4120โ fix the VR4120 ๐-mno-fix-vr4120โ don't fix the VR4120 ๐-mfix-vr4130โ fix the VR4130 ๐ซถ-mno-fix-vr4130โ don't fix the VR4130 ๐-mfix-sb1โ fix the SB-1 ๐-mno-fix-sb1โ don't fix the SB-1 ๐ฆ-mflush-func=funcโ flush function namedfunc๐ธ-mno-flush-funcโ no flush function โจ-mbranch-cost=numโ set the branch cost tonum๐ฅ-mbranch-likelyโ branch likely on ๐ง-mno-branch-likelyโ branch likely off ๐-mcompact-branches=policyโ pick the compact branches policy ๐-mfp-exceptionsโ FP exceptions on โญ-mno-fp-exceptionsโ FP exceptions off ๐-mvr4130-alignโ VR4130 align on ๐-mno-vr4130-alignโ VR4130 align off ๐ซถ-msynciโ synci on ๐-mno-synciโ synci off ๐-mlxc1-sxc1โ lxc1/sxc1 on ๐ฆ-mno-lxc1-sxc1โ lxc1/sxc1 off ๐ธ-mmadd4โ madd4 on โจ-mno-madd4โ madd4 off ๐ฅ-mrelax-pic-callsโ relax PIC calls on ๐ง-mno-relax-pic-callsโ relax PIC calls off ๐-mmcount-ra-addressโ mcount RA address ๐-mframe-header-optโ frame header opt on โญ-mno-frame-header-optโ frame header opt off ๐
๐ฆ MMIX Options
-mlibfuncsโ library functions on ๐-mno-libfuncsโ library functions off ๐ซถ-mepsilonโ epsilon on ๐-mno-epsilonโ epsilon off ๐-mabi=gnuโ the GNU ABI ๐ฆ-mabi=mmixwareโ the mmixware ABI ๐ธ-mzero-extendโ zero extend โจ-mknuthdivโ Knuth div ๐ฅ-mtoplevel-symbolsโ top-level symbols ๐ง-melfโ ELF ๐-mbranch-predictโ branch predict on ๐-mno-branch-predictโ branch predict off โญ-mbase-addressesโ base addresses on ๐-mno-base-addressesโ base addresses off ๐-msingle-exitโ single exit ๐ซถ-mno-single-exitโ no single exit ๐
๐ฆ MN10300 Options
-mmult-bugโ mult bug on ๐-mno-mult-bugโ mult bug off ๐ฆ-mno-am33โ no AM33 ๐ธ-mam33โ AM33 โจ-mam33-2โ AM33-2 ๐ฅ-mam34โ AM34 ๐ง-mtune=cpu-typeโ tune for the CPU type ๐-mreturn-pointer-on-d0โ return pointer on D0 ๐-mno-crt0โ no crt0 โญ-mrelaxโ relax ๐-mliwโ LIW on ๐-msetlbโ SETLB on ๐ซถ
๐ฆ Moxie Options
-mebโ big endian ๐-melโ little endian ๐-mmul.xโ mul.x on ๐ฆ-mno-crt0โ no crt0 ๐ธ
๐ฆ MSP430 Options
-msimโ simulator mode โจ-masm-hexโ assembler hex ๐ฅ-mmcu=โ pick the MCU ๐ง-mcpu=โ pick the CPU ๐-mlargeโ large model ๐-msmallโ small model โญ-mrelaxโ relax ๐-mwarn-mcuโ warn about the MCU ๐-mcode-region=โ code region ๐ซถ-mdata-region=โ data region ๐-msilicon-errata=โ silicon errata ๐-msilicon-errata-warn=โ silicon errata warnings ๐ฆ-mhwmult=โ hardware multiply ๐ธ-minrtโ minimal runtime โจ-mtiny-printfโ tiny printf ๐ฅ-mmax-inline-shift=โ max inline shift ๐ง
๐ฆ NDS32 Options
-mbig-endianโ big endian ๐-mlittle-endianโ little endian ๐-mreduced-regsโ reduced regs โญ-mfull-regsโ full regs ๐-mcmovโ cmov on ๐-mno-cmovโ cmov off ๐ซถ-mext-perfโ ext-perf on ๐-mno-ext-perfโ ext-perf off ๐-mext-perf2โ ext-perf2 on ๐ฆ-mno-ext-perf2โ ext-perf2 off ๐ธ-mext-stringโ ext-string on โจ-mno-ext-stringโ ext-string off ๐ฅ-mv3pushโ v3push on ๐ง-mno-v3pushโ v3push off ๐-m16bitโ 16-bit on ๐-mno-16bitโ 16-bit off โญ-misr-vector-size=numโ ISR vector sizenum๐-mcache-block-size=numโ cache block sizenum๐-march=archโ pick the arch ๐ซถ-mcmodel=code-modelโ pick the code model ๐-mctor-dtorโ ctor/dtor on ๐-mrelaxโ relax ๐ฆ
๐ฆ Nios II Options
-G numโ the-Gsize limit, set tonum๐ธ-mgpopt=optionโ gpopt withoptionโจ-mgpoptโ gpopt on ๐ฅ-mno-gpoptโ gpopt off ๐ง-mgprel-sec=regexpโ gprel section matchingregexp๐-mr0rel-sec=regexpโ r0rel section matchingregexp๐-melโ little endian โญ-mebโ big endian ๐-mno-bypass-cacheโ bypass cache off ๐-mbypass-cacheโ bypass cache on ๐ซถ-mno-cache-volatileโ cache volatile off ๐-mcache-volatileโ cache volatile on ๐-mno-fast-sw-divโ fast software div off ๐ฆ-mfast-sw-divโ fast software div on ๐ธ-mhw-mulโ hardware mul on โจ-mno-hw-mulโ hardware mul off ๐ฅ-mhw-mulxโ hardware mulx on ๐ง-mno-hw-mulxโ hardware mulx off ๐-mno-hw-divโ hardware div off ๐-mhw-divโ hardware div on โญ-mcustom-insn=Nโ custom instructionN๐-mno-custom-insnโ no custom instructions ๐-mcustom-fpu-cfg=nameโ custom FPU configname๐ซถ-mhalโ HAL on ๐-msmallcโ smallc on ๐-msys-crt0=nameโ sys crt0 namedname๐ฆ-msys-lib=nameโ sys lib namedname๐ธ-march=archโ pick the arch โจ-mbmxโ BMX on ๐ฅ-mno-bmxโ BMX off ๐ง-mcdxโ CDX on ๐-mno-cdxโ CDX off ๐
๐ฆ Nvidia PTX Options
-m64โ 64-bit ๐-mmainkernelโ main kernel โจ-moptimizeโ optimize ๐ฅ
๐ฆ OpenRISC Options
-mboard=nameโ board namedname๐ง-mnewlibโ newlib ๐-mhard-mulโ hard mul ๐-mhard-divโ hard div โญ-msoft-mulโ soft mul ๐-msoft-divโ soft div ๐-msoft-floatโ soft float ๐ซถ-mhard-floatโ hard float ๐-mdouble-floatโ double float ๐-munordered-floatโ unordered float ๐ฆ-mcmovโ cmov ๐ธ-mrorโ ror โจ-mroriโ rori ๐ฅ-msextโ sext ๐ง-msfimmโ sfimm ๐-mshftimmโ shftimm ๐-mcmodel=code-modelโ pick the code model โญ
๐ฆ PDP-11 Options
-mfpuโ FPU on ๐-msoft-floatโ soft float ๐-mac0โ ac0 on ๐ซถ-mno-ac0โ ac0 off ๐-m40โ 40 ๐-m45โ 45 ๐ฆ-m10โ 10 ๐ธ-mint32โ int32 โจ-mno-int16โ no int16 ๐ฅ-mint16โ int16 ๐ง-mno-int32โ no int32 ๐-msplitโ split ๐-munix-asmโ Unix assembler โญ-mdec-asmโ DEC assembler ๐-mgnu-asmโ GNU assembler ๐-mlraโ LRA ๐ซถ
๐ฆ PowerPC Options
See RS/6000 and PowerPC Options. ๐
๐ฆ PRU Options
-mmcu=mcuโ pick the MCUmcu๐-minrtโ minimal runtime ๐ฆ-mno-relaxโ relax off ๐ธ-mloopโ loop on โจ-mabi=variantโ pick the ABI variant ๐ฅ
๐ฆ RISC-V Options
-mbranch-cost=N-instructionโ branch cost inN-instruction๐ง-mpltโ PLT on ๐-mno-pltโ PLT off ๐-mabi=ABI-stringโ pick the ABI string โญ-mfdivโ fdiv on ๐-mno-fdivโ fdiv off ๐-mdivโ div on ๐ซถ-mno-divโ div off ๐-misa-spec=ISA-spec-stringโ pick the ISA spec string ๐-march=ISA-stringโ pick the ISA string ๐ฆ-mtune=processor-stringโ tune for the processor string ๐ธ-mpreferred-stack-boundary=numโ preferred stack boundarynumโจ-msmall-data-limit=N-bytesโ small data limit inN-bytes๐ฅ-msave-restoreโ save/restore on ๐ง-mno-save-restoreโ save/restore off ๐-mshorten-memrefsโ shorten memrefs on ๐-mno-shorten-memrefsโ shorten memrefs off โญ-mstrict-alignโ strict alignment ๐-mno-strict-alignโ no strict alignment ๐-mcmodel=medlowโ medlow code model ๐ซถ-mcmodel=medanyโ medany code model ๐-mexplicit-relocsโ explicit relocs on ๐-mno-explicit-relocsโ explicit relocs off ๐ฆ-mrelaxโ relax on ๐ธ-mno-relaxโ relax off โจ-mriscv-attributeโ RISC-V attributes on ๐ฅ-mno-riscv-attributeโ RISC-V attributes off ๐ง-malign-data=typeโ align data bytype๐-mbig-endianโ big endian ๐-mlittle-endianโ little endian โญ-mstack-protector-guard=guardโ stack protector guardguard๐-mstack-protector-guard-reg=regโ stack protector guard registerreg๐-mstack-protector-guard-offset=offsetโ stack protector guard offsetoffset๐ซถ-mcsr-checkโ CSR check on ๐-mno-csr-checkโ CSR check off ๐-mmovccโ movcc on ๐ฆ-mno-movccโ movcc off ๐ธ-minline-atomicsโ inline atomics on โจ-mno-inline-atomicsโ inline atomics off ๐ฅ-minline-strlenโ inline strlen on ๐ง-mno-inline-strlenโ inline strlen off ๐-minline-strcmpโ inline strcmp on ๐-mno-inline-strcmpโ inline strcmp off โญ-minline-strncmpโ inline strncmp on ๐-mno-inline-strncmpโ inline strncmp off ๐-mtls-dialect=descโ TLS dialectdesc๐ซถ-mtls-dialect=tradโ TLS dialecttrad๐
๐ฆ RL78 Options
-msimโ simulator mode ๐-mmul=noneโ no multiply ๐ฆ-mmul=g13โ multiply for G13 ๐ธ-mmul=g14โ multiply for G14 โจ-mallregsโ all regs ๐ฅ-mcpu=g10โ CPU G10 ๐ง-mcpu=g13โ CPU G13 ๐-mcpu=g14โ CPU G14 ๐-mg10โ G10 โญ-mg13โ G13 ๐-mg14โ G14 ๐-m64bit-doublesโ 64-bit doubles ๐ซถ-m32bit-doublesโ 32-bit doubles ๐-msave-mduc-in-interruptsโ save MDUC in interrupts ๐
๐ฆ RS/6000 and PowerPC Options
-mcpu=cpu-typeโ pick the CPU type ๐ฆ-mtune=cpu-typeโ tune for the CPU type ๐ธ-mcmodel=code-modelโ pick the code model โจ-mpowerpc64โ PowerPC64 ๐ฅ-maltivecโ AltiVec on ๐ง-mno-altivecโ AltiVec off ๐-mpowerpc-gpoptโ PowerPC gpopt on ๐-mno-powerpc-gpoptโ PowerPC gpopt off โญ-mpowerpc-gfxoptโ PowerPC gfxopt on ๐-mno-powerpc-gfxoptโ PowerPC gfxopt off ๐-mmfcrfโ mfcrf on ๐ซถ-mno-mfcrfโ mfcrf off ๐-mpopcntbโ popcntb on ๐-mno-popcntbโ popcntb off ๐ฆ-mpopcntdโ popcntd on ๐ธ-mno-popcntdโ popcntd off โจ-mfprndโ fprnd on ๐ฅ-mno-fprndโ fprnd off ๐ง-mcmpbโ cmpb on ๐-mno-cmpbโ cmpb off ๐-mhard-dfpโ hard DFP on โญ-mno-hard-dfpโ hard DFP off ๐-mfull-tocโ full TOC ๐-mminimal-tocโ minimal TOC ๐ซถ-mno-fp-in-tocโ no FP in TOC ๐-mno-sum-in-tocโ no sum in TOC ๐-m64โ 64-bit ๐ฆ-m32โ 32-bit ๐ธ-mxl-compatโ XL compat on โจ-mno-xl-compatโ XL compat off ๐ฅ-mpeโ PE on ๐ง-malign-powerโ align power ๐-malign-naturalโ align natural ๐-msoft-floatโ soft float โญ-mhard-floatโ hard float ๐-mmultipleโ multiple on ๐-mno-multipleโ multiple off ๐ซถ-mupdateโ update on ๐-mno-updateโ update off ๐-mavoid-indexed-addressesโ avoid indexed addresses ๐ฆ-mno-avoid-indexed-addressesโ don't avoid indexed addresses ๐ธ-mfused-maddโ fused madd on โจ-mno-fused-maddโ fused madd off ๐ฅ-mbit-alignโ bit align on ๐ง-mno-bit-alignโ bit align off ๐-mstrict-alignโ strict alignment ๐-mno-strict-alignโ no strict alignment โญ-mrelocatableโ relocatable on ๐-mno-relocatableโ relocatable off ๐-mrelocatable-libโ relocatable lib on ๐ซถ-mno-relocatable-libโ relocatable lib off ๐-mtocโ TOC on ๐-mno-tocโ TOC off ๐ฆ-mlittleโ little ๐ธ-mlittle-endianโ little endian โจ-mbigโ big ๐ฅ-mbig-endianโ big endian ๐ง-mdynamic-no-picโ dynamic no PIC ๐-mswdivโ swdiv on ๐-msingle-pic-baseโ single PIC base โญ-mprioritize-restricted-insns=priorityโ prioritize restricted insns bypriority๐-msched-costly-dep=dependence_typeโ costly dependence typedependence_type๐-minsert-sched-nops=schemeโ insert sched nops withscheme๐ซถ-mcall-aixdescโ AIX descriptors ๐-mcall-eabiโ EABI ๐-mcall-freebsdโ FreeBSD calls ๐ฆ-mcall-linuxโ Linux calls ๐ธ-mcall-netbsdโ NetBSD calls โจ-mcall-openbsdโ OpenBSD calls ๐ฅ-mcall-sysvโ SysV calls ๐ง-mcall-sysv-eabiโ SysV EABI calls ๐-mcall-sysv-noeabiโ SysV no-EABI calls ๐-mtraceback=traceback_typeโ traceback typetraceback_typeโญ-maix-struct-returnโ AIX struct return ๐-msvr4-struct-returnโ SVR4 struct return ๐-mabi=abi-typeโ pick the ABI type ๐ซถ-msecure-pltโ secure PLT ๐-mbss-pltโ BSS PLT ๐-mlongcallโ long call on ๐ฆ-mno-longcallโ long call off ๐ธ-mpltseqโ PLT seq on โจ-mno-pltseqโ PLT seq off ๐ฅ-mblock-move-inline-limit=numโ block move inline limitnum๐ง-mblock-compare-inline-limit=numโ block compare inline limitnum๐-mblock-compare-inline-loop-limit=numโ block compare inline loop limitnum๐-mno-block-ops-unaligned-vsxโ no unaligned VSX block ops โญ-mstring-compare-inline-limit=numโ string compare inline limitnum๐-miselโ isel on ๐-mno-iselโ isel off ๐ซถ-mvrsaveโ vrsave on ๐-mno-vrsaveโ vrsave off ๐-mmulhwโ mulhw on ๐ฆ-mno-mulhwโ mulhw off ๐ธ-mdlmzbโ dlmzb on โจ-mno-dlmzbโ dlmzb off ๐ฅ-mprototypeโ prototype on ๐ง-mno-prototypeโ prototype off ๐-msimโ simulator mode ๐-mmvmeโ MVME โญ-madsโ ADS ๐-myellowknifeโ Yellowknife ๐-membโ EMB ๐ซถ-msdataโ sdata on ๐-msdata=optโ sdata withopt๐-mreadonly-in-sdataโ readonly in sdata ๐ฆ-mvxworksโ VxWorks ๐ธ-G numโ the-Gsize limit, set tonumโจ-mrecipโ reciprocal approximations ๐ฅ-mrecip=optโ reciprocal approximations, with options ๐ง-mno-recipโ reciprocal approximations off ๐-mrecip-precisionโ reciprocal precision on ๐-mno-recip-precisionโ reciprocal precision off โญ-mveclibabi=typeโ vector lib ABItype๐-mfrizโ friz on ๐-mno-frizโ friz off ๐ซถ-mpointers-to-nested-functionsโ pointers to nested functions on ๐-mno-pointers-to-nested-functionsโ pointers to nested functions off ๐-msave-toc-indirectโ save TOC indirect on ๐ฆ-mno-save-toc-indirectโ save TOC indirect off ๐ธ-mpower8-fusionโ POWER8 fusion on โจ-mno-mpower8-fusionโ POWER8 fusion off ๐ฅ-mcryptoโ crypto on ๐ง-mno-cryptoโ crypto off ๐-mhtmโ HTM on ๐-mno-htmโ HTM off โญ-mquad-memoryโ quad memory on ๐-mno-quad-memoryโ quad memory off ๐-mquad-memory-atomicโ quad memory atomic on ๐ซถ-mno-quad-memory-atomicโ quad memory atomic off ๐-mcompat-align-parmโ compat align parm on ๐-mno-compat-align-parmโ compat align parm off ๐ฆ-mfloat128โ float128 on ๐ธ-mno-float128โ float128 off โจ-mfloat128-hardwareโ float128 hardware on ๐ฅ-mno-float128-hardwareโ float128 hardware off ๐ง-mgnu-attributeโ GNU attribute on ๐-mno-gnu-attributeโ GNU attribute off ๐-mstack-protector-guard=guardโ stack protector guardguardโญ-mstack-protector-guard-reg=regโ stack protector guard registerreg๐-mstack-protector-guard-offset=offsetโ stack protector guard offsetoffset๐-mprefixedโ prefixed on ๐ซถ-mno-prefixedโ prefixed off ๐-mpcrelโ PC-relative on ๐-mno-pcrelโ PC-relative off ๐ฆ-mmmaโ MMA on ๐ธ-mno-mmmaโ MMA off โจ-mrop-protectโ ROP protect on ๐ฅ-mno-rop-protectโ ROP protect off ๐ง-mprivilegedโ privileged on ๐-mno-privilegedโ privileged off ๐
โจ RX Options โจ
RX gets its whole own little flex list ๐ every flag, no skipping ๐
-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 โจ
the S/390 crew is giving main character 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 so many flags it's lowkey a whole lifestyle ๐ ๐
-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 โจ
Solaris 2 keeping it short and sweet ๐ธ
-mclear-hwcap -mno-clear-hwcap -mimpure-text
-mno-impure-text -pthreads
โจ SPARC Options โจ
SPARC is a big one, bestie, so grab a snack ๐
-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 -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 -mlra -mno-lra
โจ System V Options โจ
old school but still iconic ๐
-Qy -Qn -YP,paths -Ym,dir
โจ V850 Options โจ
the V850 list is giving lots of options, babe ๐
-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 is tiny and cute ๐ง
-mg -mgnu -munix -mlra
โจ Visium Options โจ
Visium, you're so put together ๐
-mdebug -msim -mfpu -mno-fpu -mhard-float
-msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
โจ VMS Options โจ
VMS flags, serving return codes and malloc drama ๐
-mvms-return-codes -mdebug-main=prefix -mmalloc64
-mpointer-size=size
โจ VxWorks Options โจ
VxWorks is lowkey a vibe check ๐ฆ
-mrtp -msmp -non-static -Bstatic -Bdynamic
-Xbind-lazy -Xbind-now
โจ x86 Options โจ
x86 is the biggest girlie of them all and it's not even close ๐๐ โจ
-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
-mavx512pf -mavx512er -mavx512cd -mavx512vl -mavx512bw
-mavx512dq -mavx512ifma -mavx512vbmi -msha -maes -mpclmul
-mfsgsbase -mrdrnd -mf16c -mfma -mpconfig -mwbnoinvd -mptwrite
-mprefetchwt1 -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 -mavx5124fmaps
-mavx512vnni -mavx5124vnniw -mprfchw -mrdpid -mrdseed -msgx
-mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8
-mamx-bf16 -muintr -mhreset -mavxvnni -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 -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 โจ
Windows x86 bringing the drama ๐
-mconsole -mcrtdll=library -mdll
-mnop-fun-dllimport -mthread -municode -mwin32 -mwindows
-fno-set-stack-executable
โจ Xstormy16 Options โจ
Xstormy16 just has the one, but it's a good one ๐ซถ
-msim
โจ Xtensa Options โจ
Xtensa has a whole collection going on ๐ง๐
-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 just S/390 in a new outfit, so no need to repeat yourself ๐
See S/390 and zSeries Options.
โจ Options Controlling the Kind of Output โจ
Okay so, compiling can have up to four stages: preprocessing, compilation proper, assembly, and linking, always in that order ๐ . GCC can preprocess and compile several files into several assembler input files, or squish them all into one assembler input file. Then each assembler input file makes an object file, and linking glues all the object files together (the ones just compiled and the ones you handed it) into an executable file โจ.
For any given input file, the file name suffix decides what kind of compilation happens:
file.cโ C source code that must be preprocessed.file.iโ C source code that should not be preprocessed.file.iiโ C++ source code that should not be preprocessed.file.mโ Objective-C source code. Note that you must link with thelibobjclibrary to make an Objective-C program work.file.miโ Objective-C source code that should not be preprocessed.file.mm,file.Mโ Objective-C++ source code. Note that you must link with thelibobjclibrary to make an Objective-C++ program work. Note that.Mrefers to a literal capitalM.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. Note that in.cxx, the last two letters must both be literallyx. Likewise,.Crefers to a literal capitalC.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.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). Such files are also called specs.file.adbโ Ada source code file containing a library unit body (a subprogram or package body). Such files 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 is treated this way.
You can specify the input language explicitly with the -x option:
-x languageโ okay bestie, this one lets you spill the tea on what language your next input files are written in, so gcc doesn't have to guess from the file name suffix ๐ฎ It sticks for every input file after it until the next-xshows up. Your choices for language are:c,c-header,cpp-outputc++,c++-header,c++-system-header,c++-user-header,c++-cpp-outputobjective-c,objective-c-header,objective-c-cpp-outputobjective-c++,objective-c++-header,objective-c++-cpp-outputassembler,assembler-with-cppadadf77,f77-cpp-input,f95,f95-cpp-inputgo
-x noneโ the main character move to undo all that ๐ It turns off any language specification, so the files after it get handled by their file name suffixes again, exactly like-xnever existed. โจ
Okay so if you only want some of the compilation stages ๐ง, you can use -x (or filename suffixes) to tell gcc where to start, and then pick one of -c, -S, or -E to say where it should stop. Heads up though, some combos (like -x cpp-output -E) literally make gcc do nothing at all ๐
-cโ compile or assemble the source files, but don't link ๐ธ The linking stage just gets skipped, and you end up with 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, which don't need compiling or assembling, get ignored.
- By default, the object file name for a source file is made by swapping the suffix
-Sโ stop after the compilation proper and don't assemble ๐ฆ You get an assembler code file for each non-assembler input file you gave it.- By default, the assembler file name is made by swapping the suffix
.c,.i, etc. for.s. - Input files that don't need compilation are ignored.
- By default, the assembler file name is made by swapping the suffix
-Eโ stop after preprocessing and skip the compiler proper ๐ The preprocessed source code gets sent to the standard output.- Input files that don't need preprocessing are ignored.
-o fileโ put the primary output intofile๐ This works for whatever you're making: an executable, an object file, an assembler file, or preprocessed C code.- If you don't specify
-o, here's where things land: an executable goes ina.out, the object file forsource.suffixgoes insource.o, its assembler file goes insource.s, a precompiled header file goes insource.suffix.gch, and all the preprocessed C source gets printed to standard output.
- If you don't specify
Okay, the tea is that -o only names the primary output, but it also changes what your auxiliary and dump outputs get called ๐ See the examples below for the full picture. Unless you override it, both auxiliary and dump outputs get dropped into the same directory as the primary output. For auxiliary outputs, the input file's suffix gets swapped for the suffix of the auxiliary file type. For dump outputs, the dump file's suffix gets tacked onto the input file suffix. In compilation commands, the base name of both auxiliary and dump outputs is the primary output's base name. In compile and link commands, the primary output name (minus the executable suffix) gets combined with the input file name. If both share the same base name, ignoring the suffix, the result is just that base name. Otherwise they get smooshed together with a dash in between ๐ซถ
gcc -c foo.c ...
This uses foo.o as the primary output and puts the aux outputs and dumps right next to it. For example, you'd get the aux file foo.dwo for -gsplit-dwarf, and the dump file foo.c.???r.final for -fdump-rtl-final โจ
If you explicitly name a non-linker output file, aux and dump files take the same base name by default:
gcc -c foo.c -o dir/foobar.o ...
This names the aux outputs dir/foobar.* and the dump outputs dir/foobar.c.* ๐
A linker output does things a little differently, prefixing the aux and dump outputs instead:
gcc foo.c bar.c -o dir/foobar ...
This will generally name the aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and the dump outputs dir/foobar-foo.c.* and dir/foobar-bar.c.* ๐
The one exception is when the executable shares its base name with the single input:
gcc foo.c -o dir/foo ...
In this case the aux outputs are named dir/foo.* and the dump outputs are named dir/foo.c.* ๐
Want more control over where these land? You can adjust the location and names of auxiliary and dump outputs with -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 touch the name of the primary output. Intermediate outputs, if you choose to keep them, aren't considered primary outputs. They count as auxiliary outputs instead.
gcc -save-temps -S foo.c
This one saves the (no longer) temporary preprocessed file as foo.i, then compiles to the (implied) output file foo.s. Meanwhile:
gcc -save-temps -dumpbase save-foo -c foo.c
This preprocesses to save-foo.i, compiles to save-foo.s (which is now an intermediate, so it counts as 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 you explicitly gave one. Dump output files, like the ones requested by -fdump-* options, keep the input name suffix. Aux output files, like the ones requested by other non-dump options (for example -save-temps, -gsplit-dwarf, and -fcallgraph-info), drop it.
You can get similar suffix differentiation for dump and aux outputs with an explicitly given -dumpbase basename.suf by also specifying -dumpbase-ext .suf ๐ซถ
If dumpbase is explicitly given with any directory component, then any dumppfx specification (like -dumpdir or -save-temps=*) gets ignored. Instead of being appended to it, dumpbase fully overrides it:
gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
-dumpdir pfx- -save-temps=cwd ...
This creates aux and dump outputs named alt/foo.*, ignoring dir/ from -o, the ./ prefix implied by -save-temps=cwd, and pfx- from -dumpdir ๐
When -dumpbase shows up in a command that compiles multiple inputs, or that compiles and then links, it can get combined with a dumppfx, as explained under -dumpdir. Each input file then gets compiled using the combined dumppfx, and default values for dumpbase and auxdropsuf get computed for each input file:
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs. To avoid overwriting the aux and dump outputs, it uses the dumpbase as a prefix, so the outputs are named main-foo.* and main-bar.* ๐ธ
An empty string given as dumpbase avoids the influence of the output basename on naming aux and dump outputs during compilation, so the default values get computed instead:
gcc -c foo.c -o dir/foobar.o -dumpbase " ...
This names the aux outputs dir/foo.* and the dump outputs dir/foo.c.*. Notice how the basenames come from the input name, but the directory still defaults to the output's directory ๐
The empty-string dumpbase doesn't stop the output basename from being used for outputs during linking, though:
gcc foo.c bar.c -o dir/foobar -dumpbase " -flto ...
The compilation of the source files names the aux outputs dir/foo.* and dir/bar.*, and the dump outputs dir/foo.c.* and dir/bar.c.*. LTO recompilation during linking uses dir/foobar. as the prefix for dumps and aux files ๐
-dumpbase-ext auxdropsufโ when forming the name of an auxiliary output file (but not a dump output), this drops the trailingauxdropsuffromdumpbasebefore any suffixes get appended ๐ If you don't specify it, it defaults to the suffix of a default dumpbase. That means the input file's suffix when-dumpbaseisn't on the command line, or when the dumpbase is combined with adumppfx.
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 aux outputs in dir/x-foo.*. They take the location of the primary output and drop the .c suffix from the dumpbase. Dump outputs keep the suffix, so they land in dir/x-foo.c.* โจ
This option gets ignored if it doesn't match the suffix of a specified dumpbase. The one exception is when it's used as an alternative to the executable suffix while 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. To avoid overwriting the aux and dump outputs, it uses the executable name minus auxdropsuf as a prefix. So the aux outputs get named main-foo.* and main-bar.*, and the dump outputs get named main-foo.c.* and main-bar.c.* ๐ฆ
-dumpdir dumppfxโ when forming the name of an auxiliary or dump output file, this usesdumppfxas a prefix ๐
gcc -dumpdir pfx- -c foo.c ...
This creates foo.o as the primary output and names the auxiliary outputs pfx-foo.*. It combines the given dumppfx with the default dumpbase, which comes from the default primary output, which in turn comes from the input name. Dump outputs also take the input name suffix, so they become pfx-foo.c.* ๐
If you want to use dumppfx as a directory name, it has to 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 names the auxiliary outputs dir/bar.*. It combines the given dumppfx with the default dumpbase derived from the primary output name. Dump outputs take the input name suffix too, so they land in dir/bar.c.* ๐
By default it points at the location of the output file, unless the output file is a special file like /dev/null. The options -save-temps=cwd and -save-temps=obj override this default, just like an explicit -dumpdir option does. If you give multiple of these, the last one wins:
gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
This outputs foo.o, with the auxiliary outputs named foo.*, because -save-temps=* overrides the dumppfx from the earlier -dumpdir option. It doesn't matter that =obj is already the default for -save-temps, or that the output directory is implicitly the current directory. The dump outputs are named foo.c.* ๐ซถ
When you compile from multiple input files and -dumpbase is set, the dumpbase name gets glued onto the dumppfx ๐
. You drop an auxdropsuf suffix and add a dash. If the name has any directory components, it straight up overrides the explicit or defaulted dumppfx instead ๐ซถ. Either way, each compilation gets differently-named aux and dump outputs โจ, which is giving organized.
gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
This one sends auxiliary dumps to dir/pfx-main-foo.* and dir/pfx-main-bar.*, because dumpbase- gets appended to dumppfx ๐ฆ. The dump outputs keep the input file suffix instead: 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 ...
Here -dumpbase is applied to one source, so it doesn't compute and append a separate dumpbase per input file ๐. Its auxiliary and dump outputs just go in dir/pfx-main.*.
When you compile and then link from multiple input files, a defaulted or explicitly specified dumppfx also gets the dumpbase- transformation from above (like the foo.c and bar.c compile, but without -c). If you don't give -dumpdir or -dumpbase, the linker output base name gets the same treatment instead. You subtract auxdropsuf if it's specified, or the executable suffix otherwise, then add a dash and append the result to the default dumppfx. But heads up, this is different from the earlier linking cases:
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
does not append the output name main to dumppfx, because -dumpdir is explicitly specified ๐. The vibe is that an explicit dumppfx can already include the output name in the prefix if you want it there โจ. Only an explicitly specified -dumpbase gets combined with it, so a meaningful option doesn't just get tossed out ๐.
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 an explicit -dumpdir inhibits 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 ๐ธ.
Summing it all up for an intuitive (though slightly imprecise) data flow ๐ง : 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. dumpbase is set to the basename, unless -dumpbase overrides it. If there are multiple inputs or linking, this dumpbase may be 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 they keep the suffix from dumpbase.
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 or derived from the linker output name (but not from the inputs), even in cases where that combination wouldn't otherwise get used. A trailing period replaces the compiler-added dash, if there is one. Since lto-wrapper is involved in linking, it doesn't normally get any -dumpbase or -dumpbase-ext, and it ignores them if it does.
When running sub-compilers, lto-wrapper appends the LTO stage names to the dumppfx it received. It makes sure that prefix contains a directory component, so it overrides any -dumpdir. Then it passes that along as -dumpbase to the sub-compilers ๐.
-vโ Prints the commands executed to run each stage of compilation to standard error. It also prints the version number of the compiler driver program, plus the version of the preprocessor and the compiler proper ๐.-###โ Like-v, except the commands never actually run, and arguments get quoted unless they only contain alphanumeric characters or"./-_". This is perfect for shell scripts that want to capture the driver-generated command lines ๐ง.--helpโ Prints a description of the command-line optionsgccunderstands to standard output. If-vis also specified,--helpgets passed on to the various processesgccinvokes, so they can display the options they accept ๐ซถ. If-Wextrawas specified prior to--helpon the command line, options with no documentation attached get displayed too ๐.--target-helpโ Prints a description of the target-specific command-line options for each tool to standard output. For some targets, extra target-specific information may also get printed โจ.
--help={class|[^]qualifier}[,...]
Print (to standard output) a description of the command-line options the compiler understands that fit into all of the specified classes and qualifiers ๐. These 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 forlanguage, wherelanguageis 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 common to all languages ๐ค.
These 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โ๏ธ.
Thus, for example, to display all the undocumented target-specific switches the compiler supports, use:
--help=target,undocumented
The sense of a qualifier can be flipped by prefixing it with the ^ character. So, for example, to display all binary warning options (ones that are either on or off and don't take an argument) that have a description, use:
--help=warnings,^joined,^undocumented
The argument to --help= should not consist solely of inverted qualifiers ๐
.
Combining several classes is possible, but it usually restricts the output so much that there's nothing to display. 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 successive use displays its requested class of options, skipping any that were already displayed. If --help is also specified anywhere on the command line, it takes precedence over any --help= option ๐.
If the -Q option appears on the command line before the --help= option, the descriptive text displayed by --help= 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 is 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
Alternatively, you can discover which binary optimizations are enabled by -O3 by using:
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 GCC you invoked ๐ฃ.-pass-exit-codesโ Normally,gccexits with the code1if any phase of the compiler returns a non-success return code. With-pass-exit-codes, it returns the numerically highest error produced by any phase that returned an error indication instead. The C, C++, and Fortran front ends return4if they run into 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 ๐ง.-specs=fileโ Processesfileafter the compiler reads in the standard specs file, to override the defaults thegccdriver uses when deciding which switches to pass tocc1,cc1plus,as,ld, and so on ๐ฏ. You can specify more than one-specs=fileon the command line. They get processed in order, from left to right ๐.-wrapperโ Invokes all subcommands under a wrapper program. The name of the wrapper program and its parameters get 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โ okay so this one is a whole glow-up for file paths ๐บ๏ธโจ When you compile files living in directoryold, any references to them in the compilation result get recorded as if they lived innewinstead. Specifying it is equivalent to specifying all the individual-f*-prefix-mapoptions at once ๐ It's giving reproducible builds that are location independent ๐ฆ Directories referenced by directives are not affected by these options. See also-fmacro-prefix-map,-fdebug-prefix-map,-fprofile-prefix-mapand-fcanon-prefix-map๐ธ-fcanon-prefix-mapโ ngl this one is a detail-oriented queen ๐ Normally, for the-f*-prefix-mapoptions, the old prefix gets compared against the filename that would normally be referenced using a textual comparison. That means ignoring character case on case-insensitive filesystems, and treating slashes and backslashes as equal on DOS-based filesystems.-fcanon-prefix-mapmakes those comparisons happen on canonicalized paths ofoldand the referenced filename instead ๐ง-fplugin=name.soโ load the plugin code from the filename.so๐ It's assumed to be a shared object that the compiler willdlopen. The base name of the shared object is used to identify the plugin when parsing arguments (see-fplugin-arg-name-key=valuebelow) ๐ Each plugin should define the callback functions specified in the Plugins API โจ-fplugin-arg-name-key=valueโ defines an argument calledkeywith a value ofvaluefor the plugin calledname๐-fdump-ada-spec[-slim]โ for C and C++ source and include files, generate corresponding Ada specs ๐ ๐-fada-spec-parent=unitโ when used with-fdump-ada-spec[-slim]above, this generates Ada specs as child units of the parentunit๐ฆ-fdump-go-spec=fileโ for input files in any language, generate corresponding Go declarations infile๐น This makes Goconst,type,var, andfuncdeclarations, which is lowkey a really useful way to start writing a Go interface to code written in some other language ๐ซถ@fileโ read command-line options fromfile๐ The options read get inserted right where the original@fileoption was. Iffiledoesn't exist or can't be read, then the option gets treated literally and is not removed ๐ญ
Options inside file are separated by whitespace. If you want a whitespace character inside an option, wrap the entire option in either single or double quotes ๐ Any character (including a backslash) can be included by prefixing it with a backslash ๐ The file can even contain more @file options of its own, and those get processed recursively ๐
โจ 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 ๐ฆ GCC recognizes files with these names and compiles them as C++ programs, even if you call the compiler the same way you would for C programs (usually with the name gcc) ๐
However, using gcc does not add the C++ library ๐ฌ g++ is a program that calls GCC and automatically specifies linking against the C++ library, so it's the main character for C++ ๐ It treats .c, .h and .i files as C++ source files instead of C source files, unless -x is used ๐ This program is also useful when precompiling a C header file with a .h extension for use in C++ compilations ๐ง On many systems, g++ is also installed with the name c++ โจ
When you compile C++ programs, you can specify many of the same command-line options you use for compiling programs in any language ๐ You can also use command-line options meaningful for C and related languages, or options that are meaningful only for C++ programs ๐
๐ Options Controlling C Dialect ๐
The following options control the dialect of C (or languages derived from C, such as C++, Objective-C and Objective-C++) that the compiler accepts ๐ซถ
-ansiโ in C mode, this is equivalent to-std=c90. In C++ mode, it's equivalent to-std=c++98๐
This turns off certain GCC features that are incompatible with ISO C90 (when compiling C code), or with standard C++ (when compiling C++ code) ๐ Examples are the asm and typeof keywords, and predefined macros such as unix and vax that identify the type of system you're using. It also enables the undesirable and rarely used ISO trigraph feature ๐ For the C compiler, it disables recognition of C++ style // comments, as well as the inline keyword ๐ญ
The alternate keywords __asm__, __extension__, __inline__ and __typeof__ keep working despite -ansi โจ You would not want to use them in an ISO C program, of course, but it's useful to put them in header files that might be included in compilations done with -ansi ๐ฆ Alternate predefined macros such as __unix__ and __vax__ are also available, with or without -ansi ๐ธ
The -ansi option does not cause non-ISO programs to be rejected gratuitously ๐ซถ For that, -Wpedantic is required in addition to -ansi โญ
The macro __STRICT_ANSI__ is predefined when the -ansi option is used ๐ Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for. This is to avoid interfering with any programs that might use these names for other things ๐ก๏ธ
Functions that are normally built in but do not have semantics defined by ISO C (such as alloca and ffs) are not built-in functions when -ansi is used ๐ซ
-std=โ determines the language standard ๐ This option is currently only supported when compiling C or C++ ๐ง
The compiler can accept several base standards, such as c90 or c++98, and GNU dialects of those standards, such as gnu90 or gnu++98 ๐ When a base standard is specified, 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, such as the asm and typeof keywords ๐ It does not turn off other GNU extensions that have no meaning in ISO C90, such as omitting the middle term of a ?: expression ๐ญ
On the other hand, when a GNU dialect of a standard is specified, all features supported by the compiler are enabled, even when those features change the meaning of the base standard ๐ค As a result, some strict-conforming programs may get rejected ๐จ The particular standard is used by -Wpedantic to identify which features are GNU extensions given that version of the standard. For example, -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic does not ๐ต๏ธโโ๏ธ
A value for this option must be provided. Possible values are:
c90,c89,iso9899:1990โ supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code ๐iso9899:199409โ ISO C90 as modified in amendment 1 ๐ทc99,c9x,iso9899:1999,iso9899:199xโ ISO C99 ๐ธ This standard is substantially completely supported, modulo bugs and floating-point issues (mainly, but not entirely, relating to optional C99 features from Annexes F and G). See<https://gcc.gnu.org/c99status.html>for more information ๐ The namesc9xandiso9899:199xare deprecated ๐ฅc11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard ๐ This standard is substantially completely supported, modulo bugs, and floating-point issues (mainly, but not entirely, relating to optional C11 features from Annexes F and G). It also covers the optional Annexes K (Bounds-checking interfaces) and L (Analyzability) ๐ค The namec1xis deprecated ๐ฅc17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision of the ISO C standard (published in 2018) ๐ This standard is the same as C11 except for corrections of defects (all of which are also applied with-std=c11) and a new value of__STDC_VERSION__, so it's supported to the same extent as C11 ๐c23,c2x,iso9899:2024โ ISO C23, the 2023 revision of the ISO C standard (expected to be published in 2024) ๐ฎ Support for this version is experimental and incomplete ๐งช The namec2xis deprecated ๐ฅ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. This is the default for C code ๐gnu23,gnu2xโ 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++2b,c++23โ okay bestie, this is the next revision of the ISO C++ standard, planned for 2023 ๐ โจ Support is highly experimental and will almost certainly change in incompatible ways in future releases ๐gnu++2b,gnu++23โ the GNU dialect of-std=c++2b. Same energy: highly experimental and almost certainly going to change in incompatible ways later on ๐c++2c,c++26โ the next revision of the ISO C++ standard, planned for 2026 ๐ฆ Also highly experimental, and it will almost certainly change in incompatible ways in future releases. Don't get too attached ๐ฅบgnu++2c,gnu++26โ the GNU dialect of-std=c++2c๐ Highly experimental, and almost certainly going to change in incompatible ways in future releases.-aux-info filenameโ this one is giving documentation energy ๐ It outputs prototyped declarations for all functions declared and/or defined in a translation unit, including the ones in header files, into the given filename. It's silently ignored in any language other than C, so don't stress if nothing happens in C++ ๐ซถ
The file also drops comments that tell you where each declaration came from (source file and line). The character right after the line number and colon tells you whether the declaration was implicit, prototyped or unprototyped: I for implicit, N for new (prototyped) or O for old (unprototyped). The character after that tells you whether it came from a declaration or a definition: C for declaration or F for definition ๐ For function definitions, you also get a K&R-style list of arguments followed by their declarations, all inside comments, placed after the declaration.
-fno-asmโ the keyword cleanup switch ๐งน This stopsasm,inlineandtypeoffrom being treated as keywords, so your code can use those words as identifiers. You can use__asm__,__inline__and__typeof__instead. In C,-ansiimplies-fno-asm.
In C++, inline is a standard keyword and isn't affected by this switch. If you want, you can use -fno-gnu-keywords instead, which disables typeof but leaves asm and inline alone ๐
In C99 mode (-std=c99 or -std=gnu99), this switch only affects asm and typeof, since inline is a standard keyword in ISO C99. In C23 mode (-std=c23 or -std=gnu23), it only affects asm, since typeof is a standard keyword in ISO C23.
-fno-builtin,-fno-builtin-functionโ this one's a bit of a plot twist ๐ญ It stops GCC from recognizing built-in functions that don't begin with__builtin_as a prefix.
GCC normally generates special code for certain built-in functions so they run more efficiently. For example, calls to alloca may become single instructions that adjust the stack directly, and calls to memcpy may become inline copy loops. The resulting code is often smaller and faster ๐ But since the function calls don't show up as calls anymore, you can't set a breakpoint on them, and you can't change what the functions do by linking against a different library. Also, when a function is recognized as built-in, GCC may use info about it to warn about problems with calls to it, or to generate better code, even if the result still contains calls to that function. For instance, you get warnings with -Wformat for bad calls to printf when printf is built in and strlen is known not to modify global memory.
With -fno-builtin-function, only that one built-in function gets disabled. The function name must not begin with __builtin_. If you name a function that isn't built-in in this version of GCC, the option is ignored ๐ There's no matching -fbuiltin-function option. If you want to pick and choose built-in functions when using -fno-builtin or -ffreestanding, you can define macros like these:
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fcond-mismatchโ lowkey chaotic ๐ It allows conditional expressions with mismatched types in the second and third arguments. The value of such an expression isvoid. This option is not supported for C++ ๐ โโ๏ธ-ffreestandingโ assert the vibe: freestanding ๐๏ธ It asserts that compilation targets a freestanding environment, which implies-fno-builtin. In a freestanding environment, the standard library may not exist, and program startup may not necessarily be atmain. The most obvious example is an OS kernel ๐ This is equivalent to-fno-hosted.-fgimpleโ experimental era ๐งช It enables parsing of function definitions marked with__GIMPLE. This is an experimental feature that allows unit testing of GIMPLE passes.-fgnu-tmโ transactional memory, but make it spicy ๐ฅ 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 an experimental feature, and its interface may change in future versions of GCC as the official specification changes. Please note that not all architectures are supported for this feature โ ๏ธ
For more information on GCC's support for transactional memory,
Note that the transactional memory feature is not supported with non-call exceptions (-fnon-call-exceptions) ๐
-fgnu89-inlineโ the throwback option ๐ผ It tells GCC to use the traditional GNU semantics forinlinefunctions when in C99 mode.
Using this option is roughly equivalent to adding the gnu_inline function attribute to all inline functions โจ
The option -fno-gnu89-inline explicitly tells GCC to use the C99 semantics for inline when in C99 or gnu99 mode. In other words, it specifies 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โ the opposite of freestanding, obviously ๐ It asserts that compilation targets a hosted environment, which implies-fbuiltin. A hosted environment is one where the entire standard library is available, and wheremainhas a return type ofint. Examples are nearly everything except a kernel ๐ธ This is equivalent to-fno-freestanding.-flax-vector-conversionsโ not for new code, bestie ๐ซ It allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types. This option should not be used for new code.-fms-extensionsโ Microsoft header energy ๐ช It accepts some non-standard constructs that are used in Microsoft header files.
In C++ code, this allows member names in structures to be similar to previous type declarations. Like this:
typedef int UOW;
struct ABC {
UOW UOW;
};
Some cases of unnamed fields in structures and unions are only accepted with this option ๐ซ Note that this option is off for all targets except for x86 targets using ms-abi.
-foffload=disable,-foffload=default,-foffload=target-listโ offload era unlocked ๐ This decides which OpenMP and OpenACC offload targets get code generated for them. The default behavior, which is the same as-foffload=default, is to generate code for all supported offload targets.-foffload=disablegenerates code only for the host fallback, while-foffload=target-listgenerates code only for the specified comma-separated list of offload targets.
Offload targets are specified in GCC's internal target-triplet format. To see the list of configured offload targets, run the compiler with -v. They're listed under OFFLOAD_TARGET_NAMES ๐
-foffload-options=options,-foffload-options=target-triplet-list=optionsโ pass the good stuff along ๐ With-foffload-options=options, GCC passes the specified options to the compilers for all enabled offloading targets. If you want options that only apply to a specific target or targets, use the-foffload-options=target-list=optionsform. Thetarget-listis a comma-separated list in the same format as for the-foffload=option.
Typical command lines look like this:
-foffload-options='-fno-math-errno -ffinite-math-only' -foffload-options=nvptx-none=-latomic
-foffload-options=amdgcn-amdhsa=-march=gfx906
-fopenaccโ OpenACC is giving main character ๐ฌ It enables handling of OpenACC directives:#pragma accin C/C++, and!$accin free-form Fortran, plus!$acc,c$accand*$accin fixed-form Fortran. When you specify-fopenacc, the compiler generates accelerated code according to the OpenACC Application Programming Interface v2.6 (https://www.openacc.org). This option implies-pthread, so it's only supported on targets that have support for-pthreadโจ-fopenacc-dim=geomโ set your compute dimensions ๐ This specifies default compute dimensions for parallel offload regions that don't explicitly specify their own. Thegeomvalue is a triple of':'-separated sizes, in order'gang','worker'and'vector'. You can leave a size out to use a target-specific default value ๐ง-fopenmpโ the big OpenMP moment ๐ It enables handling of OpenMP directives:#pragma omp,[[omp::directive(...)]],[[omp::sequence(...)]]and[[omp::decl(...)]]in C/C++, and!$ompin Fortran. It also enables the conditional compilation sentinel!$in Fortran. In fixed source form Fortran, the sentinels can also start withcor*.
When you specify -fopenmp, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5 (https://www.openmp.org) ๐ This option implies -pthread, so it's only supported on targets that have support for -pthread. -fopenmp also implies -fopenmp-simd ๐ซถ
-fopenmp-simdโ the simd-only starter pack ๐ It enables handling of OpenMP'ssimd,declare simd,declare reduction,assume,ordered,scanandloopdirectives, plus combined or composite directives that havesimdas a constituent. That covers#pragma omp,[[omp::directive(...)]],[[omp::sequence(...)]]and[[omp::decl(...)]]in C/C++, and!$ompin Fortran. It also enables the conditional compilation sentinel!$in Fortran. In fixed source form Fortran, the sentinels can also start withcor*. Other OpenMP directives are ignored ๐
Unless -fopenmp is also specified, the loop region binds to the current task region, no matter what bind clause you gave it ๐
โจ -fopenmp-target-simd-clone ๐ฆ
Okay so, GCC already makes SIMD clones for functions marked with declare simd, but bestie, it also makes clones for functions marked with the OpenMP declare target directive that are suitable for vectorization, as long as this option is in effect ๐
. The device-type can be none, host, nohost, or any. Those map to the keywords for the device_type clause of declare target, and clones get generated for the intersection of the devices you specify ๐ฅ.
Fun fact: -fopenmp-target-simd-clone is the same as -fopenmp-target-simd-clone=any, and -fno-openmp-target-simd-clone is 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, so it's not going to sneak up on you ๐.
โจ -fpermitted-flt-eval-methods=style ๐
ISO/IEC TS 18661-3 adds brand-new permissible values for FLT_EVAL_METHOD. These say that operations and constants with a semantic type that is an interchange or extended format should be evaluated to the precision and range of that type ๐ง. The new values are a superset of what C99/C11 allows, and C99/C11 doesn't say what any other positive value of FLT_EVAL_METHOD means. So code that conforms to C11 may never have been written with the new values in mind ๐ญ.
This flag decides whether the compiler allows only the FLT_EVAL_METHOD values from C99/C11, or the extended set from ISO/IEC TS 18661-3. The style is either c11 or ts-18661-3, whichever fits ๐.
The default in a standards-compliant mode (like -std=c11 or similar) is -fpermitted-flt-eval-methods=c11. The default in a GNU dialect (like -std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3 โจ.
The -fdeps-* options are the squad that pulls structured dependency information out of a source file. That means figuring out what resources from other source files the source needs to compile, plus what resources the source itself provides ๐. You can use that info to add dependencies between compilation rules based on what the sources actually contain, instead of making the build tools spell it all out too ๐ซถ.
โจ -fdeps-file=file ๐
This is where the structured dependency information gets written ๐.
โจ -fdeps-format=format ๐
This sets the format for structured dependency information. p1689r5 is the only supported format right now ๐
. Heads up: when this argument is specified, the output of -MF gets stripped of some information (namely C++ modules). That's so it doesn't use extended makefile syntax that most tools won't understand ๐ญ.
โจ -fdeps-target=file ๐ฆ
This is the -MT equivalent for structured dependency information. It names the target that will eventually need any required resources, and that will provide any resources extracted from the source that other sources might need ๐ธ.
โจ -fplan9-extensions ๐ง
This accepts some non-standard constructs used in Plan 9 code ๐.
It enables -fms-extensions. It also lets you pass pointers to structures with anonymous fields to functions that expect pointers to elements of the field's type, and it lets you refer to anonymous fields declared using a typedef ๐. Note that this is only supported for C, not C++ ๐.
โจ -fsigned-bitfields, -funsigned-bitfields, -fno-signed-bitfields, -fno-unsigned-bitfields ๐
These control whether a bit-field is signed or unsigned when the declaration doesn't use either signed or unsigned ๐ฅ. By default, a bit-field like that is signed, which makes sense since basic integer types like int are signed too ๐ซถ.
โจ -fsigned-char ๐
Lets the type char be signed, just like signed char โญ.
This is equivalent to -fno-unsigned-char, which is the negative form of -funsigned-char. And -fno-signed-char is equivalent to -funsigned-char ๐
.
โจ -funsigned-char ๐
Lets the type char be unsigned, just like unsigned char ๐ธ.
Every kind of machine has a default for what char should be. It's either like unsigned char 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, lets 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 always behaves just like one of those two ๐.
โจ -fstrict-flex-arrays (C and C++ only) and -fstrict-flex-arrays=level (C and C++ only) ๐
These control when the trailing array of a structure gets treated as a flexible array member for the purpose of accessing its elements. The value of level sets how strict that is ๐.
-fstrict-flex-arrays is the same as -fstrict-flex-arrays=3, which is the strictest. Every trailing array of a structure is treated as a flexible array member ๐ฅ.
The negative form, -fno-strict-flex-arrays, is the same as -fstrict-flex-arrays=0, which is the least strict. Here, a trailing array only counts as a flexible array member when it's declared as one per the C99 standard and onward ๐ง.
The possible values of level are the same as for the strict_flex_array attribute. You can also control this for one specific trailing array field of a structure by using the variable attribute strict_flex_array ๐.
Also, the -fstrict_flex_arrays option interacts with the -Wstrict-flex-arrays option ๐ซถ.
โจ -fsso-struct=endianness ๐
This sets the default scalar storage order of structures and unions to the endianness you pick. The accepted values are big-endian, little-endian, and native, which is the native endianness of the target and the default โจ. This option isn't supported for C++ ๐.
โ ๏ธ Bestie, be careful here! Using -fsso-struct causes GCC to generate code that is NOT binary compatible with code generated without it, if the endianness you specified isn't the native endianness of the target ๐.
โจ Options Controlling C++ Dialect โจ
This section covers the command-line options that only matter for C++ programs ๐. You can still use most GNU compiler options no matter what language your program is in ๐. For example, you might compile a file firstClass.C like this:
g++ -g -fstrict-enums -O -c firstClass.C
In that example, only -fstrict-enums is an option meant only for C++ programs ๐ง. You can use the other options with any language GCC supports ๐ซถ.
Some options for compiling C programs, such as -std, are also relevant for C++ programs ๐ฅ.
Here's the list of options that are only for compiling C++ programs ๐:
โจ -fabi-version=n ๐ฆ
Uses version n of the C++ ABI. The default is version 0 ๐ธ.
Version 0 refers to the version that conforms most closely to the C++ ABI specification. So the ABI you get with version 0 will change between versions of G++ as ABI bugs get fixed ๐ญ.
Here's the version rundown, bestie ๐ :
- Version 1 โ the first version of the C++ ABI, which first appeared in G++ 3.2 ๐.
- Version 2 โ first appeared in G++ 3.4, and was the default through G++ 4.9 ๐.
- Version 3 โ corrects an error in mangling a constant address as a template argument ๐ธ.
- Version 4 โ first appeared in G++ 4.5, and implements a standard mangling for vector types ๐ฆ.
- Version 5 โ first appeared in G++ 4.6, and corrects the mangling of attribute
const/volatileon function pointer types,decltypeof a plain decl, and use of a function parameter in the declaration of another parameter ๐. - Version 6 โ first appeared in G++ 4.7, and corrects the promotion behavior of C++11 scoped enums and the mangling of template argument packs,
const/static_cast, prefix++and--, and a class scope function used as a template argument ๐ง. - Version 7 โ first appeared in G++ 4.8, and treats
nullptr_tas a builtin type and corrects the mangling of lambdas in default argument scope ๐ฅ. - Version 8 โ first appeared in G++ 4.9, and corrects the substitution behavior of function types with function-cv-qualifiers โจ.
- Version 9 โ first appeared in G++ 5.2, and corrects the alignment of
"nullptr_t"๐. - Version 10 โ first appeared in G++ 6.1, and adds mangling of attributes that affect type identity, such as ia32 calling convention attributes (e.g.
stdcall) ๐. - Version 11 โ first appeared in G++ 7, and corrects the mangling of
sizeof...expressions and operator names. For multiple entities with the same name within a function that are declared in different scopes, the mangling now changes starting with the twelfth occurrence. It also implies-fnew-inheriting-ctors๐ซถ. - Version 12 โ first appeared in G++ 8, and corrects the calling conventions for empty classes on the x86_64 target and for classes with only deleted copy/move constructors. It accidentally changes the calling convention for classes with a deleted copy constructor and a trivial move constructor ๐ญ.
- Version 13 โ first appeared in G++ 8.2, and fixes the accidental change from version 12 ๐.
- Version 14 โ first appeared in G++ 10, and corrects the mangling of the
nullptrexpression ๐ธ. - Version 15 โ first appeared in G++ 10.3, and corrects a G++ 10 ABI tag regression ๐ฆ.
- Version 16 โ first appeared in G++ 11, and changes the mangling of
"__alignof__"so it's distinct from that of"alignof", plus dependent operator names ๐ . - Version 17 โ first appeared in G++ 12, and fixes the layout of classes that inherit from aggregate classes with default member initializers in C++14 and up ๐.
- Version 18 โ first appeared in G++ 13, and fixes manglings of lambdas that have additional context ๐.
- Version 19 โ first appeared in G++ 14, and fixes manglings of structured bindings to include ABI tags ๐.
See also -Wabi ๐.
โจ -fabi-compat-version=n ๐ง
On targets that support strong aliases, G++ works around mangling changes by creating an alias with the correct mangled name whenever it defines a symbol with an incorrect mangled name ๐ฅ. This switch specifies which ABI version to use for that alias ๐ซถ.
okay so with -fabi-version=0 (the default) this one defaults to 13, which is GCC 8.2 compatibility ๐
. if you explicitly pick a different ABI version, it defaults to 0 instead โจ . need compatibility with GCC versions 3.2 through 4.9? then use -fabi-compat-version=2 ๐ซถ
if you skip this option but do pass -Wabi=n, that version gets used for the compatibility aliases ๐ฆ . and if you pass this option alongside plain -Wabi (no version attached), the version from this option is what the warning uses ๐ฅ
-fno-access-control
turns off all access checking, full stop ๐ โโ๏ธ . this one is mainly handy for working around bugs in the access control code ๐
-faligned-new
this is for C++17 new on types that need more alignment than void* ::operator new(std::size_t) provides ๐ง . you can pass a number like -faligned-new=32 to say how much alignment (in bytes) that function gives you, but honestly few people need to override the default of alignof(std::max_align_t) ๐
it's on by default when you're using -std=c++17 โจ
-fchar8_t, -fno-char8_t
bestie, this turns on char8_t support as adopted for C++20 ๐ . you get a brand new char8_t fundamental type, the types of UTF-8 string and character literals change, there are new signatures for user-defined literals, standard library updates, and new __cpp_char8_t and __cpp_lib_char8_t feature test macros ๐
this option lets you overload functions 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 creates incompatibilities with ISO C++11 and later standards ๐ญ . for example, this 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
this makes sure the pointer returned by operator new isn't null before you start poking at the storage it allocated ๐ . honestly it's usually unnecessary, because the C++ standard says operator new only returns 0 if it's declared throw(), and in that case the compiler always checks the return value even without this option ๐ . in every other case, when operator new has a non-empty exception specification, running out of memory gets signalled by throwing std::bad_alloc ๐ฅ
see also new (nothrow) ๐ซง
-fconcepts, -fconcepts-ts
this turns on support for the C++ Concepts feature, which lets you constrain template arguments ๐ฆ . with -std=c++20 and above, Concepts are part of the language standard, so -fconcepts defaults to on โจ
some constructs that got allowed by the earlier C++ Extensions for Concepts Technical Specification, ISO 19217 (2015), but never made it into the standard can be enabled with -fconcepts-ts ๐งฉ
๐จ -fconcepts-ts was deprecated in GCC 14 and may be removed in GCC 15. users are expected to convert their code to C++20 concepts, so start the glow-up now ๐
-fconstexpr-depth=n
sets the max nested evaluation depth for C++11 constexpr functions to n ๐ . you need a limit here to catch endless recursion during constant expression evaluation. the minimum the standard specifies is 512 ๐งฎ
-fconstexpr-cache-depth=n
sets the max nesting level of constexpr evaluation depth that gets cached to n ๐ง . it's a heuristic, so you're trading compilation speed (when the cache skips repeated calculations) against memory consumption (when the cache gets huge from highly recursive evaluations) โ๏ธ . the default is 8. very few users are likely to want to adjust it, but if your code does heavy constexpr calculations, feel free to experiment and see which value works best for you ๐
-fconstexpr-fp-except
okay so Annex F of the C standard says IEC559 floating point exceptions hit at compile time should not stop compilation ๐ค . C++ compilers have historically not followed that, and instead treat floating point division by zero as non-constant even though it has a well-defined value ๐ . this flag tells the compiler to give Annex F priority over other rules saying a particular operation is undefined โจ
constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
-fconstexpr-loop-limit=n
sets the max number of iterations for a loop in C++14 constexpr functions to n ๐ . a limit is needed to catch infinite loops during constant expression evaluation. the default is 262144 (1<<18)
-fconstexpr-ops-limit=n
sets the max number of operations during a single constexpr evaluation ๐งฎ . even when a single loop's iterations are capped by the limit above, you can still get stuck: if there are several nested loops, each with lots of iterations that are still under that limit, or if a loop body (or even code outside a loop) has too many expressions to evaluate, the constexpr evaluation might take too long ๐ฉ . the default is 33554432 (1<<25)
-fcontracts
this enables experimental support for the C++ Contracts feature ๐งช . it was briefly added to and then removed from the C++20 working paper (N4820). the implementation also includes proposed enhancements from papers P1290, P1332, and P1429. this is mostly for people experimenting to refine the feature so it's ready for a future C++ standard ๐ฌ
on a violation of a checked contract, the violation handler gets called. you can replace the violation handler by defining:
void
handle_contract_violation (const std::experimental::contract_violation&);
there are different sets of additional flags for N4820 contracts, P1332 contracts, or P1429 contracts, and these sets cannot be used together โ . the flags are:
-fcontract-mode=[on|off]โ controls whether any contracts have any semantics at all. defaults toon.-fcontract-assumption-mode=[on|off]โ [N4820] controls whether contracts with levelaxiomshould have the assume semantic. defaults toon.-fcontract-build-level=[off|default|audit]โ [N4820] specifies which level of contracts to generate checks for. defaults todefault.-fcontract-continuation-mode=[on|off]โ [N4820] controls whether the program is allowed to keep executing after a contract violation. that is, checked contracts have themaybesemantic (described below) rather than theneversemantic. defaults tooff.-fcontract-role=<name>:<default>,<audit>,<axiom>โ [P1332] specifies the concrete semantics for each contract level of a particular contract role.-fcontract-semantic=[default|audit|axiom]:<semantic>โ [P1429] specifies 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 tooff.
the possible concrete semantics you can set 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 is called. if the handler returns,std::terminateis called.check_maybe_continue,maybeโ this contract is checked. if it fails, the violation handler is called. if the handler returns, execution continues normally.
-fcoroutines
enables support for the C++ coroutines extension ๐งต . just know it's experimental โ๏ธ
-fdiagnostics-all-candidates
lets the C++ front end note all candidates during an overload resolution failure, including when a deleted function gets selected ๐
-fno-elide-constructors
so the C++ standard lets an implementation skip creating a temporary that's only used to initialize another object of the same type ๐๏ธ . specifying this option disables that optimization and forces G++ to call the copy constructor in all cases ๐ . it also causes G++ to call trivial member functions that would otherwise get 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
this tells the compiler not to generate code that checks for violations of exception specifications at run time ๐ซ . it violates the C++ standard, but it can be useful for shrinking code size in production builds, kinda like defining NDEBUG ๐งน
๐ this does NOT give your code permission to throw exceptions in violation of the exception specifications! the compiler still optimizes based on those specs, so throwing an unexpected exception results in undefined behavior at run time
-fextern-tls-init,-fno-extern-tls-initโ okay bestie, C++11 and OpenMP letthread_localandthreadprivatevariables do dynamic (runtime) initialization ๐ง. To make that work, every use of one of these variables goes through a wrapper function that handles any setup it needs ๐ . When the use and the definition live in the same translation unit, the compiler can optimize that overhead away โจ. But if the use is in a different translation unit, you eat significant overhead even when 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 (because the variable is statically initialized, or because a use in the defining TU runs before any uses 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โ this lets the C++ frontend fold calls tostd::move,std::forward,std::addressofandstd::as_const๐ธ. Unlike regular inlining, no debug information gets generated for these calls. Since they're rarely interesting to debug, this is enabled by default unless-fno-inlineis active ๐.-fno-gnu-keywordsโ don't treattypeofas 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โ this turns off immediate function escalation, where certain functions 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);
}
This compiles in C++20 ๐. f is an immediate-escalating function (because of the auto it's a function template, and it's declared constexpr), and id(t) is an immediate-escalating expression, so f gets promoted to consteval โจ. That means the call to id(t) is in an immediate context, so it doesn't have to produce a constant (this is the mechanism that allows consteval function composition) ๐ง. However, with -fno-immediate-escalation, f is not promoted to consteval, and since the call to the consteval function id(t) is not a constant expression, the compiler rejects the code ๐. This option is turned on by default, and it's only effective in C++20 mode or later ๐.
-fimplicit-constexprโ make 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, along with other optimizations โญ.-fno-implicit-templatesโ never emit code for non-inline templates that get instantiated implicitly (aka by use), and only emit code for explicit instantiations ๐ซถ. If you use this option, you have to be careful to structure your code so it includes all the explicit instantiations it needs, or you'll get undefined symbols at link time ๐ญ.-fno-implicit-inline-templatesโ don't emit code for implicit instantiations of inline templates either ๐ . By default, inlines are handled differently so that compiles with and without optimization need the same set of explicit instantiations ๐ฆ.-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-ts,-fno-modules-tsโ enable support for C++20 modules ๐ง. You usually won't need-fno-modules-ts, since that's already the default. Even though modules are a C++20 feature, they aren't implicitly enabled just by selecting that standard version ๐.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ compile a header file so it becomes an importable header unit ๐ธ.-fmodule-implicit-inlineโ member functions defined inside their class definitions are not implicitly inline for modular code ๐ค. This is different from traditional C++ behavior, and there are good reasons for it, but it can be a headache when porting code ngl ๐ญ. This option makes those function definitions implicitly inline. Just know it generates an ABI incompatibility, so you have to use it everywhere or nowhere โ ๏ธ. (Definitions outside of a named module stay implicitly inline regardless โจ.)-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 an oracle you can query for module name to filename mappings ๐ฎ. If you don't specify one, theCXX_MODULE_MAPPERenvironment variable gets used, and if that's unset, an in-process default is provided ๐.-fmodule-onlyโ only emit the Compiled Module Interface, and skip any object file ๐ฆ.-fms-extensionsโ disableWpedanticwarnings about constructs used in MFC, like implicitintand getting a pointer to a member function via non-standard syntax ๐.-fnew-inheriting-ctorsโ enable the P0136 adjustment to the semantics of C++11 constructor inheritance โจ. This is 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 ๐ธ. This allows a template with default template arguments to be used as an argument for a template template parameter with 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 ๐. These includeffs,alloca,_exit,index,bzero,conjf, and other related functions ๐.-fnothrow-optโ treat athrow()exception specification as if it were anoexceptspecification ๐ฅ. This reduces or eliminates the text size overhead compared to a function with no exception specification ๐. If the function has local variables of types 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 such an exception specification results in a call toterminaterather thanunexpected๐.-fno-operator-namesโ don't treat the operator name keywordsand,bitand,bitor,compl,not,orandxoras synonyms for keywords ๐ .-fno-optional-diagsโ disable diagnostics that the standard says a compiler doesn't need to issue ๐ซ . Right now, the only one G++ issues in that category is the one for a name having multiple meanings within a class ๐คท.-fno-pretty-templatesโ when an error message mentions 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 the signature ๐. For example, you getvoid f(T) [with T = int]instead ofvoid f(int), so it's clear which template is involved ๐. When an error message mentions a specialization of a class template, the compiler leaves out any template arguments that match the default template arguments for that template โจ. If either of these behaviors makes errors harder to understand instead of easier, you can use-fno-pretty-templatesto turn them off ๐ซถ.-fno-rttiโ disable generation of information about every class with virtual functions, which C++ run-time type identification (dynamic_castandtypeid) uses ๐ง. 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 as needed ๐ธ. Thedynamic_castoperator can still be used for casts that don't require run-time type information, i.e. casts tovoid *or to unambiguous base classes ๐ฆ.
Mixing code compiled with -frtti with code compiled with -fno-rtti may not work ๐ฌ. For example, programs may fail to link if a class compiled with -fno-rtti is used as a base for a class compiled with -frtti โ ๏ธ.
-fsized-deallocationโ enable the built-in global declarations introduced in C++14 ๐:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
This is super useful for 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 in the enumeration ๐ง . (Per the C++ standard, that's basically a value that fits 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โ 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 ๐. It's enabled by default with-std=c++17โจ.-fstrong-eval-order=someenables just the ordering of member access and shift expressions, and it's the default without-std=c++17๐ธ.-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โ ๐ okay so this sets the max instantiation depth for template classes ton. That limit is what lets the compiler catch endless recursion during template class instantiation, which is honestly a lifesaver. ANSI/ISO C++ conforming programs must not rely on a max depth greater than17(it got bumped to1024in C++11). The default is900, because the compiler can run out of stack space before it ever reaches1024in some situations ๐ญ-fno-threadsafe-staticsโ skip the extra code that uses the C++ ABI's thread-safe initialization routines for local statics โจ If your code doesn't need to be thread-safe, this can shave a little off code size.-fuse-cxa-atexitโ registers destructors for objects with static storage duration using__cxa_atexitinstead ofatexit๐ฆ This is required for fully standards-compliant handling of static destructors, but it only works if your C library supports__cxa_atexit.-fno-use-cxa-get-exception-ptrโ don't use the__cxa_get_exception_ptrruntime routine. ๐ This makesstd::uncaught_exceptionincorrect, but it's necessary if that runtime routine isn't available.-fvisibility-inlines-hiddenโ ๐ this switch tells GCC that you won't try to compare pointers to inline functions or methods when their addresses are taken in different shared objects.
GCC can then effectively mark inline methods with __attribute__ ((visibility ("hidden"))), so they don't show up in a DSO's export table and don't need a PLT indirection when used inside that DSO. This can have a dramatic effect on load and link times for a DSO, because it massively shrinks the dynamic export table when a library leans hard on templates ๐ฅ
This isn't quite the same as marking methods 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 mark a method with an explicit visibility to cancel out the switch for that method. For example, if you do want to compare pointers to a particular inline method, mark it 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โ ๐ this flag tries to use visibility settings to make GCC's C++ linkage model match Microsoft Visual Studio's. It makes these changes to GCC's linkage model:- It sets the default visibility to
hidden, like-fvisibility=hidden. - Types, but not their members, are not hidden by default.
- The One Definition Rule is relaxed for types without explicit visibility specifications that are defined in more than one shared object. Those declarations are permitted if they'd be permitted when this option isn't used.
- It sets the default visibility to
In new code it's better to use -fvisibility=hidden and export just the classes that are meant to be externally visible. Unfortunately, code might rely on the Visual Studio behavior, perhaps accidentally.
Among the consequences: static data members of the same type, with the same name, defined in different shared objects are different, so changing one doesn't change the other. Pointers to function members defined in different shared objects may also not compare equal.
โ ๏ธ When this flag is given, defining types with the same name differently is a violation of the ODR. Be careful, bestie.
-fno-weakโ do not use weak symbol support, even if the linker provides it. By default, G++ uses weak symbols when they're available. This option exists only for testing and should not be used by end-users ๐ It results in inferior code and has no benefits. It may be removed in a future release of G++.-fext-numeric-literals(C++ and Objective-C++ only) โ ๐ง this accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions. When it's turned off, those suffixes are treated as C++11 user-defined literal numeric suffixes.
It's on by default for all pre-C++11 dialects and all GNU dialects: -std=c++98, -std=gnu++98, -std=gnu++11, -std=gnu++14. It's off by default for ISO C++11 onwards (-std=c++11, ...).
-nostdinc++โ don't search for header files in the standard directories specific to C++, but still search the other standard directories. (This option is used when building the C++ library.) ๐ธ-flang-info-include-translate,-flang-info-include-translate-not,-flang-info-include-translate=headerโ ๐ฆ these inform you of include translation events. The first one notes accepted include translations, the second notes declined ones. Theheaderform informs you about include translations relating to that specific header. Ifheaderis of the form"user"or"<system>", it gets resolved to a specific user or system header using the include path.-flang-info-module-cmi,-flang-info-module-cmi=moduleโ ๐ these inform you of Compiled Module Interface (CMI) pathnames. The first one notes all read CMI pathnames. Themoduleform notes reading a specific module's CMI.modulemay be a named module or a header-unit. A header-unit is indicated by either being 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 choices:libstdc++(the default, native C++ runtime for G++) andlibc++, which is the C++ runtime installed on some operating systems (e.g. Darwin versions from Darwin11 onwards). This switches G++ to use the headers from the specified library, and to emit-lstdc++or-lc++respectively when a C++ runtime is required for linking.
In addition, these warning options have meanings only for C++ programs ๐
-Wabi-tag(C++ and Objective-C++ only) โ โ ๏ธ warns when a type with an ABI tag is used in a context that doesn't have that ABI tag. See C++ Attributes for more information about ABI tags.-Wcomma-subscript(C++ and Objective-C++ only) โ ๐ warns about uses of a comma expression within a subscripting expression. This usage was deprecated in C++20 and is going to be removed in C++23. A comma expression wrapped in( )is not deprecated. 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 isn't valid in C++23, but used to be valid (though deprecated) in C++20, with a pedantic warning. That warning can be disabled with -Wno-comma-subscript.
This is enabled by default with -std=c++20 unless -Wno-deprecated is given, and with -std=c++23 regardless of -Wno-deprecated.
This warning is upgraded to an error by -pedantic-errors in C++23 mode or later.
-Wctad-maybe-unsupported(C++ and Objective-C++ only) โ ๐ warns when performing class template argument deduction (CTAD) on a type with no explicitly written deduction guides. This points out cases where CTAD succeeded only because the compiler synthesized the implicit deduction guides, which might not be what the programmer intended. Certain style guides allow CTAD only on types that specifically "opt-in", i.e. types designed to support CTAD. This warning can be suppressed 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 of 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 ended. For example:
int n = 1;
const int& r = std::max(n - 1, n + 1); // r is dangling
In the example above, two temporaries are created, one for each argument, and a reference to one of the temporaries is returned. However, both temporaries are destroyed at the end of the full expression, so the reference r is dangling. This warning also detects 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 are checked as well, but only their object argument:
struct S {
const S& self () { return *this; }
};
const S& s = S().self(); // s is dangling
Certain functions are safe in this respect, for example std::use_facet: they take and return a reference, but they don't return one of its arguments, which can fool the warning. Such functions can be excluded from the warning 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 will be disabled for all the member functions.
-Wdangling-reference also warns about code like:
auto p = std::minmax(1, 2);
Okay so the std::minmax situation is a whole trap, bestie ๐ญ It returns a std::pair<const int&, const int&>, and both of those references dangle once the full expression that contains the std::minmax call ends ๐
This warning doesn't go off for "std::span"-like classes ๐ฆ So what counts as span-like? We're talking about a class that looks something like this:
template<typename T>
struct Span {
T* data_;
std::size len_;
};
So basically, a non-union class with a pointer data member and a trivial destructor is span-like ๐ธ If you really need the warning gone, the gnu::no_dangling attribute turns it off ๐
And yes, this warning is on under -Wall ๐
-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ Okay, this one is a red flag ๐ฉ It warns whendeletedestroys an instance of a class that has virtual functions but a non-virtual destructor. Deleting a derived object through a base-class pointer is unsafe when the base doesn't have a virtual destructor ๐ฌ Enabled by-Wallโจ-Wdeprecated-copy(C++ and Objective-C++ only) โ This one warns that the implicit copy constructor or copy assignment operator is deprecated when the class has a user-provided copy constructor or copy assignment operator (C++11 and up) ๐ It's enabled by-Wextra. Add-Wdeprecated-copy-dtorand it also deprecates the implicit version when the class has a user-provided destructor ๐-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only) โ This turns off the warning for when the usual arithmetic conversions hit operands where one is an enum and the other is a different enum. That conversion got deprecated in C++20 ๐ฅ For example:
enum E1 { e };
enum E2 { f };
int k = f - e;
-Wdeprecated-enum-enum-conversion is on by default with -std=c++20. In pre-C++20 dialects, you can turn it on with -Wenum-conversion ๐
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only) โ Same energy, but this time the warning is for an enum mixed with a floating-point type in the usual arithmetic conversions. Also deprecated in C++20 ๐ง For example:
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7;
-Wdeprecated-enum-float-conversion is on by default with -std=c++20. In pre-C++20 dialects, use -Wenum-conversion to enable it ๐
-Wno-elaborated-enum-baseโ For C++11 and above, 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 in a declaration that isn't just a standalone declaration of the enum ๐ It's on by default, and-pedantic-errorsupgrades it to an error ๐ฅ-Wno-init-list-lifetime(C++ and Objective-C++ only) โ Do not warn aboutstd::initializer_listuses that are likely to leave you with dangling pointers. The array behind aninitializer_listis treated like a normal C++ temporary, so it's super easy to accidentally hold a pointer to it after it's gone ๐ญ Here are the main ways that goes wrong:- 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 gets assigned from a brace-enclosed initializer list, the temporary array made for the right side only lives until the end of the full-expression. So by the next statement, that variable is dangling ๐ฅบ
// 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
- When a list constructor stores the
beginpointer from aninitializer_listargument, that does not extend the array's lifetime. So if a class variable gets constructed from a temporaryinitializer_list, the pointer is left dangling by the end of the variable declaration statement ๐ฆ -Winvalid-constexpr(C++ and Objective-C++ only) โ This warns when a function never actually 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 an invocation could be an evaluated subexpression of a core constant expression. C++23 dropped that requirement, so aconstexprfunction or template might end up with no invocation that qualifies, and that's allowed now ๐ธ This warning is on by default as a pedantic warning in C++20 and earlier. In C++23, you can turn on-Winvalid-constexpr, and then it's 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's 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. It's a conforming extension, done so older code that uses formatting macros from<inttypes.h>keeps 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 handles warnings when a user-defined literal operator is declared with a literal suffix identifier that doesn't begin with an underscore. Those identifiers are reserved for future standardization, so these warnings are enabled by default ๐
-Wno-narrowing(C++ and Objective-C++ only) โ For C++11 and later, narrowing conversions get diagnosed by default, because the standard requires it ๐ A narrowing conversion from a constant is an error, and a narrowing conversion from a non-constant is a warning.-Wno-narrowingsuppresses that diagnostic. Heads up though, this doesn't change the meaning of well-formed code, since narrowing conversions are still ill-formed in SFINAE contexts ๐ With-Wnarrowingin 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) โ This warns when anoexceptexpression evaluates to false because of a call to a function that lacks a non-throwing exception specification (throw()ornoexcept), even though the compiler knows that function never throws ๐ค-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. As an 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 raw memory function call, likememsetormemcpy, is an object of class type. It also warns when writing into that object might skip a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers ๐ฑ Messing with the representation of these objects can violate invariants the member functions rely on. For example, thememsetcall below is undefined because it modifies a non-trivial class object, so GCC flags it ๐จ
std::string str = "abc";
memset (&str, 0, sizeof str);
The safe move for initializing or clearing storage for these types is to use the appropriate constructor or assignment operator, if there is one ๐ซถ -Wclass-memaccess is enabled by -Wall. If you explicitly cast the pointer to the class object to void *, or to a type the raw memory function can safely access, the warning goes away ๐ฆ
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ This warns when a class has virtual functions and an accessible non-virtual destructor, either on itself or on an accessible polymorphic base class. Deleting a derived instance through a pointer to the class or its base is possible but unsafe in that case ๐ This warning is automatically enabled if-Weffc++is specified. Honestly,-Wdelete-non-virtual-dtor(enabled by-Wall) is the one to prefer, because it warns about the unsafe cases without false positives ๐-Wregister(C++ and Objective-C++ only) โ This warns on uses of theregisterstorage class specifier, except when it's part of the GNU Explicit Register Variables extension. Theregisterkeyword got deprecated in C++11 and removed in C++17 ๐ฅ It's enabled by default with-std=c++17๐-Wreorder(C++ and Objective-C++ only) โ okay bestie, this one is SO relatable ๐ It warns when the member initializers you wrote are in a different order than they actually run in. You typed them one way and the compiler is like "nah, declaration order only ๐ " For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler rearranges the initializers for i and j so they match the order the members are declared in, and it warns you about it with a little ๐ซถ This warning is enabled by -Wall.
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this one warns when a call tostd::movestops copy elision from happening ๐ญ A typical copy elision moment is returning from a function with a class return type, where the expression being returned is the name of a non-volatile automatic object, it's not a function parameter, and it has the same type as the function return type. Here's the tea:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
But in this example, the std::move call prevents copy elision, so it's giving main character energy in the wrong way ๐ This warning is enabled by -Wall.
-Wno-redundant-move(C++ and Objective-C++ only) โ this one catches redundant calls tostd::move, aka the ones where a move would have happened anyway 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 isn't applicable. Consider:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant. Because G++ implements Core Issue 1579, another example is:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this example, copy elision isn't applicable because the type of the expression being returned and the function return type differ, yet G++ still treats the return value as if it were designated by an rvalue ๐ธ This warning is enabled by -Wextra.
-Wrange-loop-construct(C++ and Objective-C++ only) โ this one warns when a C++ range-based for-loop is making an unnecessary copy ๐ That usually 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 ๐
It also warns when a loop variable in a range-based for-loop is initialized with a value of a different type, which results in a copy. For example:
void fn() {
int arr[10];
for (const double &x : arr) { ... }
}
In the example above, every iteration of the loop creates and destroys a temporary value of type double, which the reference const double & is bound to ๐ซ This warning is enabled by -Wall.
-Wredundant-tags(C++ and Objective-C++ only) โ this one warns about redundant class-key and enum-key stuff in references to class types and enumerated types, in spots where the key could be dropped without causing an ambiguity ๐ง For example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
On the other hand, in this example there is no warning, because the keyword is actually needed:
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) โ this one says "don't warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage" ๐ โโ๏ธ Here's why it matters: 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.Cfile, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default โจ-Weffc++(C++ and Objective-C++ only) โ this one warns about violations of the following style guidelines from Scott Meyers' Effective C++ series of books ๐ Respect the vibes:- 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 base classes too ๐ซถ
When you select this option, be aware that the standard library headers don't obey all of these guidelines, so you can use grep -v to filter out those warnings. Not your problem, not your fault ๐
-Wno-exceptions(C++ and Objective-C++ only) โ disables the warning about an exception handler being shadowed by another handler ๐ซฃ That one can point out a wrong ordering of exception handlers, so it's a whole vibe check.-Wstrict-null-sentinel(C++ and Objective-C++ only) โ this one warns about using an uncastedNULLas a sentinel ๐ When you're compiling only with GCC, it's a valid sentinel, sinceNULLis defined to__null. Even though it's a null pointer constant rather than a null pointer, it's guaranteed to be the same size as a pointer. But this use isn't portable across different compilers, so bestie, be careful ๐ฅบ-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, from before the ISO standard was implemented, declarations likefriend int foo(int), where the name of the friend is an unqualified-id, could be read as a particular specialization of a template function. The warning exists to diagnose those 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 in a C++ program ๐ The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are way less vulnerable to unintended effects and much easier to search for, so switch over, no cap โจ-Woverloaded-virtual,-Woverloaded-virtual=n(C++ and Objective-C++ only) โ these warn when a function declaration hides virtual functions from a base class ๐ Check this drama:
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, so code like this:
B* b;
b->f();
fails to compile ๐ญ If the different signatures aren't an accident, the simplest fix 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:
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 picks a promotion from an unsigned or enumerated type to a signed type, over a conversion to an unsigned type of the same size ๐ฅ Older versions of G++ tried to preserve unsignedness, but the standard mandates the current behavior, so it is what it is.-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, like the STL, so you can still use the STL. You may also instantiate or specialize templates.-Wmismatched-new-delete(C++ and Objective-C++ only) โ warns about mismatches between calls tooperator neworoperator deleteand the corresponding call to the allocation or deallocation function ๐ซถ This includes invocations of C++operator deletewith pointers returned from either mismatched forms ofoperator new, or from other functions that allocate objects for whichoperator deleteisn't a suitable deallocator. It also covers calls to other deallocation functions with pointers returned fromoperator newfor 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
}
Okay so the new/free mix-up above is exactly what this one catches ๐ญ The related option -Wmismatched-dealloc ๐ฆ handles mismatches for allocation and deallocation functions other than operator new and operator delete. Different vibe, same energy. Also, -Wmismatched-new-delete is included in -Wall ๐
-Wmismatched-tags(C++ and Objective-C++ only) โ ๐ Warns when a struct, class, or class template (or one of its specializations) gets declared with a class-key that doesn't match the definition, or the first declaration if there's no definition. In this example, thestruct Objectin the argument list ofdrawsets it off. To dodge the warning, either drop the redundantstructor swap it forclassso it matches the definition.
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
Using struct as a class-key is totally legal, as the example shows ๐ This option is just here to keep your class declarations looking consistent. If your code is meant to be portable to Windows-based compilers, it also helps prevent unresolved references caused by different mangling of symbols declared with different class-keys โจ You can use it on its own or together with -Wredundant-tags.
-Wmultiple-inheritance(C++ and Objective-C++ only) โ ๐ฆ Warns when a class is defined with multiple direct base classes. Some coding rules ban multiple inheritance, so this lets you enforce that rule. It stays quiet inside system headers like the STL, so you can still use the STL ๐ You can also define classes that indirectly use multiple inheritance.-Wvirtual-inheritanceโ ๐ธ Warns when a class is defined with a virtual direct base class. Same deal: some coding rules disallow multiple inheritance, so this can enforce that. It's inactive inside system headers like the STL, so the STL is still fair game. You can also define classes that indirectly use virtual inheritance.-Wno-virtual-move-assignโ Suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator.
๐ This is dangerous! If the virtual base is reachable along more than one path, it gets moved multiple times, which can leave both objects in the moved-from state. If your move assignment operator is written to avoid moving from a moved-from object, you can disable this warning.
-Wnamespacesโ โจ Warns when a namespace definition is opened. Some coding rules ban namespaces, so this can enforce that. It's inactive inside system headers like the STL, so you can still use the STL. You can also use using directives and qualified names.-Wno-template-id-cdtor(C++ and Objective-C++ only) โ Disables the warning about using a simple-template-id as the declarator-id of a constructor or destructor. That became invalid in C++20 via DR 2237. Here's an example:
template<typename T> struct S {
S<T>(); // should be S();
~S<T>(); // should be ~S();
};
-Wtemplate-id-cdtor is enabled by default with -std=c++20, and it's also enabled by -Wc++20-compat.
-Wno-terminate(C++ and Objective-C++ only) โ ๐ฅ Disables the warning about a throw-expression that will immediately result in a call toterminate.-Wno-vexing-parse(C++ and Objective-C++ only) โ ๐ Warns about the most vexing parse ambiguity. This is when a declaration looks like a variable definition, but C++ requires it to be read as a function declaration. 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, like 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 tovoid. That kind of conversion function will never be called, so the warning is skipped.-Wvolatile(C++ and Objective-C++ only) โ ๐ Warns about deprecated uses of thevolatilequalifier. That covers:- postfix and prefix
++and--expressions ofvolatile-qualified types - simple assignments used for their value, where the left operand is a
volatile-qualified non-class type - compound assignments where the left operand is a
volatile-qualified non-class type volatile-qualified function return typesvolatile-qualified parameter types- structured bindings of a
volatile-qualified type
- postfix and prefix
This usage was deprecated in C++20. It's enabled by default with -std=c++20 ๐
-Wzero-as-null-pointer-constant(C++ and Objective-C++ only) โ Warns when a literal0gets used as a null pointer constant. This can help you move over tonullptrin C++11 โจ-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 it only warns about global allocation functions, but-Waligned-new=allalso warns about class member allocation functions.-Wno-placement-new,-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, the placement new expression below gets flagged, because it tries to construct an array of 64 integers in a buffer that's only 64 bytes large:
char buf [64];
new (buf) int[64];
This warning is enabled by default.
-Wplacement-new=1โ This is the default level 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 followingnewexpression isn't diagnosed at this level, even though the C++ standard says it has 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, you get all the same diagnostics as level 1, plus a diagnostic for placement new expressions that construct an object in the last member of a structure. That member has to be an array of a single element, and its size has to be smaller than the object being constructed. The previous example gets flagged here, but the following construct uses the flexible member array extension to avoid the warning at level 2:
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ ๐ Warns about catch handlers that don't catch via reference. With-Wcatch-value=1(or just-Wcatch-value), it warns about polymorphic class types caught by value. With-Wcatch-value=2, it warns about all class types caught by value. With-Wcatch-value=3, it warns about all types that aren't caught by reference.-Wcatch-valueis enabled by-Wall.-Wconditionally-supported(C++ and Objective-C++ only) โ Warns for conditionally-supported constructs (C++11[intro.defs]).-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 after in-class function definitions ๐ง-Wno-global-module(C++ and Objective-C++ only) โ Disables the diagnostic for when the global module fragment of a module unit doesn't consist only of preprocessor directives.-Wno-inaccessible-base(C++, Objective-C++ only) โ ๐ Controls warnings when a base class is inaccessible in a class derived from it because of ambiguity. This warning is enabled by default. The warning for ambiguous virtual bases is enabled by-Wextra. Here's an example:
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 theoffsetofmacro to a non-POD type. According to the 2014 ISO C++ standard, applyingoffsetofto a non-standard-layout type is undefined. In existing C++ implementations, though,offsetoftypically gives meaningful results. This flag is for people who know they're writing nonportable code and have deliberately chosen to ignore the warning about it. The restrictions onoffsetofmay be relaxed in a future version of the C++ standard.-Wsized-deallocation(C++ and Objective-C++ only) โ โญ Warns about a definition of an unsized deallocation function:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
without a definition of the corresponding sized deallocation function:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
or vice versa. It's enabled by -Wextra along with -fsized-deallocation.
-Wsuggest-final-types: okay bestie, this one warns you about types with virtual methods that would be cleaner marked with the C++11finalspecifier, or, if possible, declared in an anonymous namespace ๐ฆ. It lets GCC devirtualize polymorphic calls more aggressively โจ. It works best with link-time optimization, since LTO has a fuller picture of the class hierarchy graph ๐ฅ.-Wsuggest-final-methods: same energy, but for individual virtual methods ๐ . It warns when a method would be improved by thefinalspecifier, or when its type could go in an anonymous namespace or getfinal๐ธ. Again, LTO makes this more accurate because it knows more about the class hierarchy graph ๐ง. The move is to check the-Wsuggest-final-typessuggestions first, then rebuild with the new annotations ๐.-Wsuggest-override: flags virtual functions that override something without theoverridekeyword ๐.-Wno-conversion-null(C++ and Objective-C++ only): turns off warnings for conversions betweenNULLand non-pointer types ๐. Heads up,-Wconversion-nullis already on by default ๐.
๐ Options Controlling Objective-C and Objective-C++ Dialects ๐
NOTE: this manual doesn't teach you the Objective-C and Objective-C++ languages themselves ๐. What it does cover is the command-line options that only matter for those languages. You can still use most of the language-independent GNU compiler options too ๐.
Here's a quick example of compiling a file called some_class.m:
gcc -g -fgnu-runtime -O -c some_class.m
In that example, -fgnu-runtime is only meant for Objective-C and Objective-C++ ๐
. The other options work with any language GCC supports โจ.
Since Objective-C is basically an extension of C, Objective-C compiles can also use C front-end options, like -Wtraditional ๐ฆ. Objective-C++ compiles can use C++-specific options too, like -Wabi ๐ฅ.
Here's the list of options that are only for Objective-C and Objective-C++ programs ๐ซถ:
-fconstant-string-class=class-name: picks the class that gets instantiated for each literal string written as"@"...""๐. The default isNXConstantStringwith the GNU runtime andNSConstantStringwith the NeXT runtime ๐. On Darwin / macOS, if-fconstant-cfstringsis also present, it overrides this setting and makes"@"...""literals laid out as constant CoreFoundation strings ๐. Also,-fconstant-cfstringsis just an alias for the target-specific-mconstant-cfstringsโจ.-fgnu-runtime: generates object code that works with the standard GNU Objective-C runtime ๐. This is the default on most systems ๐.-fnext-runtime: generates output that works with the NeXT runtime ๐. It's the default on NeXT-based systems, including Darwin / macOS ๐ธ. The macro__NEXT_RUNTIME__is predefined if, and only if, you use this option ๐ง.-fno-nil-receivers: tells the compiler to assume every Objective-C message dispatch ([receiver message:arg]) in this translation unit has a receiver that isn'tnil๐. That lets the runtime use more efficient entry points ๐ฅ. It only works with the NeXT runtime and ABI version 0 or 1 ๐ซถ.-fobjc-abi-version=n: uses versionnof the Objective-C ABI for the selected runtime ๐ . Right now this is only supported for the NeXT runtime ๐ฆ. Version 0 is the traditional (32-bit) ABI with no support for properties or other Objective-C 2.0 additions ๐ฅบ. Version 1 is the traditional (32-bit) ABI with 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 targets and Version 2 on 64-bit targets ๐.-fobjc-call-cxx-cdtors: for each Objective-C class, it checks whether any instance variable is a C++ object with a non-trivial default constructor ๐. If one is, it synthesizes a special- (id) .cxx_constructinstance method that runs those constructors in order, then returnsself๐. It also checks for C++ objects with a non-trivial destructor, and if it finds any, synthesizes a- (void) .cxx_destructmethod that runs those destructors in reverse order ๐.
These generated - (id) .cxx_construct and - (void) .cxx_destruct methods only touch instance variables declared in the current Objective-C class, not the ones inherited from superclasses ๐ง. It's the Objective-C runtime's job to call all of these methods across an object's inheritance hierarchy ๐. The runtime calls - (id) .cxx_construct right after a new object instance is allocated, and calls - (void) .cxx_destruct right before it deallocates the instance ๐ซถ.
As of this writing, only the NeXT runtime on Mac OS X 10.4 and later can invoke - (id) .cxx_construct and - (void) .cxx_destruct ๐.
-fobjc-direct-dispatch: allows fast jumps to the message dispatcher โก. On Darwin, this happens through the comm page ๐ธ.-fobjc-exceptions: turns on syntax for structured exception handling in Objective-C, kind of like C++ ๐ฆ. You need this to use the Objective-C keywords@try,@throw,@catch,@finallyand@synchronized๐ . It works with both the GNU runtime and the NeXT runtime, but not 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 its own, different garbage collection setup that doesn't need special compiler flags ๐.-fobjc-nilcheck: for the NeXT runtime with version 2 of the ABI, checks for anilreceiver in method invocations before making the actual call ๐ซถ. This is the default, and you can turn it off with-fno-objc-nilcheck๐ . Class methods and super calls never get this nil check, no matter what this flag is set to ๐ . Right now this flag does nothing with the GNU runtime or an older version of the NeXT runtime ABI ๐ฅฒ.-fobjc-std=objc1: makes the compiler follow the language syntax of Objective-C 1.0, the one GCC 4.0 recognized ๐ฐ๏ธ. This only affects the Objective-C additions to C/C++, so it doesn't change conformance to C/C++ standards, which the separate C/C++ dialect flags control ๐. With this option on, any Objective-C or Objective-C++ syntax that GCC 4.0 doesn't recognize gets rejected ๐ . It's super handy if you need to be sure your Objective-C code compiles 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 pairs with the Fix-and-Continue debugging mode, where the object file can be recompiled and dynamically reloaded while the program is running, no restart needed ๐. For now, Fix-and-Continue only works with the NeXT runtime on Mac OS X 10.3 and later ๐.-fzero-link: when compiling for the NeXT runtime, the compiler normally swaps calls toobjc_getClass("...")(when the class name is known at compile time) for static class references that get initialized at load time, which makes things faster โก. Using-fzero-linkturns that off and keeps theobjc_getClass("...")calls ๐ซถ. That's useful in Zero-Link debugging mode, since it lets you modify individual class implementations while the program runs ๐ ๏ธ. The GNU runtime always keepsobjc_get_class("...")calls, no matter what command-line options you pass ๐.-fno-local-ivars: by default, Objective-C instance variables can be accessed like local variables inside the methods of the class they're declared in ๐. That can cause shadowing between instance variables and other variables with the same name, whether they're declared locally in a class method or globally ๐ญ. Using-fno-local-ivarsturns this behavior off and avoids those shadowing problems ๐ซถ.-fivar-visibility=[public|protected|private|package]: sets the default instance variable visibility to whichever option you pick ๐ฆ. Any instance variables declared outside the scope of an access modifier directive will default to that visibility ๐ .-gen-decls: dumps the interface declarations for all classes seen in the source file into a file namedsourcename.decl๐.-Wassign-intercept(Objective-C and Objective-C++ only): warns whenever the garbage collector intercepts an Objective-C assignment ๐๏ธ.-Wno-property-assign-default(Objective-C and Objective-C++ only): stops the warning for an Objective-C object property that doesn't have assign semantics specified ๐.-Wno-protocol(Objective-C and Objective-C++ only): if a class says it implements a protocol, GCC normally warns for every protocol method the class doesn't implement ๐ง. Even if a method is inherited from the superclass, that still counts as a warning by default ๐ค. With-Wno-protocol, inherited methods count as implemented, so no warning shows up for them ๐ซถ.-Wobjc-root-class(Objective-C and Objective-C++ only): warns if a class interface has no superclass ๐ณ. Most classes inherit fromNSObject(orObject), for example ๐. If you're declaring classes that are meant to be root classes, you can silence the warning by marking their interfaces with__attribute__((objc_root_class))๐.
๐ Objective-C Warnings ๐
-Wselector(Objective-C and Objective-C++ only) โ okay so this one warns you if the same selector shows up with different method types during compilation ๐. The check runs on the method list at the very end of compilation. It also checks every selector used in a@selector(...)expression that matches a method found during compilation ๐ง. Since all of this only happens at the end, these warnings won't show up if the final stage never gets reached, like when an error stops compilation early, or when-fsyntax-onlyis in use ๐ญ.-Wstrict-selector-match(Objective-C and Objective-C++ only) โ this one is giving strict ๐ . It warns when you send a message with a selector to a receiver of typeidorClass, and multiple methods for that selector have different argument and/or return types. By default this flag is off ๐, and when it's off the compiler skips these warnings if the only differences are 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 was never declared ๐ซถ. A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, whether explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection. This one checks right away when it spots a@selector(...)expression, while-Wselectorwaits until the final stage of compilation ๐ฆ. It also backs up the coding style rule that methods and selectors need to be declared before they're used. Main character energy ๐.-print-objc-runtime-infoโ generates a C header describing the largest structure that gets passed by value, if there is one ๐.
โจ Options to Control Diagnostic Messages Formatting โจ
Okay so traditionally, diagnostic messages were formatted without caring what the output device looked like (its width, and so on) ๐. These options 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 wide ๐. If n is zero, no line-wrapping happens, and each error message stays on a single line. This is the default for all front ends.
Note: this option also affects the display of the#errorand#warningpre-processor directives, and the deprecated function/type/variable attribute. It does not affect thepragma GCC warningandpragma GCC errorpragmas ๐ญ.
-fdiagnostics-plain-outputโ requests that diagnostic output look as plain as possible ๐งผ. This is handy when you're running dejagnu or other tools that parse diagnostics and need the output to stay stable over time.-fdiagnostics-plain-outputis currently equivalent to these options:
-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers
-fdiagnostics-color=never -fdiagnostics-urls=never
-fdiagnostics-path-format=separate-events
-fdiagnostics-text-art-charset=none
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 reporter to emit source location info once. So if a message is too long and has to be wrapped, 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 put the same source location info (as a prefix) on every physical line created when a too-long message gets broken up.-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ turns colors on in diagnostics ๐. WHEN can benever,always, orauto. The default depends on how the compiler was configured. It can be any of thoseWHENoptions, orneverif theGCC_COLORSenvironment variable isn't in the environment, andautootherwise.autoonly uses color when standard error is a terminal and you're not running in an emacs shell ๐ง. The forms-fdiagnostics-colorand-fno-diagnostics-colorare aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively.
The colors are set by the GCC_COLORS environment variable ๐
. Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings. SGR commands get interpreted by the terminal or terminal emulator. Check the section in your text terminal's documentation for the permitted values and what they mean as character attributes ๐. These substring values are integers written in decimal, and they can be stacked together with semicolons. Common ones you might stack include:
1for bold4for underline5for blink7for inverse39for default foreground color30to37for foreground colors90to97for 16-color mode foreground colors38;5;0to38;5;255for 88-color and 256-color mode foreground colors49for default background color40to47for background colors100to107for 16-color mode background colors48;5;0to48;5;255for 88-color and 256-color mode background colors
The default GCC_COLORS is this giant vibe ๐จ:
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
Here 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 supported capabilities:
error=โ SGR substring forerror:markers.warning=โ SGR substring forwarning:markers.note=โ SGR substring fornote:markers.path=โ SGR substring for coloring paths of control-flow events printed via-fdiagnostics-path-format=, like the identifiers of individual events and the lines showing interprocedural calls and returns.range1=โ SGR substring for the first additional range.range2=โ SGR substring for the second additional range.locus=โ SGR substring for location info, likefile:lineorfile:line:columnetc.quote=โ SGR substring for info printed within quotes.fnname=โ SGR substring for names of C++ functions.targs=โ SGR substring for C++ function template parameter bindings.fixit-insert=โ SGR substring for fix-it hints suggesting text to be inserted or replaced.fixit-delete=โ SGR substring for fix-it hints suggesting text to be deleted.diff-filename=โ SGR substring for filename headers within generated patches.diff-hunk=โ SGR substring for the starts of hunks within generated patches.diff-delete=โ SGR substring for deleted lines within generated patches.diff-insert=โ SGR substring for inserted lines within generated patches.type-diff=โ SGR substring for highlighting mismatching types within template arguments in the C++ frontend.valid=โ SGR substring for highlighting valid elements within text art diagrams.invalid=โ SGR substring for highlighting invalid elements within text art diagrams.-fdiagnostics-urls[=WHEN]โ uses escape sequences to embed URLs in diagnostics ๐. For example, when-fdiagnostics-show-optionshows the command-line option controlling a diagnostic, it embeds a URL pointing to the docs for that option.
WHEN can be never, always, or auto. auto only uses URL escape sequences when standard error is a terminal, and you're not running in an emacs shell or any graphical terminal known to be incompatible with this feature (see below) ๐
โโ๏ธ.
The default depends on how the compiler was configured, and it can be any of the WHEN options above. GCC can also be configured with 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 variable is present and non-empty in the compiler's environment, or never if neither is.
Even with -fdiagnostics-urls=always, the behavior still depends on those environment variables ๐:
- If
GCC_URLSis set to empty orno, URLs don't get embedded in diagnostics. - If it's set to
st, URLs use ST escape sequences. - If it's set to
bel, the default, URLs use BEL escape sequences. - Any other non-empty value enables the feature.
- If
GCC_URLSisn't set,TERM_URLSis used as a fallback.
Quick aside: ST is an ANSI escape sequence whose string terminator is ESC \. BEL is an ASCII character, CTRL-G, that usually sounds like a beep ๐.
At this point GCC also tries to detect a few terminals that don't implement the URL feature, and that have had bugs in some versions still in use, where URL escapes are likely to misbehave and print garbage on the screen ๐ญ. That list currently includes 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, every diagnostic emitted includes text showing the command-line option that directly controls it (if that option is known to the diagnostic machinery) ๐งพ. Using-fno-diagnostics-show-optionturns that off.-fno-diagnostics-show-caretโ bye, source line and caret ๐
By default, every diagnostic comes with the original source line and a caret ^ pointing at the column ๐
This option suppresses that info. If you pass -fmessage-length=n, the source line gets chopped to n characters โ๏ธ When the output goes to the terminal, the width is limited by the COLUMNS environment variable or, if that isn't set, the terminal width ๐ฅ๏ธ
-fno-diagnostics-show-labelsโ no more little labels on the code ๐ท๏ธ
By default, when printing source code (via -fdiagnostics-show-caret), diagnostics can label ranges of source code with useful info, like the types of expressions. It's giving detective energy ๐
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses those labels (in the example above, the vertical bars and the "char *" and "long int" text) ๐
-fno-diagnostics-show-cweโ hide the CWE tags ๐
Diagnostic messages can optionally have a CWE identifier attached (see https://cwe.mitre.org/index.html) โจ GCC itself only provides that metadata for some -fanalyzer diagnostics, and GCC plugins may also add it. By default, if the info is there, it gets printed with the diagnostic. This option suppresses the printing of this metadata ๐ซถ
-fno-diagnostics-show-rulesโ no rule tags either ๐
Diagnostic messages can optionally have rules attached to them, like rules from a coding standard or a specification. GCC itself doesn't do this for any of its diagnostics, but plugins can. By default, if that info is present, it gets printed with the diagnostic. This option suppresses the printing of this metadata ๐
-fno-diagnostics-show-line-numbersโ kill the left margin ๐ธ
By default, when printing source code (via -fdiagnostics-show-caret), a left margin is printed, showing line numbers. This option suppresses that left margin ๐ฆ
-fdiagnostics-minimum-margin-width=widthโ set the minimum margin width ๐
This option controls the minimum width of the left margin printed by -fdiagnostics-show-line-numbers. It defaults to 6 ๐
-fdiagnostics-parseable-fixitsโ fix-its that IDEs can actually read ๐ง
This one is for IDEs, bestie ๐ป Fix-it hints get emitted in a machine-parseable format. For each fix-it, a line gets printed after the relevant diagnostic, starting with the string fix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
The location is a half-open range, expressed as a count of bytes, starting at byte 1 for the initial column. In the example above, bytes 3 through 20 of line 45 of "test.c" get replaced with the given string ๐
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape backslash as "\\", tab as "\t", newline as "\n", double quotes as "\"", and non-printable characters as octal (for example, vertical tab as "\013") ๐ซง
An empty replacement string means the given range gets removed ๐๏ธ An empty range (for example "45:3-45:3") means the string gets inserted at the given position โ
-fdiagnostics-generate-patchโ get a diff, no cap ๐
This prints fix-it hints to stderr in unified diff format, after any diagnostics are printed. For example:
--- 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, following the same rules as for diagnostics (see -fdiagnostics-color) ๐
-fdiagnostics-show-template-treeโ C++ template types, but make it a tree ๐ณ
In the C++ frontend, when printing diagnostics about mismatching template types, such as:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
this flag enables printing a tree-like structure that shows the common and differing parts of the types, like this:
map<
[...],
vector<
[double != float]>>
The parts that differ are highlighted with color ("double" and "float" in this case) ๐จ
-fno-elide-typeโ stop the[...]shortcuts ๐ โโ๏ธ
By default, when the C++ frontend prints diagnostics about mismatching template types, the common parts of the types get printed as "[...]" to keep the error message short. For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying -fno-elide-type suppresses that behavior ๐
This flag also affects the output of the -fdiagnostics-show-template-tree flag โจ
-fdiagnostics-path-format=KINDโ how control-flow paths get shown ๐ค๏ธ
This specifies how to print paths of control-flow events for diagnostics that have one attached. KIND is none, separate-events, or inline-events, which is the default ๐
none means don't print diagnostic paths at all ๐ซ
separate-events means print a separate "note" diagnostic for each event within the diagnostic. For example:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-events means print the events "inline" within the source code. This view tries to consolidate the events into runs of sufficiently close events, printing them as labelled ranges within the source ๐ช
For example, the same events as above might be printed as:
'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 is shown by grouping the events by stack frame, and using indentation to show how stack frames are nested, pushed, and popped ๐ง
'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โ extra depth info for path debugging ๐ฌ
This option provides additional info when printing control-flow paths associated with a diagnostic ๐ฆ
If this option is provided, the stack depth will be printed for each run of events within -fdiagnostics-path-format=inline-events. If it's provided with -fdiagnostics-path-format=separate-events, then the stack depth and function declaration will be appended when printing each event ๐ช
This one is intended for GCC developers and plugin developers who are debugging diagnostics that report interprocedural control flow ๐ ๏ธ
-fno-show-columnโ no column numbers, please ๐
Do not print column numbers in diagnostics. This may be necessary if diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu ๐ค
-fdiagnostics-column-unit=UNITโ pick how columns get counted ๐ข
This selects the units for the column number. It affects traditional diagnostics (when -fno-show-column isn't in play), as well as JSON format diagnostics if requested ๐
The default UNIT, display, counts the number of display columns each character occupies. That can be bigger than the number of bytes needed to encode the character (like with tab characters), or smaller (like with multibyte characters). For example, the character "GREEK SMALL LETTER PI (U+03C0)" occupies one display column, but its UTF-8 encoding needs two bytes. The character "SLIGHTLY SMILING FACE (U+1F642)" occupies two display columns, and its UTF-8 encoding needs four bytes ๐
Setting UNIT to byte makes the column number count raw bytes in every case, which is how GCC did it before version 11.1.0. ๐งฎ Very old-school, bestie. ๐ฐ๏ธ
-fdiagnostics-column-origin=ORIGINโ picks which number the first column gets ๐ฆ
The default of 1 is the classic GCC vibe and matches the GNU style guide, so it's the safe pick โจ. Some utilities actually work better with an origin of 0, and any non-negative value is allowed, so you have options ๐
.
-fdiagnostics-escape-format=FORMATโ decides how weird bytes get displayed when GCC prints source lines ๐ธ
Normally GCC just prints the source bytes straight up. But some diagnostics are about encoding drama in the source file, like malformed UTF-8 or Unicode normalization issues ๐ญ. Those get flagged, so GCC escapes any byte that isn't printable ASCII when it prints the relevant source lines. This option controls how those bytes get escaped ๐ซถ.
The default FORMAT is unicode. It shows non-printable-ASCII Unicode characters as <U+XXXX>, and any bytes that don't form a validly UTF-8-encoded Unicode character show up as hex in the form <XX> ๐.
For example, say a source line has the string before, then the Unicode character U+03C0 ("GREEK SMALL LETTER PI", with UTF-8 encoding 0xCF 0x80), then the byte 0xBF (a stray UTF-8 trailing byte), then the string after. For that diagnostic, you'd get:
before<U+03C0><BF>after
Setting FORMAT to bytes shows every non-printable-ASCII byte as <XX>, so you can see the underlying encoding of non-ASCII Unicode characters ๐. For the example above, this gets printed:
before<CF><80><BF>after
-fdiagnostics-text-art-charset=CHARSETโ picks which characters get used for "text art" diagrams ๐จ
Some diagnostics include text art, which are visualizations made out of text and meant to be viewed in a monospaced font ๐ง. This option picks the characters used for those diagrams, if any. CHARSET can be none, ascii, unicode, or emoji.
none turns the diagrams off completely. ascii keeps everything pure ASCII, aka "ASCII art" ๐ค. unicode lets the diagrams use a conservative amount of Unicode drawing characters, like box-drawing characters ๐ฆ. emoji goes further and adds emoji to the mix too, like emitting U+26A0 WARNING SIGN followed by U+FE0F VARIATION SELECTOR-16 to select the emoji variant of the character โ ๏ธ.
The default is emoji, except when the environment variable LANG is set to C. In that case the default is ascii ๐.
-fdiagnostics-format=FORMATโ switches up how diagnostics get printed ๐
FORMAT can be text, sarif-stderr, sarif-file, json, json-stderr, or json-file. 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 โจ.
json is just a synonym for json-stderr. The json-stderr and json-file formats are identical, apart from where the JSON goes: the former emits to stderr, while json-file writes it to source.gcc.json ๐.
The emitted JSON is a top-level JSON array, and inside it are JSON objects representing the diagnostics ๐ซถ.
Diagnostics can have child diagnostics too. For example, this error and note:
misleading-indentation.c:15:3: warning: this 'if' clause does not
guard... [-Wmisleading-indentation]
15 | if (flag)
| ^~
misleading-indentation.c:17:5: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
17 | y = 2;
| ^
might be printed in JSON form (after formatting) like this:
[
{
"kind": "warning",
"locations": [
{
"caret": {
"display-column": 3,
"byte-column": 3,
"column": 3,
"file": "misleading-indentation.c",
"line": 15
},
"finish": {
"display-column": 4,
"byte-column": 4,
"column": 4,
"file": "misleading-indentation.c",
"line": 15
}
}
],
"message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"display-column": 5,
"byte-column": 5,
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"escape-source": false,
"message": "...this statement, but the latter is ..."
}
]
"escape-source": false,
"column-origin": 1,
}
]
Here the "note" is a child of the "warning" ๐ท.
A diagnostic has a "kind". If that's "warning", then there's an "option" key describing the command-line option controlling the warning ๐จ.
A diagnostic can contain zero or more locations. Each location has an optional "label" string and up to three positions within it: a "caret" position and optional "start" and "finish" positions. A position is described by a "file" name, a "line" number, and three numbers indicating a column position:
"display-column"counts display columns, accounting for tabs and multibyte characters."byte-column"counts raw bytes."column"is equal to one of the previous two, as dictated by the-fdiagnostics-column-unitoption.
All three columns are relative to the origin set by -fdiagnostics-column-origin. That's usually 1, but it can be set to 0 for compatibility with other utilities that number columns from 0 ๐ง. The column origin gets recorded in the JSON output under the "column-origin" tag. In the remaining examples below, the extra column number outputs have been left out for brevity ๐.
For example, this error:
bad-binary-ops.c:64:23: error: invalid operands to binary + (have 'S' {aka
'struct s'} and 'T' {aka 'struct t'})
64 | return callee_4a () + callee_4b ();
| ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| | |
| | T {aka struct t}
| S {aka struct s}
has three locations ๐. Its primary location is at the "+" token at column 23. It also has two secondary locations, describing the left and right-hand sides of the expression, and those have labels ๐
. It might be printed in JSON form as:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"escape-source": false,
"message": "invalid operands to binary + ..."
}
If a diagnostic contains fix-it hints, it has a "fixits" array made of half-open intervals, similar to the output of -fdiagnostics-parseable-fixits ๐ง. For example, this diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
might be printed in JSON form as:
{
"children": [],
"fixits": [
{
"next": {
"column": 21,
"file": "demo.c",
"line": 8
},
"start": {
"column": 15,
"file": "demo.c",
"line": 8
},
"string": "color"
}
],
"kind": "error",
"locations": [
{
"caret": {
"column": 15,
"file": "demo.c",
"line": 8
},
"finish": {
"column": 20,
"file": "demo.c",
"line": 8
}
}
],
"escape-source": false,
"message": "\u2018struct s\u2019 has no member named ..."
}
okay so the fix-it hint is basically saying "swap this chunk out for that." ๐
It replaces the text from "start" up to but not including "next" with the "string" value. Want to delete something? Give "string" an empty value ๐งน. Want to insert something? Make "start" equal "next" โจ. So cute, so precise, no notes.
If the diagnostic has a path of control-flow events attached to it, you'll see a "path" array full of event objects ๐ฆ. Each event has a "description" string, a "location" object, plus a "function" string and a "depth" number for tracking interprocedural paths. The "function" tells you which function is running at that event, and the "depth" is the stack depth relative to some baseline. Higher depth means more frames on the stack. Main character stack energy ๐ธ.
For example, the intraprocedural example shown for -fdiagnostics-path-format= might have this JSON for its path:
"path": [
{
"depth": 0,
"description": "when 'PyList_New' fails, returning NULL",
"function": "test",
"location": {
"column": 10,
"file": "test.c",
"line": 25
}
},
{
"depth": 0,
"description": "when 'i < count'",
"function": "test",
"location": {
"column": 3,
"file": "test.c",
"line": 27
}
},
{
"depth": 0,
"description": "when calling 'PyList_Append', passing NULL from (1) as argument 1",
"function": "test",
"location": {
"column": 5,
"file": "test.c",
"line": 29
}
}
]
Diagnostics also have a boolean attribute called escape-source ๐. It's a hint for whether non-ASCII bytes should be escaped when the pertinent lines of source code get printed. It's true for diagnostics involving source encoding issues, so that's your red flag, bestie ๐ฉ.
-fno-diagnostics-json-formattingโ okay so 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 so the hierarchy looks pretty and readable ๐. Use-fno-diagnostics-json-formattingto strip that whitespace out. It must be passed before the option it is to affect โ ๏ธ. This is meant for tools that don't expect newlines in the output, like the kind older GCC releases spit out ๐ง.
๐ Options to Request or Suppress Warnings ๐
Okay, warnings are diagnostic messages about stuff that isn't technically broken but is risky or hints that there might be a mistake lurking ๐.
The following language-independent options don't turn on specific warnings. Instead, they control what kinds of diagnostics GCC produces ๐ .
-fsyntax-onlyโ checks your code for syntax errors and then stops right there. No extra fuss ๐งผ.-fmax-errors=nโ caps the number of error messages atn, and once you hit that, GCC bails instead of trying to keep going through the source code ๐. Ifnis0(the default), there's no limit on how many error messages get printed. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option ๐.-wโ inhibits all warning messages. Silence is golden ๐คซ.-Werrorโ turns every warning into an error ๐ค.-Werror=โ turns one specific warning into an error. You append the warning's specifier, so for example-Werror=switchturns the warnings controlled by-Wswitchinto errors. This one also has a negative form, used to negate-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐ โโ๏ธ.-Wfatal-errorsโ makes the compiler abort compilation on the first error it runs into, instead of trying to keep going and printing more error messages ๐.
The warning message for each controllable warning includes the option that controls it ๐. You can then use that option with -Werror= and -Wno-error= like we just covered. (Printing of the option in the warning message can be disabled using the -fno-diagnostics-show-option flag.)
Note that specifying -Werror=foo automatically implies -Wfoo. However, -Wno-error=foo does not imply anything ๐ง.
You can request many specific warnings with options that begin with -W. For example, -Wimplicit requests warnings on implicit declarations ๐. Each of these specific warning options also has a negative form that begins with -Wno- to turn the warnings off. For example, -Wno-implicit. This manual only lists one of the two forms, whichever one is not 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-value. The combined effect of positive and negative forms is that more specific options have priority over less specific ones, independently of 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 emits a diagnostic stating that the option is not recognized ๐คทโโ๏ธ. However, if the -Wno- form is used, the behavior is slightly different: 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, and some instances of other warnings may not be issued at all unless optimization is enabled ๐ฅ. While optimization in general improves the efficacy of control and data flow sensitive warnings, in some cases it may also cause false positives ๐.
-Wpedantic,-pedanticโ issues all the warnings demanded by strict ISO C and ISO C++, and diagnoses all programs that use forbidden extensions, plus 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-stdoption 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) โจ. However, without this option, certain GNU extensions and traditional C and C++ features are supported as well. With this option, they get diagnosed, or rejected entirely 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, so application programs should avoid them ๐ซ.
Some warnings about non-conforming programs are controlled by options other than -Wpedantic. In many cases they're implied by -Wpedantic but can be disabled separately by their specific option, e.g. -Wpedantic -Wno-pointer-sign ๐ง.
Where the standard specified with -std represents a GNU extended dialect of C, such as gnu90 or gnu99, there is a corresponding base standard: the version of ISO C that the GNU extended dialect is based on. Warnings from -Wpedantic are given where the base standard requires them. (It doesn't make sense for those warnings to only be given for features outside the specified GNU C dialect, since by definition the GNU dialects of C include every feature the compiler supports with the given option, so there would be nothing to warn about ๐ค.)
-pedantic-errorsโ okay bestie, this one is STRICT ๐ It turns the stuff the base standard (see-Wpedantic) says must be diagnosed into errors. That covers some spots with undefined behavior at compile-time, plus some other spots that won't stop a program that's valid under the standard from compiling ๐ซถ
Heads up, this is not the same as -Werror=pedantic ๐ ngl that one is kinda pointless, since it only turns -Wpedantic diagnostics into errors. -pedantic-errors goes further and also hits the required diagnostics that are always on, or controlled by options other than -Wpedantic. Main character energy ๐
Want the required diagnostics that are warnings by default to become errors, but without turning on the -Wpedantic diagnostics? Then use -pedantic-errors -Wno-pedantic. Or -pedantic-errors -Wno-error=pedantic if you want those enabled but still just as warnings ๐ธ
Some required diagnostics are errors by default, but you can knock them down to warnings with -fpermissive or their own specific warning option, like -Wno-error=narrowing ๐ฆ
Some diagnostics for non-ISO practices are controlled by specific warning options other than -Wpedantic, but -pedantic-errors makes those into errors too. For instance:
-Wattributes (for standard attributes), -Wchanges-meaning (C++), -Wcomma-subscript (C++23 or later), -Wdeclaration-after-statement (C90 or earlier), -Welaborated-enum-base (C++11 or later), -Wimplicit-int (C99 or later), -Wimplicit-function-declaration (C99 or later), -Wincompatible-pointer-types, -Wint-conversion, -Wlong-long (C90 or earlier), -Wmain, -Wnarrowing (C++11 or later), -Wpointer-arith, -Wpointer-sign, -Wincompatible-pointer-types, -Wregister (C++17 or later), -Wvla (C90 or earlier), -Wwrite-strings (C++11 or later)
-fpermissiveโ the chill option ๐ง It downgrades some required diagnostics about nonconformant code from errors to warnings, so yes, it lets some nonconforming code compile. Some C++ diagnostics are controlled only by this flag, and 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)
-fpermissive is the default for the historic C language modes (-std=c89, -std=gnu89, -std=c90, -std=gnu90) ๐ฐ๏ธ
-Wallโ this one flags all the warnings about constructions some users find questionable, and that are easy to avoid (or easy to 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 the 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
Now, a fair warning ๐ some warning flags are not implied by -Wall. Some of them flag stuff users generally don't see as questionable, but which you might occasionally want to check for. Others flag constructions that are necessary or hard to avoid in some cases, with no simple way to rewrite the code to shush the warning. Some of them are turned on by -Wextra, but lots of them have to be enabled one by one ๐
-Wextraโ this turns on some extra warning flags that-Walldoesn't enable โจ (Fun fact: this option used to be called-W. The older name still works, but-Wextrais way more descriptive, so we stan ๐)
-Wabsolute-value (only for C/ObjC), -Walloc-size, -Wcalloc-transposed-args, -Wcast-function-type, -Wclobbered, -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-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, -Wunused-parameter (only with -Wunused or -Wall), -Wunused-but-set-parameter (only with -Wunused or -Wall)
-Wextra also prints warning messages for these cases too ๐
- A pointer is compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
- (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared
register. - (C++ only) Taking the address of a variable that has been declared
register. - (C++ only) A base class is not initialized in the copy constructor of a derived class.
-Wabi(C, Objective-C, C++ and Objective-C++ only) โ okay this one is about ABI drama ๐ง It warns about code affected by ABI changes, which includes code that might not be compatible with the vendor-neutral C++ ABI, as well as the psABI for the particular target.
Since G++ now defaults to updating the ABI with each major release, -Wabi normally only warns about C++ ABI compatibility problems if a check got added later in a release series for an ABI issue found after the initial release. It warns about more things if an older ABI version is selected with -fabi-version=n ๐
-Wabi can also take an explicit version number, to warn about C++ ABI compatibility with a particular -fabi-version level. For example, -Wabi=2 warns about changes relative to -fabi-version=2.
If an explicit version number is provided and -fabi-compat-version is not specified, the version number from this option gets used for compatibility aliases. If no explicit version number is given with this option, but -fabi-compat-version is specified, that version number is used for C++ ABI warnings ๐
Now, real talk no check is perfect ๐ฅบ Although an effort has been made to warn about all such cases, there are probably some that go unwarned, even though G++ is generating incompatible code. There may also be cases where warnings fire even though the generated code is actually compatible.
If you're worried that G++ code might not be binary compatible with code from other compilers, you should rewrite your code to avoid these warnings ๐ซถ
Known incompatibilities in -fabi-version=2 (which was the default from GCC 3.4 to 4.9) include:
- A template with a non-type template parameter of reference type was mangled incorrectly:
extern int N;
template <int &> struct S {};
void n (S<N>) {2}
This was fixed in -fabi-version=3.
- SIMD vector types declared using
__attribute ((vector_size))were mangled in a non-standard way that doesn't allow for overloading of functions taking vectors of different sizes.
The mangling was changed in -fabi-version=4.
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration got folded away.
These mangling issues were fixed in -fabi-version=5.
- Scoped enumerators passed as arguments to a variadic function get promoted like unscoped enumerators, causing
va_argto complain. On most targets this doesn't actually affect the parameter passing ABI, since there's no way to pass an argument smaller thanint. The ABI also changed the mangling of template argument packs,const_cast,static_cast, prefix increment/decrement, and a class scope function used as a template argument.
These issues were corrected in -fabi-version=6.
- Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t.
These issues were corrected in -fabi-version=7. ๐
- When mangling a function type that has function-cv-qualifiers, the un-qualified function type was wrongly counted as a substitution candidate ๐ญ. This was fixed in
-fabi-version=8, the default for GCC 5.1 ๐ . decltype(nullptr)had an alignment of 1, which led to unaligned accesses ๐. It didn't change the ABI of a function with anullptr_tparameter, since parameters already get a minimum alignment ๐ซถ. This was fixed in-fabi-version=9, the default for GCC 5.2 ๐ฅ.- Target-specific attributes that change what a type is, like ia32 calling conventions on a function type (
stdcall,regparm, etc.), weren't reflected in the mangled name ๐. That caused name collisions whenever function pointers were used as template arguments. This was fixed in-fabi-version=10, the default for GCC 6.1 ๐. - For SysV/x86-64, unions with
long doublemembers are passed in memory, as the psABI specifies ๐ง. Before GCC 4.4 that wasn't the case. For example:
union U {
long double ld;
int i;
};
union U is now always passed in memory ๐ฆ.
-Wno-changes-meaning(C++ and Objective-C++ only) โ C++ wants unqualified uses of a name inside a class to mean the same thing across the whole class scope, so using a name first and declaring it later 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. Both diagnostics can be turned off with -Wno-changes-meaning. If you'd rather the error be a warning, use -Wno-error=changes-meaning or -fpermissive โจ. Both diagnostics are also suppressed by -fms-extensions ๐ธ.
-Wchar-subscriptsโ warns if an array subscript has typechar๐. This is a super common mistake, since people forget thatcharis signed on some machines. This warning is enabled by-Wall๐.-Wno-coverage-mismatchโ warns if feedback profiles don't match when you use-fprofile-use๐. If a source file changes between-fprofile-generateand-fprofile-use, the profile feedback files can stop matching the source, and GCC can't use the feedback info. By default this warning is on and treated as an error. Use-Wno-coverage-mismatchto silence the warning, or-Wno-error=coverage-mismatchto silence the error.
Turning off the error can lead to poorly optimized code. It's only really useful for very minor changes, like bug fixes in an existing code-base. 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 is given up when the conditional has more terms than there are bits in agcov_type_unsigned. This warning is enabled by default ๐.-Wno-coverage-invalid-line-numberโ warns if a function ends before it begins because of invalid linenum macros ๐คฏ. The warning is only emitted when--coverageis enabled.
By default this warning is enabled and treated as an error. -Wno-coverage-invalid-line-number disables the warning, and -Wno-error=coverage-invalid-line-number disables the error ๐ซ .
-Wno-cpp(C, Objective-C, C++, Objective-C++ and Fortran only) โ silences the warnings that#warningdirectives spit out ๐คซ.-Wdouble-promotion(C, C++, Objective-C and Objective-C++ only) โ warns when afloatvalue gets implicitly promoted todouble๐. CPUs with a 32-bit single-precision floating-point unit dofloatin hardware but emulatedoublein software. So doing math withdoubleon those machines is way more expensive because of the emulation overhead ๐ข.
It's super easy to accidentally do math in double, because floating-point literals are implicitly double ๐ฉ. For example:
float area(float radius)
{
return 3.14159 * radius * radius;
}
The compiler does the whole 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 ๐ง. This warning is enabled by-Wall๐ .-Wformat,-Wformat=nโ checks calls toprintfandscanf(and friends) ๐จ๏ธ. It makes sure the arguments match the types the format string expects, and that the conversions in the format string actually make sense ๐ง. This covers standard functions plus anything else marked with format attributes, in theprintf,scanf,strftimeandstrfmonfamilies (strfmonis an X/Open extension and isn't in the C standard), or other target-specific families ๐ท. Which functions get checked without a format attribute depends on the standard version you picked. Those checks are turned off by-ffreestandingor-fno-builtin๐ซ.
The formats are checked against the features in GNU libc version 2.2 โจ. That includes all of ISO C90 and C99, plus stuff from the Single Unix Specification and some BSD and GNU extensions. Other library implementations might not support all of these, and GCC won't warn about features that go beyond a particular library's limits ๐ซถ. But if you use -Wpedantic together with -Wformat, you'll get warnings about format features that aren't in the standard version you selected. That doesn't apply to 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 ๐. Some parts of this level of checking 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 it's the same as-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k๐.
-Wno-format-contains-nulโ if-Wformatis on, don't warn about format strings that contain NUL bytes ๐ โโ๏ธ.-Wno-format-extra-argsโ if-Wformatis on, don't warn about extra arguments passed to aprintforscanfformat function ๐ฆ. The C standard says those extra arguments are just ignored ๐ซ .
If the unused arguments sit between used arguments that are given with $ operand number specifications, warnings still come out by default. That's because the compiler can't know what type to pass to va_arg to skip the unused ones ๐ตโ๐ซ. For scanf formats, though, this option does suppress the warning when all the unused arguments are pointers. The Single Unix Specification says those unused pointer arguments are allowed ๐ง.
-Wformat-overflow,-Wformat-overflow=levelโ warns about calls to formatted output functions likesprintfandvsprintfthat might overflow the destination buffer ๐ฅ. If the exact number of bytes a format directive writes can't be figured out at compile time, GCC estimates it with heuristics. Those 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 ๐งธ. It only warns about calls that will most likely overflow the buffer. At this level, numeric arguments with unknown values are assumed to be one, and strings of unknown length are assumed to be empty ๐ฑ. Numeric arguments known to be bounded to a subrange of their type, or string arguments whose output is bounded by the directive's precision or by a finite set of string literals, are assumed to take whatever value in their range produces the most bytes of output ๐. For example, this call tosprintfgets flagged. Even with bothaandbequal to zero, the terminating NUL character ('\0') that the function appends to the destination buffer gets written past its end ๐ฑ. Making the buffer one byte bigger is enough to dodge the warning, though it might not be enough to actually avoid the overflow ๐.
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
-Wformat-overflow=2โ level 2 warns about calls that might overflow the destination buffer if an argument is long enough or large enough in magnitude ๐ฃ. At level 2, unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise ๐ข. Unknown string arguments whose length can't be assumed bounded, either by the directive's precision, by a finite set of string literals they might evaluate to, or by the character array they may point to, are assumed to be 1 character long ๐งฉ.
Okay so we're picking up right where that sprintf example left off ๐ญ๐ At level 2, that same call gets flagged again, but this time it's because if a is equal to a 32-bit INT_MIN, the first %i directive will write some of its digits past the end of the destination buffer ๐. To make the call safe no matter what the two variables hold, the destination buffer has to be at least 34 bytes. GCC even drops the minimum buffer size into an informational note right after the warning, so you don't have to do the math yourself ๐
If resizing the buffer isn't your vibe, you can limit the range of the formatted values instead โจ You can cap the maximum length of string arguments by putting a precision in the format directive. And if you can assume numeric arguments are bounded by less than the precision of their type, picking an appropriate length modifier for the format specifier will shrink the buffer you need. For example, if a and b in the example above are guaranteed to be within the precision of the short int type, then either using the %hi format directive or casting the argument to short drops the maximum required size of the buffer 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โ Okay, so if-Wformatis on, this tells GCC to chill and not warn about zero-length formats ๐ธ The C standard says zero-length formats are totally allowed, so no drama needed.-Wformat-nonliteralโ If-Wformatis on, GCC will also warn when the format string isn't a string literal, since it can't check that kind of format ๐. The exception is when the format function takes its format arguments as ava_list.-Wformat-securityโ If-Wformatis on, this one also flags format function calls that could be a security problem ๐ฅ. Right now it warns aboutprintfandscanfcalls where the format string isn't a string literal and there are no format arguments, likeprintf (foo);. That's a potential security hole if the format string came from untrusted input and contains%n. (This is currently a subset of what-Wformat-nonliteralwarns about, but future warnings may be added to-Wformat-securitythat aren't included in-Wformat-nonliteral.)-Wformat-signednessโ If-Wformatis on, this warns when the format string wants an unsigned argument but you pass a signed one, and vice versa ๐-Wformat-truncation,-Wformat-truncation=levelโ Okay this one is giving output truncation drama ๐ It warns about calls to formatted input/output functions likesnprintfandvsnprintfthat might cut off the output. When 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 argument and on optimization. Turning on optimization 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-truncationor-Wformat-truncation=1โ Level 1 is enabled by-Wformatand is the conservative option ๐ง. 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 is spicier and also warns about bounded functions whose return value is used, if they might truncate given an argument of big enough length or magnitude ๐ฅ.
-Wformat-y2kโ If-Wformatis on, 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 ๐ซ.-Wnonnullis included in-Walland-Wformat, and you can turn it off with-Wno-nonnull.-Wnonnull-compareโ Warns when you compare an argument marked with thenonnullfunction attribute against null inside the function ๐. It's included in-Wall, and you can disable it with-Wno-nonnull-compare.-Wnull-dereferenceโ Warns if the compiler finds paths that trigger erroneous or undefined behavior from dereferencing a null pointer ๐. This only works when-fdelete-null-pointer-checksis active, which optimizations enable on most targets. How precise the warnings are depends on the optimization options you use.-Wnrvo(C++ and Objective-C++ only) โ Warns if the compiler doesn't elide the copy from a local variable to the return value, even though[class.copy.elision]allows it ๐. This is commonly called the Named Return Value Optimization. In the example below, the compiler can't elide copies from bothv1andv2, so it doesn't elide either one.
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 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 ๐ช. This option can only be used together with-Wuninitialized.
In the following snippet, GCC warns about i being uninitialized only when -Winit-self is specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++.
-Wno-implicit-int(C and Objective-C only) โ This controls warnings when a declaration doesn't specify a type ๐ค. It's enabled by default as an error in C99 and later C dialects, and also by-Wall. You can downgrade the error to a warning with-fpermissive(along with certain other errors), or for this error alone with-Wno-error=implicit-int.
This warning gets upgraded to an error by -pedantic-errors.
-Wno-implicit-function-declaration(C and Objective-C only) โ This controls warnings when a function is used before it's declared ๐ฃ. It's enabled by default as an error in C99 and later C dialects, and also by-Wall. You can downgrade the error to a warning with-fpermissive(along with certain other errors), or for this error alone with-Wno-error=implicit-function-declaration.
This warning gets upgraded to an error by -pedantic-errors.
-Wimplicit(C and Objective-C only) โ Same as-Wimplicit-intand-Wimplicit-function-declarationcombined ๐งฉ. This warning is enabled by-Wall.-Whardenedโ Warns when-fhardeneddidn't enable an option from its set (see-fhardenedfor the full list) ๐ก๏ธ. For instance, if you use-fhardenedand-fstack-protectorat the same time on the command line,-Whardenedwarns because-fstack-protector-strongisn't enabled by-fhardened.
This warning is enabled by default and 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 a switch case falls through ๐. For example:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
This warning doesn't fire when the last statement of a case can't fall through, like when there's a return statement or a call to a function declared with the noreturn attribute ๐. -Wimplicit-fallthrough= also takes control flow statements, like ifs, into account, and only warns when it's actually appropriate. For example:
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a fallthrough is exactly what you want, so GCC gives you an attribute, __attribute__ ((fallthrough)), to use along with a null statement to suppress the warning that would otherwise show up ๐ง:
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 has a standard way to suppress -Wimplicit-fallthrough using [[fallthrough]]; instead of the GNU attribute โจ. In C++11 or C++14, you can use [[gnu::fallthrough]];, which is a GNU extension. Instead of these attributes, you can also add a fallthrough comment to silence the warning ๐ฌ. The whole body of the C or C++ style comment has to match the regular expressions listed below. The option argument n decides what kinds of comments are accepted:
-Wimplicit-fallthrough=0disables the warning altogether ๐ซ.-Wimplicit-fallthrough=1matches the".*"regular expression, so any comment counts as a fallthrough comment ๐ซถ.-Wimplicit-fallthrough=2case insensitively matches the".*falls?[ \t-]*thr(ough|u).*"regular expression ๐ธ.-Wimplicit-fallthrough=3case sensitively matches one of the following regular expressions:
okay so -Wimplicit-fallthrough=3 is the pickiest level ๐
the comment has to match one of these patterns, and GCC checks them exactly like this ๐
*<"-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=4 is a bit more chill ๐ธ it matches case sensitively against this shorter list:
*<"-fallthrough">
*<"@fallthrough@">
*<"lint -fallthrough[ \t]*">
*<"[ \t]*FALLTHR(OUGH|U)[ \t]*">
-Wimplicit-fallthrough=5 doesn't recognize any comments as fallthrough comments at all ๐ only attributes can turn the warning off, so no comment-based escape hatch for you, bestie ๐
The comment also needs to sit right before case or default, with only whitespace and other comments in between, or before a user label that comes right before a case or default label โจ like this:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is turned on by -Wextra ๐ฅ
๐ -Wno-if-not-aligned (C, C++, Objective-C and Objective-C++ only)
This one controls whether warnings triggered by the warn_if_not_aligned attribute get issued ๐ฆ they're on by default, so you have to actively turn them off with -Wno-if-not-aligned if you don't want them.
๐ -Wignored-qualifiers (C and C++ only)
Warns if a function's return type has a type qualifier like const โจ in ISO C that qualifier does nothing, since the returned value isn't an lvalue, so it's giving "pointless" ๐ญ For C++, the warning only shows up for scalar types or void. ISO C doesn't allow qualified void return types on function definitions, so those always get a warning even without this option, no cap.
This warning is also turned on by -Wextra.
๐ -Wno-ignored-attributes (C and C++ only)
This controls warnings for when an attribute gets ignored ๐ it's different from -Wattributes, which is about attributes being unknown or used in the wrong place. This one fires whenever the compiler decides to drop an attribute. It's on by default.
๐ -Wmain
Warns if the type of main looks suspicious ๐ main should be a function with external linkage that returns int and takes either zero arguments, two, or three arguments of the right types. This is on by default in C++, and it's turned on by either -Wall or -Wpedantic.
โ ๏ธ -pedantic-errors upgrades this warning into an error, so it stops being just a warning, bestie ๐ฑ
๐ง -Wmisleading-indentation (C and C++ only)
Warns when the indentation doesn't match the real block structure ๐ specifically, it fires for if, else, while, and for clauses that have a guarded statement without braces, followed by an unguarded statement at the same indentation level. Gotcha energy ๐
In this example, bar is misleadingly indented like it's guarded by the if, but it isn't:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
If you mix tabs and spaces, the warning uses -ftabstop= to figure out whether the statements actually line up, and it defaults to 8 ๐
It won't warn about code with multiline preprocessor logic like this one ๐ธ
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
It also skips anything after a #line directive ๐ง that usually means the code was autogenerated, and nobody can assume anything about the file layout that the directive points to.
This warning is turned on by -Wall in C and C++ โจ
๐ฆ -Wmissing-attributes
Warns when a function declaration is missing one or more attributes that a related function is declared with ๐ this matters because leaving them out can hurt correctness or efficiency of the generated code. For example, it fires for declarations of aliases that use attributes to set less restrictive requirements than their targets. That usually means a potential optimization opportunity ๐
The option -Wattribute-alias=2 is kind of the opposite ๐ it warns when an alias is more restrictive than its target, which could lead to incorrect code generation. The attributes considered here include "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc", "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull", and "returns_twice".
In C++, the warning fires when an explicit specialization of a primary template is declared without an attribute that the primary template has. The attributes that count are "alloc_align", "alloc_size", "assume_aligned", "format", "format_arg", "malloc", or "nonnull". The attributes "deprecated", "error", and "warning" suppress the warning..
You can use the "copy" attribute to apply the same set of attributes to a declaration as another declaration has, without listing them all out ๐ซถ it works on declarations of functions, variables, or types.
-Wmissing-attributes is turned on by -Wall ๐ฅ
For example, the primary function template below uses both "malloc" and "alloc_size", so the explicit specialization gets flagged because it's missing one of them ๐
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
๐ธ -Wmissing-braces
Warns if an aggregate or union initializer isn't fully bracketed ๐
in this example, the initializer for a isn't fully bracketed, but the one for b is.
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is turned on by -Wall โจ
๐ -Wmissing-include-dirs (C, C++, Objective-C, Objective-C++ and Fortran only)
Warns if a user-supplied include directory doesn't exist ๐ this option is disabled by default for C, C++, Objective-C, and Objective-C++. For Fortran, it's partially on by default, but only for -I and -J ๐
๐ซง -Wno-missing-profile
This controls warnings about missing feedback profiles when you use -fprofile-use ๐ it catches cases where a new function or a new file got added between compiling with -fprofile-generate and -fprofile-use, without regenerating the profiles. In those cases, the profile feedback data files don't have any info for the new function or file, bestie.
Also, if profile count data (.gcda) files get removed, GCC can't use any profile feedback information at all ๐ญ in every one of these cases, you get warnings reminding you that a profile generation step is due. Ignoring them can give you poorly optimized code, so be careful ๐
-Wno-missing-profile turns the warning off, but it's not recommended ๐ซ only do it when the missing profile data is actually justified.
๐ -Wmismatched-dealloc
Warns about calls to deallocation functions with pointer arguments that came from allocation functions the deallocator doesn't match ๐ง you can pair up matching allocators and deallocators with the malloc attribute. Unless -fno-builtin turns it off, the standard functions "calloc", "malloc", "realloc", and "free", plus the C++ "operator new" and "operator delete" forms, are implicitly matched up already โจ
In this example, mydealloc is the deallocator for pointers returned by myalloc ๐
void mydealloc (void*);
__attribute__ ((malloc (mydealloc, 1))) void*
myalloc (size_t);
void f (void)
{
void *p = myalloc (32);
// ...use p...
free (p); // warning: not a matching deallocator for myalloc
mydealloc (p); // ok
}
In C++, the related option -Wmismatched-new-delete catches mismatches involving either "operator new" or "operator delete" ๐
-Wmismatched-dealloc is included in -Wall ๐
๐ -Wmultistatement-macros
Warns about unsafe multi-statement macros that look guarded by a clause like if, else, for, switch, or while ๐ฌ the problem is that after the macro expands, only the first statement is actually guarded.
For example:
#define DOIT x++; y++
if (c)
DOIT;
This increments y unconditionally, not just when c holds ๐ It can usually be fixed by wrapping the macro in a do-while loop:
#define DOIT do { x++; y++; } while (0)
if (c)
DOIT;
This warning is turned on by -Wall in C and C++ ๐ซถ
๐ง -Wparentheses
Warns when parentheses are left out in certain spots ๐ like when there's an assignment where a truth value is expected, or when nested operators have precedence that people often mix up.
It also warns if a comparison like x<=y<=z shows up ๐ that's equivalent to (x<=y ? 1 : 0) <= z, which is a different reading from ordinary math notation, so it's giving confusing ๐ญ
It also warns about dangerous uses of the GNU extension to ?: with the middle operand omitted ๐ when the condition 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 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 turned on by -Wall ๐
-Wno-self-move(C++ and Objective-C++ only) โ okay bestie ๐ซถ this one screams when youstd::movea value into itself. That usually does absolutely nothing, so it's lowkey a red flag ๐ฉ. Here's the sus code:
struct T {
...
};
void fn()
{
T t;
...
t = std::move (t);
}
This warning is enabled by -Wall ๐
-Wsequence-pointโ ohhh this one is the drama queen ๐ It warns about code that might have undefined semantics because it breaks the sequence point rules in the C and C++ standards. Sequence points are like little checkpoints where the program has finished certain stuff. They happen after a full expression finishes (one that isn't part of a bigger expression), after the first operand of&&,||,? :or,(comma) operator gets evaluated, before a function is called (but after its arguments and the expression naming the called function are evaluated), and in a few other spots. Outside those checkpoints, the order that subexpressions get evaluated is not specified ๐คทโโ๏ธ The rules only give a partial order, not a total one. For example, if two functions get called in one expression with no sequence point between them, the order they run in is not specified. The standards committee did rule that function calls don't overlap though ๐ธ
It's also not specified when, between sequence points, changes to object values take effect. Programs that depend on that have undefined behavior. The standards basically say that between two sequence points, an object can only have its stored value changed once, and the old value can only be read to figure out the new value being stored.
๐ If a program breaks these rules, the results on any particular implementation are entirely unpredictable. Not a vibe.
Examples of undefined-behavior code are a = a++;, a[n] = b[n++] and a[i++] = i;. Some more complicated cases aren't diagnosed by this option, and it may give an occasional false positive, but overall it's been found pretty effective at catching this sort of problem ๐
C++17 is going to define the order of evaluation of operands in more cases. In particular, it requires the right-hand side of an assignment to be evaluated before the left-hand side, so the examples above are no longer undefined. But this option will still warn about them, to help people avoid writing code that's undefined in C and earlier revisions of C++ ๐ง
The standard is worded confusingly, so there's some debate over the precise meaning of the sequence point rules in subtle cases. Links to discussions of the problem, including proposed formal definitions, can be found on the GCC readings page at <https://gcc.gnu.org/readings.html> ๐
This warning is enabled by -Wall for C and C++ ๐
-Wno-return-local-addrโ bestie, this one turns off the warning for returning a pointer (or a reference, in C++) to a variable that goes out of scope once the function returns ๐ฆ-Wreturn-mismatchโ this one checks yourreturnstatements ๐ง It warns aboutreturnstatements without an expression in functions that don't returnvoid. It also warns about areturnwith an expression in avoidfunction, unless the expression's type is alsovoid. As a GNU extension, that last case is accepted without a warning unless-Wpedanticis used.
โ ๏ธ Trying to use the return value of a non-voidfunction other thanmainthat flows off the end by reaching the closing curly brace that ends the function is undefined. Yikes ๐ญ
This warning is specific to C and enabled by default. In C99 and later dialects it's treated as an error ๐ If you want to downgrade it to a warning, you can use -fpermissive (which also downgrades other warnings), or just this one with -Wno-error=return-mismatch ๐
-Wreturn-typeโ warns whenever a function is defined with a return type that defaults toint(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 anyreturnstatement at all ๐
โ ๏ธ Trying to use the return value of a non-voidfunction other thanmainthat flows off the end by reaching the closing curly brace that ends the function is undefined.
Unlike in C, in C++, flowing off the end of a non-void function other than main results in undefined behavior even when the value of the function isn't used. Scary stuff ๐ฑ
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 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 is enabled by default in C99 and C++11 modes (and newer). This level does not warn about left-shifting1into 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 ๐ง-Wshift-overflow=2โ this warning level also warns about left-shifting1into the sign bit, unless C++14 mode (or newer) is active ๐ฅ
-Wswitchโ warns whenever aswitchstatement has an index of enumerated type and lacks acasefor one or more of the named codes of that enumeration. (Having adefaultlabel prevents this warning.)caselabels outside the enumeration range also trigger warnings when this option is used, even if there's adefaultlabel. This warning is enabled by-Wall๐-Wswitch-defaultโ warns whenever aswitchstatement doesn't have adefaultcase ๐ธ-Wswitch-enumโ the same vibe as-Wswitch, withcaselabels outside the enumeration range also provoking warnings. The only real difference is that this one warns about an omitted enumeration code even when there's adefaultlabel ๐-Wno-switch-boolโ don't warn when aswitchstatement 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 thanbool. For example:
switch ((int) (a == 4))
{
...
}
This warning is enabled by default for C and C++ programs ๐ฆ
-Wno-switch-outside-rangeโ controls warnings when aswitchcasehas a value outside its respective type range. This warning is enabled by default for C and C++ programs ๐-Wno-switch-unreachableโ don't warn when aswitchstatement contains statements between the controlling expression and the firstcaselabel, since those will never be executed. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
-Wswitch-unreachable does not warn if the statement between the controlling expression and the first case label is just a declaration:
switch (cond)
{
int i;
...
case 5:
i = 5;
...
}
This warning is enabled by default for C and C++ programs ๐
-Wsync-nand(C and C++ only) โ warns when the__sync_fetch_and_nandand__sync_nand_and_fetchbuilt-in functions are used. These functions changed semantics in GCC 4.4 โญ-Wtrivial-auto-var-initโ warns when-ftrivial-auto-var-initcan't initialize an automatic variable. A common situation is an automatic variable declared between the controlling expression and the firstcaselabel of aswitchstatement ๐ง
-Wunused-but-set-parameterโ warns whenever a function parameter is assigned to but otherwise unused (aside from its declaration). To suppress this warning, use theunusedattribute. This warning is also enabled by-Wunusedtogether with-Wextra๐ท-Wunused-but-set-variableโ warns whenever a local variable is assigned to but otherwise unused (aside from its declaration). This warning is enabled by-Wall. To suppress it, use theunusedattribute. It's also enabled by-Wunused, which is enabled by-Wall๐-Wunused-functionโ warns whenever astaticfunction is declared but not defined, or when a non-inlinestaticfunction is unused. This warning is enabled by-Wall๐ธ-Wunused-labelโ warns whenever a label is declared but not used. This warning is enabled by-Wall. To suppress it, use theunusedattribute ๐-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ warns when atypedeflocally defined in a function is not used. This warning is enabled by-Wall๐ซถ-Wunused-parameterโ warns whenever a function parameter is unused aside from its declaration. This option is not enabled by-Wunusedunless-Wextrais also specified. To suppress this warning, use theunusedattribute โจ-Wno-unused-resultโ don't warn if a caller of a function marked with the attributewarn_unused_resultdoesn't use its return value. The default is-Wunused-result๐-Wunused-variableโ okay bestie, this one sounds the alarm whenever a local or static variable is just sitting there doing nothing except its declaration ๐. This option implies-Wunused-const-variable=1for C, but not for C++ ๐ โโ๏ธ. It's enabled by-Wallโจ. To shush this warning, slap the"unused"attribute on it ๐ .-Wunused-const-variable,-Wunused-const-variable=nโ the sequel ๐ฌ. This warns whenever a constant static variable is unused aside from its declaration ๐ธ. To suppress it, use the"unused"attribute ๐ซถ.-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 ๐ง. It's enabled by either-Wunused-variableor-Wunusedfor C, but not for C++. In C this declares variable storage, but in C++ it isn't an error, since const variables take the place of"#define"s ๐คทโโ๏ธ.-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 explicitly request this level 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's explicitly not used ๐ง. To suppress it, cast the unused expression to"void"๐ซถ. It catches an expression-statement, or the left-hand side of a comma expression, that contains no side effects. For example, an expression such asx[i,j]causes a warning, whilex[(void)i,j]does not ๐. This warning is enabled by-Wall๐.-Wunusedโ the combo meal ๐. It's all the above-Wunusedoptions combined, except the ones documented as needing to be specified explicitly ๐. If you want 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,-Wuse-after-free=nโ only for C, Objective-C, C++ and Objective-C++ ๐ฆ. This one warns about uses of pointers to dynamically allocated objects that have been made indeterminate by a call to a deallocation function ๐. It's 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 diagnose unconditional uses of pointers made indeterminate by a deallocation call or a successful call to"realloc", regardless of whether that call actually resulted in a reallocation of memory ๐ง . This includes double-"free"calls, as well as uses in arithmetic and relational expressions. Although undefined, uses of indeterminate pointers in equality (or inequality) expressions 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 to"free"in the following function is 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 to"realloc"as an attempt to figure out whether the call relocated the object to a different address ๐ค. They get their own level so legacy code can gradually transition 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 obviates needing to adjust the stored pointers after reallocation โจ. -Wuse-after-free=2 is included in -Wall ๐
.
-Wuseless-castโ only for C, Objective-C, C++ and Objective-C++ ๐. It warns when an expression is cast to its own type. It does not occur when a class object is converted to a non-reference type, because that's a way to create a temporary ๐ง:
struct S { };
void g (S&&);
void f (S&& arg)
{
g (S(arg)); // make arg prvalue so that it can bind to S&&
}
-Wuninitializedโ warns if an object with automatic or allocated storage duration is used without having been initialized ๐ญ. In C++, it also warns if a non-static reference or non-static"const"member appears in a class without constructors ๐ซ .
In addition, passing a pointer (or in C++, a reference) to an uninitialized object into a "const"-qualified argument of a built-in function known to read the object is also diagnosed by this warning ๐. (-Wmaybe-uninitialized is issued for ordinary functions ๐.)
If you want to warn about code that uses the uninitialized value of the variable in its own initializer, use the -Winit-self option ๐ช.
These warnings occur 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 version of GCC you're using ๐ฒ.
Note that there may be no warning about a variable that's only used to compute a value that itself is never used, because such computations may be deleted by data flow analysis before the warnings are printed ๐๏ธ.
In C++, this warning also warns about 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__atomicbuiltins,__syncbuiltins, and the C11 atomic generic functions with a memory consistency argument that is either invalid for the operation or outside the range of values of the"memory_order"enumeration ๐งต. For example, since the"__atomic_store"and"__atomic_store_n"built-ins are only defined for the relaxed, release, and sequentially consistent memory orders, the following code is 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 that is initialized, but some other paths where it isn't, the compiler emits a warning if it can't prove the uninitialized paths aren't executed at run time ๐. In addition, passing a pointer (or in C++, a reference) to an uninitialized object into a"const"-qualified function argument is also diagnosed by this warning ๐. (-Wuninitializedis issued for built-in functions known to read the object.) Annotating the function with attribute"access (none)"indicates that the argument isn't used to access the object, and avoids the warning ๐ซถ.
These warnings are only possible in optimizing compilation, because otherwise GCC doesn't keep track of the state of variables ๐ง .
These warnings are made optional because GCC may not be able to determine when the code is correct in spite of appearing to have an error ๐. Here is one example of how this can happen:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If the value of "y" is always 1, 2 or 3, then "x" is always initialized, but GCC doesn't know this ๐คทโโ๏ธ. To suppress the warning, you need to provide a default case with assert(0) or similar code ๐
.
This option also warns when a non-volatile automatic variable might be changed by a call to "longjmp". The compiler sees only the calls to "setjmp". It cannot know where "longjmp" will be called; in fact, a signal handler could call it at any point in the code ๐ฑ. As a result, you may get a warning even when there is in fact no problem, because "longjmp" cannot actually be called at the place that would cause a problem ๐.
Some spurious warnings can be avoided if you declare all the functions you use that never return as "noreturn" ๐งน.
This warning is enabled by -Wall or -Wextra โจ.
-Wunknown-pragmasโ warns when a"#pragma"directive is encountered that GCC doesn't understand ๐คจ. If this command-line option is used, warnings are even issued for unknown pragmas in system header files ๐. That is not the case if the warnings are only enabled by the-Wallcommand-line option ๐ โโ๏ธ.-Wno-pragmasโ do not warn about misuses of pragmas, such as incorrect parameters, invalid syntax, or conflicts between pragmas ๐ซก. See also-Wunknown-pragmas๐.-Wno-prio-ctor-dtor: okay so this is a don't yell at me switch ๐ GCC won't warn if you give a constructor or destructor a priority from 0 to 100. The constructor and destructor attributes let you set a priority to control when they run, either beforemainis called or after it returns ๐ง But the compiler keeps 0โ100 for itself, so your priority values have to be greater than 100 โจ-Wstrict-aliasing: this one only works when-fstrict-aliasingis turned on ๐ It warns about code that might break the strict aliasing rules the compiler uses for optimization. It doesn't catch every case, but it goes after the more common pitfalls ๐ซถ It's included in-Wall, and it's equivalent to-Wstrict-aliasing=3๐ฆ-Wstrict-aliasing=n: also only active when-fstrict-aliasingis on โจ It warns about the same kind of sketchy code, and higher levels are more accurate (fewer false positives) but take more effort, kinda like how-Oworks ๐ฅ-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3.- Level 1: 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 tradeoff is it has many false positives ๐ It warns for all pointer conversions between possibly incompatible types, even if the pointer is never dereferenced. It runs in the front end only. - Level 2: aggressive, quick, and not too precise ๐ญ It may still have many false positives (not as many as level 1 though) 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, and it runs in the front end only.
- Level 3 (default for
-Wstrict-aliasing): this is the one that should have very few false positives and few false negatives ๐ It's slightly slower than levels 1 or 2 when optimization is enabled. It takes care of 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 handles multiple statement cases using flow-sensitive points-to information. It only warns when the converted pointer is dereferenced, and it does not warn about incomplete types.
- Level 1: most aggressive, quick, and least accurate ๐ It's possibly useful when the higher levels don't warn but
-Wstrict-overflow,-Wstrict-overflow=n: this is only active when signed overflow is undefined ๐ It warns about cases where the compiler optimizes based on the assumption that signed overflow never happens. It doesn't warn about every spot where the code might overflow, just the spots where the compiler actually does an optimization, so this warning depends on your optimization level ๐ค
An optimization that assumes no signed overflow is perfectly safe if the variables involved never actually overflow, so this warning can easily give a false positive (a warning about code that isn't really a problem) ๐ฅบ To help you focus on the important stuff, there are several warning levels. No warnings get issued for undefined signed overflow when estimating how many iterations a loop needs, especially when figuring out whether a loop runs at all.
-Wstrict-overflow=1: warns about cases that are both questionable and easy to avoid, like the compiler simplifyingx + 1 > xto1. This level is enabled by-Wall. Higher levels aren't, so you have to request them explicitly ๐-Wstrict-overflow=2: also warns about other cases where a comparison gets simplified to a constant, likeabs (x) >= 0. That 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 cases where a comparison is simplified, likex + 1 > 1getting simplified tox > 0๐-Wstrict-overflow=4: also warns about other simplifications not covered above, like(x * 10) / 5getting simplified tox * 2โจ-Wstrict-overflow=5: also warns when the compiler reduces the magnitude of a constant involved in a comparison, likex + 2 > ygetting simplified tox + 1 >= y. This only shows up at the highest warning level because the 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, because one argument is longer than the array the other argument is stored in (or the bound, forstrncmp) ๐ซง Calls like that could be mistakes. In the example below, thestrcmpcall gets flagged because its result is necessarily non-zero no matter what's in the arraya. This one is enabled by-Wextra๐
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");
}
-Wno-stringop-overflow,-Wstringop-overflow,-Wstringop-overflow=type: warns for calls to string manipulation functions likememcpyandstrcpythat are determined to overflow the destination buffer ๐จ The optional argument is one greater than the type of Object Size Checking used to figure out the size of the destination ๐ฆ It only matters for functions that operate on character arrays, not raw memory functions likememcpy, which always use Object Size type-0. 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, but it can detect a small subset of simple buffer overflows even without optimization in calls to GCC built-in functions like __builtin_memcpy that correspond to the standard functions. Either way, it only warns about a subset of the buffer overflows that the matching overflow checking built-ins would catch. In the example below, the strcpy call gets a warning 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
}
-Wstringop-overflow,-Wstringop-overflow=1: this uses type-zero Object Size Checking to figure out the sizes of destination objects ๐ At this setting, it doesn't warn for writes past the end of subobjects of larger objects accessed through pointers, unless the size of the largest surrounding object is known. When the destination might be one of several objects, it's assumed to be the largest one of them. On Linux systems, when optimization is enabled at this setting, the option warns for the same code as when the_FORTIFY_SOURCEmacro is defined to a non-zero value ๐ง-Wstringop-overflow=2: this uses type-one Object Size Checking to figure out the sizes of destination objects ๐ At this setting, it warns about overflows when writing to members of the largest complete objects whose exact size is known. It does not warn for excessive writes to the same members of unknown objects referenced by pointers, since they might point to arrays with an unknown number of elements. This is the default setting for the option ๐-Wstringop-overflow=3: this uses type-two Object Size Checking to figure out the sizes of destination objects ๐ At this setting, it warns about overflowing the smallest object or data member. It's the most restrictive setting that can still give warnings for safe code ๐ฌ-Wstringop-overflow=4: this uses type-three Object Size Checking to figure out the sizes of destination objects ๐ฅ At this setting, it warns about overflowing any data members. When the destination is one of several objects, it uses the size of the largest of them to decide whether to warn. Just like-Wstringop-overflow=3, this setting may result in warnings for benign code ๐-Wno-stringop-overread: warns for calls to string manipulation functions likememchrorstrcpythat are determined to read past the end of the source sequence ๐-Wstringop-overreadis enabled by default, so this is the switch to flip if you want it quiet ๐ซถ-Wno-stringop-truncation: don't warn for calls to bounded string manipulation functions likestrncat,strncpy, andstpncpythat might either truncate the copied string or leave the destination unchanged ๐ฆ In the example below, thestrncatcall sets a bound that's less than the length of the source string. That means the copy gets truncated, so the call is flagged. To avoid the warning, usebufsize - strlen (buf) - 1)as the bound โจ
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Okay, so bestie, this next example is a whole vibe ๐
The strncpy call below copies only the characters before the terminating NUL into d, and it does not tack the NUL onto the end. Assuming strncpy always gives you a NUL-terminated string is a super common mistake ๐ญ, so GCC calls it out. If you don't need the result to be NUL-terminated, use memcpy instead ๐
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
Next up, the strncpy call here uses the size of the destination buffer as its bound. If the source string is equal to or longer than that size, the copy won't be NUL-terminated, so this one gets flagged too ๐ To dodge the warning, pass sizeof buf - 1 as the bound and set the last element of the buffer to NUL. Main character energy ๐
void copy (const char *s)
{
char buf[80];
strncpy (buf, s, sizeof buf);
...
}
If a character array is meant to hold a sequence of bytes with no terminating NUL, you can annotate it with the attribute nonstring so GCC stops yelling about it ๐ฆ Just know these arrays aren't suitable for functions that expect NUL-terminated strings ๐ To help catch accidental misuse, GCC warns unless it can prove the use is safe.
-Wstrict-flex-arrays(C and C++ only) โ Okay, this one checks for improper usage of flexible array members. The level comes from thestrict_flex_array (level)attribute on the trailing array field of a struct if it's available, otherwise from the-fstrict-flex-arrays=leveloption.-Wstrict-flex-arraysis only effective when level is greater than 0 ๐ธ
The levels stack up like this:
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.level=2: in addition tolevel=1, extra warnings are issued for a trailing one-element array reference of a structure if the array is referenced as a flexible array member.level=3: in addition tolevel=2, extra warnings are issued for a trailing zero-length array reference of a structure if the array is referenced as a flexible array member.
This option hits harder when -ftree-vrp is active (the default for -O2 and above), but some warnings can show up even without optimization โจ
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]returns_nonnull|โ Warns when adding an attribute might be a good idea ๐ง The attributes this covers are listed below:
-Wsuggest-attribute=pure
-Wsuggest-attribute=const
-Wsuggest-attribute=noreturn
-Wmissing-noreturn
-Wsuggest-attribute=malloc
-Wsuggest-attribute=returns_nonnull
-Wno-suggest-attribute=returns_nonnull
These flag functions that could be candidates for the pure, const, noreturn, malloc or returns_nonnull attributes. GCC only warns for functions visible in other compilation units, or (for pure and const) if it can't prove the function returns normally. A function returns normally if it doesn't contain an infinite loop or return abnormally by throwing, calling abort or trapping. This analysis needs -fipa-pure-const, which is on by default at -O and higher. Higher optimization levels make the analysis more accurate ๐ฅ
-Wsuggest-attribute=format,-Wmissing-format-attributeโ Warns about function pointers that might be candidates forformatattributes ๐ These are only possible candidates, not absolute ones. GCC guesses that function pointers withformatattributes 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 fit any function that calls something like vprintf or vscanf, but that's not always the case, and some functions where format attributes are appropriate might not get detected.
-Wsuggest-attribute=coldโ Warns about functions that might be candidates for thecoldattribute ๐ง This is based on static detection and usually only warns about functions that always lead to a call to anothercoldfunction, like wrappers of C++throwor fatal error reporting functions that end up atabort.-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 gets assigned to. This includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc๐-Walloc-zeroโ Warns about calls to allocation functions decorated withalloc_sizethat specify zero bytes, including the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc๐ญ The behavior of these functions with a zero size differs between implementations (and forreallocit's been deprecated), so relying on it can cause subtle portability bugs. Please avoid it ๐-Wcalloc-transposed-argsโ A coding style warning ๐ It flags calls to allocation functions decorated withalloc_sizethat have two arguments, usesizeofas the earlier size argument, and don't use it as the later one. 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). Ifsizeofin the earlier argument (and not the latter) is intentional, you can suppress the warning withcalloc (sizeof (struct S) + 0, n)orcalloc (1 * sizeof (struct S), 4), or by usingsizeofin the later argument as well โจ-Walloc-size-larger-than=byte-sizeโ Warns about calls to functions decorated withalloc_sizethat try to allocate objects larger than the specified number of bytes. It also fires when 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 on by default ๐ You can turn off these warnings either by specifying a byte-size ofSIZE_MAXor more, or with-Wno-alloc-size-larger-than.-Wno-alloc-size-larger-thanโ Disables the-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 ๐ฌ-Walloca-larger-than=byte-sizeโ This one warns on calls toallocawhere the integer argument is either zero, or isn't bounded by a controlling predicate that limits its value to at most byte-size. It also warns for calls toallocawhere the bound value is unknown. Arguments of non-integer types count as unbounded, even if they look like they're constrained to the expected range ๐
A bounded use of alloca could look like this:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
Passing -Walloca-larger-than=1000 won't warn here, because the call to alloca is known to be at most 1000 bytes. But if -Walloca-larger-than=500 were passed, the compiler would emit a warning ๐ฆ
Unbounded uses, on the other hand, are uses of alloca with no controlling predicate constraining its integer argument. For example:
void func ()
{
void *p = alloca (n);
f (p);
}
If -Walloca-larger-than=500 were passed, the above would trigger a warning, this time because of the lack of bounds checking ๐
Note that even seemingly correct code using signed integers can cause a warning:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
In the above example, n could be negative, which would cause a larger than expected argument to be implicitly cast into the alloca call ๐ซ
This option also warns when alloca is used in a loop.
-Walloca-larger-than=PTRDIFF_MAX is enabled by default, but it's usually only effective when -ftree-vrp is active (the default for -O2 and above). See also -Wvla-larger-than=byte-size.
-Wno-alloca-larger-thanโ Disables the-Walloca-larger-than=warnings ๐ธ It's equivalent to-Walloca-larger-than=SIZE_MAXor larger.-Warith-conversionโ Do warn about implicit conversions from arithmetic operations, even when converting the operands to the same type can't change their values ๐ง This affects warnings from-Wconversion,-Wfloat-conversion, and-Wsign-conversion.
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 ๐ This warning is enabled by-Wall. It's more effective when-ftree-vrpis active (the default for-O2and above), but a subset of instances are issued even without optimization ๐
By default, bestie, 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 the trailing array of a structure as a flexible array member. โจ Here's the tea:
- 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 fromlevel=2plus 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've gotta ask for them explicitly ๐-Warray-bounds=2โ This level also warns about the intermediate results of pointer arithmetic that may yield out of bounds values. Expect a bigger pile of false positives here, and it's deactivated by default ๐ฅฒ
๐ -Warray-compare
Warn about equality and relational comparisons between two operands of array type. Bestie, this comparison was deprecated in C++20 ๐ฅ For example:
int arr1[5];
int arr2[5];
bool same = arr1 == arr2;
-Warray-compare is enabled by -Wall โจ
๐ -Warray-parameter, -Warray-parameter=n
Warn about redeclarations of functions involving parameters of array or pointer types of inconsistent kinds or forms, and enable the detection of out-of-bounds accesses to such parameters by warnings such as -Warray-bounds ๐ฅ
If the first function declaration uses the array form for a parameter declaration, the bound specified in the array is assumed to be the minimum number of elements expected to be provided in calls to the function and the maximum number of elements accessed by it. Failing to provide arguments of sufficient size, or accessing more than the maximum number of elements, may be diagnosed by warnings such as -Warray-bounds or -Wstringop-overflow. At level 1, the warning diagnoses inconsistencies involving array parameters declared using the "T[static N]" form ๐ง
For example, the warning triggers for the second declaration of f, because the first one with the keyword static specifies that the array argument must have at least four elements, while the second allows an array of any size to be passed to f ๐
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 denoting array sizes. Pointers and arrays of unspecified bound are considered equivalent and do not trigger a warning, so no drama there ๐ซถ
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 of the option, -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
Warn about declarations using the "alias" and similar attributes whose target is incompatible with the type of the alias ๐ธ
-Wattribute-alias=1โ This is the default warning level of the-Wattribute-aliasoption. It diagnoses incompatibilities between the type of the alias declaration and that of its target. Such incompatibilities are typically indicative of bugs ๐-Wattribute-alias=2โ At this level,-Wattribute-aliasalso diagnoses cases where the attributes of the alias declaration are more restrictive than the attributes applied to its target. These mismatches can potentially result in incorrect code generation. In other cases they may be benign and could be resolved simply 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. This is the default. You can disable these warnings with either -Wno-attribute-alias or -Wattribute-alias=0 ๐
โโ๏ธ
๐ธ -Wbidi-chars=[none|unpaired|any|ucn]
Warn about possibly misleading UTF-8 bidirectional control characters in comments, string literals, character constants, and identifiers. Bestie, these characters are sneaky ๐ญ They can change left-to-right writing direction into right-to-left (and vice versa), which can cause confusion between the logical order and the visual order. This may be dangerous. For instance, it may seem that a piece of code is not commented out, whereas it in fact is ๐
There are three levels of warning supported by GCC. 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 does not warn about UCNs. It is, however, possible to turn on such checking by using -Wbidi-chars=unpaired,ucn or -Wbidi-chars=any,ucn. Using -Wbidi-chars=ucn is valid, and is equivalent to -Wbidi-chars=unpaired,ucn, if no previous -Wbidi-chars=any was specified ๐ฆ
๐
-Wbool-compare
Warn about a boolean expression 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 ๐
๐ง -Wbool-operation
Warn about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program ๐ For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++17, and deprecated otherwise.) ๐ซ
This warning is enabled by -Wall ๐
๐ -Wduplicated-branches
Warn when an if-else has identical branches. This warning detects cases like this:
if (p != NULL)
return 0;
else
return 0;
It doesn't warn when both branches contain just a null statement. This warning also warns for conditional operators:
int i = x ? *p : *p;
๐ซง -Wduplicated-cond
Warn about duplicated conditions in an if-else-if chain. For instance, warn for the following code:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
๐ -Wframe-address
Warn when __builtin_frame_address or __builtin_return_address is called with an argument greater than 0. Such calls may return indeterminate values or crash the program ๐ฑ The warning is included in -Wall ๐ฅ
๐ท -Wno-discarded-qualifiers (C and Objective-C only)
Do not warn if type qualifiers on pointers are being discarded. Typically, the compiler warns if a const char * variable is passed to a function that takes a char * parameter. This option can be used to suppress such a warning ๐คซ
๐ท -Wno-discarded-array-qualifiers (C and Objective-C only)
Do not warn if type qualifiers on arrays which are pointer targets are being discarded. Typically, the compiler warns if a const int (*)[] variable is passed to a function that takes an int (*)[] parameter. This option can be used to suppress such a warning ๐
๐บ -Wno-incompatible-pointer-types (C and Objective-C only)
Do not warn when there is a conversion between pointers that have incompatible types. This warning is for cases not covered by -Wno-pointer-sign, which warns for pointer argument passing or assignment with different signedness ๐ฆ
By default, in C99 and later dialects of C, GCC treats this issue as an error. The error can be downgraded to a warning using -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=incompatible-pointer-types ๐ซถ
This warning is upgraded to an error by -pedantic-errors ๐จ
๐ซ -Wno-int-conversion (C and Objective-C only)
Do not warn about incompatible integer to pointer and pointer to integer conversions. This warning is about implicit conversions. For explicit conversions, the warnings -Wno-int-to-pointer-cast and -Wno-pointer-to-int-cast may be used ๐
By default, in C99 and later dialects of C, GCC treats this issue as an error. The error can be downgraded to a warning using -fpermissive (along with certain other errors), or for this error alone, with -Wno-error=int-conversion ๐ธ
This warning is upgraded to an error by -pedantic-errors โญ
๐ณ๏ธ -Wzero-length-bounds
Warn about accesses to elements of zero-length array members that might overlap other members of the same object. Declaring interior zero-length arrays is discouraged, because accesses to them are undefined. Undefined behavior, bestie, so please don't ๐ โโ๏ธ
For example, the first two stores in function bad are diagnosed because the array elements overlap the subsequent members b and c. The third store is diagnosed by -Warray-bounds because it is beyond the bounds 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
}
Okay so -Wzero-length-bounds is automatically switched on whenever you enable -Warray-bounds ๐
โจ
-Wno-div-by-zeroโ bestie, this one's a vibe ๐ GCC stops yelling about compile-time integer division by zero. Floating-point division by zero never gets flagged, since it can be a totally legit way to get infinities and NaNs ๐-Wsystem-headersโ normally GCC keeps quiet about warnings in system header files, since those usually aren't real problems and would just make the output messier ๐ This flag tells GCC to treat those headers like your own code and print their warnings. Heads up though:-Wallcombined with this flag still won't warn about unknown pragmas in system headers ๐ For that, you also need-Wunknown-pragmas.-Wtautological-compareโ no cap, this catches sneaky mistakes ๐ It warns if a self-comparison always evaluates to true or false, like this:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always come out true or false, for instance:
if ((a & 16) == 10) { ... }
That one is always false, so ๐ญ This warning is enabled by -Wall.
-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 that nested function indirectly. On some targets it's only data, so it needs no special treatment. But on most targets it's 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 ๐ง Sometimes it's convenient to treat floats as approximations of infinitely precise real numbers, and 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, then allow for it in your comparisons (and when producing output, but that's a different problem). Instead of testing for equality, check whether the two values have overlapping ranges. That's done with relational operators, so equality comparisons are probably mistaken ๐ โโ๏ธ-Wtraditional(C and Objective-C only) โ this one is the ultimate throwback check ๐ฐ๏ธ It warns about constructs that behave differently in traditional and ISO C. It also flags ISO C constructs with no traditional C equivalent, and/or problematic constructs you should avoid. Here's what it's watching for:- Macro parameters that appear within string literals in the macro body. Traditional C does macro replacement inside string literals, but ISO C does not.
- Some preprocessor directives didn't exist in traditional C. Traditional preprocessors only considered a line 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 the block.
- A
switchstatement with an operand of typelong. - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this. - The ISO type of an integer constant has a different width or signedness from its traditional type. This warning is only issued if the base of the constant is ten, so hexadecimal or octal values, which typically represent bit patterns, aren't warned about.
- Use of ISO string concatenation.
- Initialization of automatic aggregates.
- Identifier conflicts with labels. Traditional C lacks a separate namespace for labels.
- Initialization of unions. If the initializer is zero, the warning is omitted. This is done under the assumption that a zero initializer in user code is conditioned on something like
__STDC__to avoid missing-initializer warnings, and that it relies on default initialization to zero in the traditional C case. - Conversions by prototypes between fixed and floating-point values and vice versa. The absence of these prototypes when compiling with traditional C causes serious problems. This is a subset of the possible conversion warnings; for the full set, use
-Wtraditional-conversion. - Use of ISO C style function definitions. This warning is intentionally not issued for prototype declarations or variadic functions, because those ISO C features appear in your code when you use libiberty's traditional C compatibility macros,
PARAMSandVPARAMS. It's also bypassed for nested functions, because that feature is already a GCC extension and isn't 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 in the absence of a prototype ๐ That includes conversions between fixed-point and floating-point values and vice versa, plus conversions that change the width or signedness of a fixed-point argument, except when it matches the default promotion.-Wdeclaration-after-statement(C and Objective-C only) โ warns when a declaration is found after a statement in a block ๐ This construct comes from C++, was introduced with ISO C99, and is allowed by default in GCC. It's not supported by ISO C90. This warning is upgraded to an error by-pedantic-errors.-Wshadowโ main character energy, but make it a warning ๐ It 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 is shadowed. In C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows astruct/class/enum. If this warning is enabled, it also includes all instances of local shadowing. That means-Wno-shadow=localand-Wno-shadow=compatible-localare ignored when-Wshadowis used. Same as-Wshadow=global.-Wno-shadow-ivar(Objective-C only) โ don't warn when a local variable shadows an instance variable in 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 that of the shadowing variable. In C++, type compatibility here means the shadowing variable's type can be converted to the shadowed variable's type. The creation of this flag (in addition to-Wshadow=local) is based on the idea that when a local variable shadows another one of incompatible type, it's most likely intentional, not a bug or typo. Check out this example:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two i variables above have incompatible types, enabling only -Wshadow=compatible-local does not emit a warning. Because their types are incompatible, if a programmer accidentally uses one in place of the other, type checking is expected to catch that and emit an error or warning. Using this flag instead of -Wshadow=local can possibly reduce the number of warnings triggered by intentional shadowing. Note that this also means shadowing const char *i by 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 enabled by default. Warnings controlled by this option can be disabled either by specifying a byte-size ofSIZE_MAXor more, or by-Wno-larger-than. Also warns for calls to bounded functions such asmemchrorstrnlenthat specify a bound greater than the largest possible object, which isPTRDIFF_MAXbytes by default. These warnings can only be disabled by-Wno-larger-than๐ง-Wno-larger-thanโ disables-Wlarger-than=warnings ๐ It's equivalent to-Wlarger-than=SIZE_MAXor larger.-Wframe-larger-than=byte-sizeโ okay so this one warns you if a function's stack frame gets bigger than byte-size ๐๐ฅ. The compiler's guess at the frame size is approximate and not conservative ๐, so the real needs might be somewhat bigger than byte-size even when you get no warning at all. Also, space fromalloca, variable-length arrays, or related constructs doesn't get counted when the compiler decides whether to warn ๐.-Wframe-larger-than=PTRDIFF_MAXis on by default โจ. You can switch these warnings off by giving a byte-size ofSIZE_MAXor more, or by using-Wno-frame-larger-than๐ฆ.-Wno-frame-larger-thanโ bye bye,-Wframe-larger-than=warnings ๐๐ธ. It works the same as-Wframe-larger-than=SIZE_MAXor anything bigger.-Wfree-nonheap-objectโ this one catches you trying to free something that was never on the heap, or freeing a pointer that didn't come straight from the matching allocation function ๐ง. Like,stpcpyhands back a pointer to the terminating nul character instead of the start of your object, so thefreebelow gets flagged ๐ญ.-Wfree-nonheap-objectis part of-Wall๐.
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wstack-usage=byte-sizeโ warns if a function's stack usage might go over byte-size ๐ฅ. This math is conservative, so any space fromalloca, variable-length arrays, or related constructs gets counted ๐ซถ. The message matches what-fstack-usageprints ๐ . Here's what you'll see:- If the stack usage is fully static but goes over the limit, it says:
warning: stack usage is 1120 bytes - If the stack usage is partly dynamic but bounded, it says:
warning: stack usage might be 1648 bytes - If the stack usage is partly dynamic and not bounded, it says:
warning: stack usage might be unbounded
- If the stack usage is fully static but goes over the limit, it says:
-Wstack-usage=PTRDIFF_MAX is on by default ๐. You can turn these warnings off by giving a byte-size of SIZE_MAX or more, or by using -Wno-stack-usage ๐.
-Wno-stack-usageโ no more-Wstack-usage=warnings, periodt ๐ โโ๏ธ. Same as-Wstack-usage=SIZE_MAXor bigger.-Wunsafe-loop-optimizationsโ warns when a loop can't be optimized because the compiler can't assume anything about its index bounds ๐. Pair it with-funsafe-loop-optimizationsand it'll warn you whenever the compiler does make those assumptions ๐.-Wno-pedantic-ms-format(MinGW targets only) โ when you use it together with-Wformatand-pedantic(without GNU extensions), it silences the warnings about the non-ISOprintf/scanfwidth specifiersI32,I64, andIon Windows targets ๐ชโจ. Those depend on the MS runtime, so they're not standard, but if that's what you're going for, you can chill ๐ง.-Wpointer-arithโ heads up for anything that depends on the "size of" a function type or ofvoid๐. GNU C gives those types a size of 1, which is handy for math withvoid *pointers and pointers to functions ๐. In C++, it also warns when an arithmetic operation involvesNULL๐. This warning is also turned on by-Wpedantic๐ฅ. It gets upgraded to an error by-pedantic-errors๐จ.-Wno-pointer-compareโ don't warn when a pointer gets compared with a zero character constant ๐. That usually means the pointer was meant to be dereferenced, so the warning is usually helpful ๐คทโโ๏ธ. Here's an example:
const char *p = foo ();
if (p == '\0')
return 42;
Just so you know, the code above is invalid in C++11 ๐. This warning is enabled by default โ .
-Wno-tsanโ shuts up the warnings about unsupported features in ThreadSanitizer ๐งต. Real talk, ThreadSanitizer doesn't supportstd::atomic_thread_fenceand can report false positives ๐.-Wtype-limitsโ warns if a comparison is always true or always false because of the limited range of the data type ๐. Constant expressions don't get the warning, though ๐ . For example, it warns if an unsigned variable gets compared against zero with<or>=๐. This warning is also enabled by-Wextraโจ.-Wabsolute-value(C and Objective-C only) โ warns when you call a standard function that computes an absolute value when there's a better standard function for the job ๐งฎ. For example,abs(3.14)triggers it becausefabsis the right call for a double ๐. It also warns if the argument to one of those functions 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 get encountered that might change what your program means ๐ฎ. Trigraphs inside comments don't get warned about, except the ones that would form escaped newlines ๐ฆ. This option is implied by-Wall. If-Wallisn't given, this option is still on unless trigraphs are enabled ๐. Want trigraph conversion with no warnings but still get the other-Wallwarnings? Use-trigraphs -Wall -Wno-trigraphs๐.-Wundefโ warns if an undefined identifier gets evaluated in an#ifdirective ๐ต๏ธโโ๏ธ. Those identifiers get replaced with zero, which can be sneaky ๐ญ.-Wexpansion-to-definedโ warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective ๐. That usage isn't portable ๐ โโ๏ธ. This warning is also enabled by-Wpedanticand-Wextra๐.-Wunused-macrosโ warns about macros defined in the main file that never get used ๐งน. A macro counts as used if it gets expanded or tested for existence at least once ๐. The preprocessor also warns if the macro hasn't been used by the time it gets redefined or undefined โจ.
Built-in macros, macros defined on the command line, and macros defined in include files don't get warned about ๐.
Heads up: if a macro is actually used, but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐. To dodge the warning in that case, you could improve the scope of the macro's definition, like moving it into the first skipped block ๐ฆ. Or you could add a dummy use with something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ don't warn when an#elseor an#endifgets followed by text ๐. This happens sometimes in older programs with code that looks like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO are supposed to be in comments ๐ญ. This warning is on by default โ
.
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a non-matching type ๐ญ. For example, it warns if a call to a function returning an integer type gets cast to a pointer type ๐.-Wc90-c99-compat(C and Objective-C only) โ warns about features that are in ISO C99 but not in ISO C90 ๐ฐ๏ธ. Examples include variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on ๐งธ. This option doesn't depend on the standards mode ๐. Warnings are disabled in the expression that follows__extension__๐ซถ.-Wc99-c11-compat(C and Objective-C only) โ warns about features that are in ISO C11 but not in ISO C99 โจ. Think anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on ๐ . This option doesn't depend on the standards mode ๐. Warnings are disabled in the expression that follows__extension__๐ธ.-Wc11-c23-compat,-Wc11-c2x-compat(C and Objective-C only) โ warns about features that are in ISO C23 but not in ISO C11 ๐ฎ. Examples are omitting the string in_Static_assert, using[[]]attribute syntax, using decimal floating-point types, and so on ๐ง. This option doesn't depend on the standards mode ๐. Warnings are disabled in the expression that follows__extension__๐ซถ. The name-Wc11-c2x-compatis deprecated, so use-Wc11-c23-compatinstead ๐ฅน.
When you're not compiling in C23 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++ ๐งฉ. One example is asking for an implicit conversion fromvoid *to a pointer to a non-voidtype ๐.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changed between ISO C++ 1998 and ISO C++ 2011 ๐ฐ๏ธ. For example, identifiers that were fine in ISO C++ 1998 but are keywords in ISO C++ 2011 ๐. This warning turns on-Wnarrowingand is enabled by-Wall๐.-Wc++14-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changed between ISO C++ 2011 and ISO C++ 2014 ๐. This warning is enabled by-Wallโ .-Wc++17-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changed between ISO C++ 2014 and ISO C++ 2017 ๐ฆ. This warning is enabled by-Wallโ .-Wc++20-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changed between ISO C++ 2017 and ISO C++ 2020 ๐. This warning is 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 you use-Wpedantic๐ง.-Wno-c++14-extensions(C++ and Objective-C++ only) โ don't warn about C++14 constructs when you're compiling with an older C++ standard ๐ธ. Even without this option, some C++14 constructs only get flagged if you use-Wpedantic๐ง.-Wno-c++17-extensions(C++ and Objective-C++ only) โ don't warn about C++17 constructs when you're compiling with an older C++ standard โจ. Even without this option, some C++17 constructs only get flagged if you use-Wpedantic๐ง.-Wno-c++20-extensions(C++ and Objective-C++ only) โ okay bestie, this one tells the compiler to chill about C++20 stuff when your code is written for an older C++ standard ๐ Even without it, some C++20 constructs only get flagged if you turn on-Wpedantic.-Wno-c++23-extensions(C++ and Objective-C++ only) โ same energy, but for C++23 โจ It stops the warnings about C++23 constructs when you're compiling with an older C++ standard. Some C++23 constructs still only get called out with-Wpedantic.-Wno-c++26-extensions(C++ and Objective-C++ only) โ and yes, C++26 gets the same treatment ๐ No warnings about C++26 constructs in code built with an older C++ standard. Some C++26 constructs will only be diagnosed if-Wpedanticis used.-Wcast-qualโ this one catches you when a pointer gets cast so it drops a type qualifier from the target type. For example, it warns if aconst char *gets cast to a plainchar *๐
It also warns when a cast adds a type qualifier in an unsafe way. Casting char ** to const char ** is the classic example, and it's a whole mess:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ warns whenever a pointer cast increases the alignment the target needs. For example, it warns if achar *gets cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries ๐ฆ-Wcast-align=strictโ the no-excuses version of the one above ๐ค It warns whenever a pointer cast increases the required alignment, no matter the target machine. So achar *cast to anint *gets flagged everywhere.-Wcast-function-typeโ warns when a function pointer gets cast to an incompatible function pointer type. A few vibes to know about:- With function types that take a variable argument list, only the types of the initial arguments that are actually provided get considered.
- Any pointer-type parameter matches any other pointer-type.
- Benign differences in integral types get ignored, like
intvs.longon ILP32 targets. - Type qualifiers get ignored too.
- The function type
void (*) (void)is special and matches everything, so you can use it to suppress this warning ๐คซ - For casts involving pointer to member types, it warns whenever the cast changes the pointer to member type.
This warning is enabled by -Wextra.
-Wwrite-stringsโ in C, string constants get the typeconst char[length], so copying one's address into a non-constchar *pointer gives a warning. These help you find, at compile time, code that might try to write into a string constant. The catch is they only work well if you've been super careful withconstin your declarations and prototypes. Otherwise they're just annoying ๐ That's why-Walldoesn't ask for them.
In C++, it warns about the deprecated conversion from string literals to char *. This one is enabled by default for C++ programs.
Heads up: in C++11 mode or later, this warning gets upgraded to an error by -pedantic-errors.
-Wclobberedโ warns about variables that might get 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 doesn't apply to that front end. This flag shuts that down. It's mostly useful when you're invoking one compiler driver for multiple source files written in different languages, like this:
$ g++ -fno-rtti a.cc b.f90
The g++ driver uses the C++ front end to compile a.cc and the Fortran front end to compile b.f90. The Fortran front end then complains with this message:
f951: Warning: command-line option '-fno-rtti' is valid for C++/D/ObjC++ but not for Fortran, which may be disabled with -Wno-complain-wrong-lang.
-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โ warns about implicit conversions that might change a value ๐ That includes:- conversions between real and integer, like
abs (x)whenxis adouble; - conversions between signed and unsigned, like
unsigned ui = -1; - conversions to smaller types, like
sqrtf (M_PI).
- conversions between real and integer, like
It doesn't warn about explicit casts like abs ((int) x) and ui = (unsigned) -1, or about conversions that don't change the value, like abs (2.0). If you want to silence warnings about signed and unsigned integer conversions, use -Wno-sign-conversion.
In C++, it also warns about confusing overload resolution for user-defined conversions. It also covers conversions that never use a type conversion operator: conversions to void, to the same type, to a base class, or to a reference to them. In C++, warnings about signed and unsigned integer conversions are disabled by default unless you explicitly enable -Wsign-conversion.
Warnings about conversions from arithmetic on a small type back to that same type only show up with -Warith-conversion ๐ธ
-Wdangling-elseโ warns about constructions where it's unclear whichifstatement anelsebranch belongs to ๐ซ Here's a sneaky example:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C and C++, every else branch belongs to the innermost possible if statement, which here is if (b). That's often not what the programmer meant, and the indentation in the example above shows exactly that trap. When there's potential for this confusion, GCC issues a warning if this flag is specified. To get rid of the warning, add explicit braces around the innermost if statement, so the else can't possibly belong to the enclosing if. The fixed code looks like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses.
-Wdangling-pointer,-Wdangling-pointer=nโ โจ these warn about uses of pointers (or C++ references) to objects with automatic storage duration after their lifetime has ended. That includes local variables declared in nested blocks, compound literals, and other unnamed temporary objects. It also warns about storing the address of such objects in escaped pointers ๐ง This warning is enabled at all optimization levels, but it may give different results with optimization than without.-Wdangling-pointer=1โ at level 1, the warning only diagnoses unconditional uses of dangling pointers.-Wdangling-pointer=2โ at level 2, the warning also diagnoses conditional uses of dangling pointers, on top of the unconditional ones.
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. -Wdangling-pointer=2 is included in -Wall.
This example triggers the warning at level 1, because the address of the unnamed temporary is unconditionally referenced outside of its scope:
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 the next function, storing the address of the local variable x into the escaped pointer *p triggers the warning at level 1 ๐
void g (int **p)
{
int x = 7;
// warning: storing the address of local variable 'x' in '*p'
*p = &x;
}
In this one, the array a is out of scope by the time the pointer s gets used. Since the code that sets s is conditional, the warning triggers at level 2:
extern void frob (const char *);
void h (char *s)
{
if (!s)
{
char a[12] = "tmpname";
s = a;
}
// warning: dangling pointer 's' to 'a' may be used
frob (s);
}
-Wdate-timeโ warns when the macros__TIME__,__DATE__or__TIMESTAMP__show up, since they might stop your builds from being bit-wise-identical and reproducible โฐ-Wempty-bodyโ warns if an empty body shows up in anif,elseordo whilestatement. This warning is also enabled by-Wextra๐ซถ-Wno-endif-labelsโ stops the warnings about stray tokens after#elseand#endif๐-Wenum-compareโ warns about a comparison between values of different enumerated types. In C++, enumerated type mismatches in conditional expressions also get diagnosed, and this warning is enabled by default there. In C, it's enabled by-Wall๐ฅ-Wenum-conversionโ warns when a value of enumerated type gets implicitly converted to a different enumerated type. In C, this warning is enabled by-Wextra๐-Wenum-int-mismatch(C and Objective-C only) โ warns about mismatches between an enumerated type and an integer type in declarations. 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 the underlying type of an enumerated type is implementation-defined, these mismatches can cause portability issues. In C++, such mismatches are an error. In C, this warning is enabled by -Wall and -Wc++-compat ๐
okay so this one is about jumping over variables ๐ฆ
-Wjump-misses-init(C, Objective-C only) โ this warns if agotoor aswitchhops forward past the initialization of a variable, or jumps backward to a label after that variable has already been set up. It only cares about variables that get initialized right where they're declared. This one is only for C and Objective-C, because in C++ this kind of jump is already an error anyway ๐-Wjump-misses-initis part of-Wc++-compat๐ซถ and you can switch it off with the-Wno-jump-misses-initoption ๐ธ-Wsign-compareโ compare vibes check ๐ this warns when you compare signed and unsigned values and the result could be wrong because the signed one gets converted to unsigned. In C++ it's also turned on by-Wall, and in C it's turned on by-Wextraโจ-Wsign-conversionโ this one catches implicit conversions that might flip the sign of an integer, like shoving a signed integer expression into an unsigned integer variable ๐ An explicit cast will shut it up. In C,-Wconversionalso turns this on ๐-Wflex-array-member-not-at-end(C and C++ only) โ not it ๐ this warns when a struct with a C99 flexible array member as its last field ends up sitting in the middle of another struct. Here's the kind of thing it's talking about:
struct flex { int length; char data[]; };
struct mid_flex { int m; struct flex flex_data; int n; };
-Wfloat-conversionโ warns about implicit conversions that lower the precision of a real value. That covers real to integer, and higher precision real to lower precision real ๐ง This one is also enabled by-Wconversion๐-Wno-scalar-storage-orderโ bye bye suspicious stuff ๐ this stops the warnings about questionable constructs involving reverse scalar storage order โจ-Wsizeof-array-divโ warns when you divide twosizeofoperators and the first one is applied to an array, but the divisor isn't the size of an array element. The math won't give you the number of elements, which is almost definitely not what you meant ๐ญ Here's an example it would flag:
int fn ()
{
int arr[10];
return sizeof (arr) / sizeof (short);
}
This warning is enabled by -Wall ๐
-Wsizeof-pointer-divโ this flags suspicious divisions of twosizeofexpressions that divide the pointer size by the element size. That's the usual trick for getting an array's length, but it totally falls apart with pointers ๐ It warns about"sizeof (ptr) / sizeof (ptr[0])"when"ptr"is a pointer and not an array. This warning is enabled by-Wall๐ฅ-Wsizeof-pointer-memaccessโ warns about sketchy length arguments to certain string and memory built-in functions when the argument usessizeof. It goes off for things likememset (ptr, 0, sizeof (ptr));whenptris really a pointer, and it even suggests a possible fix. It also catchesmemcpy (&foo, ptr, sizeof (&foo));๐ This option also warns about bounded string copy functions likestrncatorstrncpywhen the bound is asizeofon the source array. Check out this one:
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
In that function, the strncat call uses the size of the source string as its bound. That's almost certainly a mistake, so it gets diagnosed ๐จ
This option is enabled by -Wall ๐
-Wno-sizeof-array-argumentโ chill, it's fine ๐ธ this turns off the warning for whensizeofis applied to a parameter that's declared as an array in a function definition. This warning is on by default for C and C++ programs ๐ซถ-Wmemset-elt-sizeโ warns about shadymemsetbuilt-in calls where the first argument points to an array, and the third argument is a number equal to the element count but not equal to the array's full size in memory. That usually means you forgot to multiply by the element size ๐ This one is enabled by-Wallโจ-Wmemset-transposed-argsโ warns about suspiciousmemsetbuilt-in calls where the second argument isn't zero and the third argument is zero. For example,memset (buf, sizeof buf, 0)gets flagged, becausememset (buf, 0, sizeof buf)was what you meant ๐ The diagnostic only shows up if the third argument is a literal zero. If it's an expression that folds down to zero, or a cast of zero to some type, the arguments are way less likely to be transposed by mistake, so no warning is emitted ๐ฆ This warning is enabled by-Wall๐-Waddressโ suspicious address alert ๐จ this warns about dodgy address expressions. That includes comparing the address of a function or a declared object to a null pointer constant, like this:
void f (void);
void g (void)
{
if (!f) // warning: expression evaluates to false
abort ();
}
It also includes comparing a pointer to a string literal:
void f (const char *x)
{
if (x == "abc") // warning: expression evaluates to false
puts ("equal");
}
And testing the result of pointer addition or subtraction for equality to null:
void f (const int *p, int i)
{
return p + i == NULL;
}
These uses usually point to a programmer error. The address of most functions and objects always evaluates to true (weak symbols are the exception), so using them in a conditional might mean you're missing parentheses in a function call or a dereference in an array expression ๐ญ
The part about object pointers can be silenced by casting the pointer operand to an integer type like intptr_t or uintptr_t ๐ซถ Comparing against string literals leads to unspecified behavior and isn't portable, and it suggests you probably meant to call strcmp ๐ The warning is also suppressed if the suspicious expression came from macro expansion. The -Waddress warning is enabled by -Wall ๐
-Wno-address-of-packed-memberโ don't warn about this one ๐ง this stops the warning for when the address of a packed member of a struct or union gets taken, which usually ends up as an unaligned pointer value. This is enabled by default ๐-Wlogical-opโ warns about suspicious uses of logical operators in expressions, including places where a bitwise operator was probably what you wanted ๐ค It also warns when both operands of a logical operator are the same:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns when a logical not is used on the left-hand side of a comparison. It won't warn if the right operand is a boolean expression. The whole point is catching sus code like this ๐
int a;
...
if (!a > 1) { ... }
You can make the warning go away by wrapping the left-hand side in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall ๐
-Waggregate-returnโ warns if any functions that return structs or unions are defined or called ๐ (In languages where you can return an array, this also triggers a warning.)-Wno-aggressive-loop-optimizationsโ this one is about loops ๐ it warns if, in a loop with a constant number of iterations, the compiler detects undefined behavior in some statement during one or more of the iterations โจ-Wno-attributesโ attribute drama ๐ this stops the warning when an unexpected__attribute__shows up, like unrecognized attributes, function attributes slapped onto variables, and so on. It doesn't stop errors for incorrectly using attributes that are supported ๐ซถ
Warnings about ill-formed uses of standard attributes get upgraded to errors by -pedantic-errors ๐ญ
You can also use -Wno-attributes= to suppress warnings about unknown scoped attributes (in C++11 and C23) ๐ง For example, -Wno-attributes=vendor::attr disables the warning for this declaration:
[[vendor::attr]] void f();
Or you can disable warnings about all attributes in a namespace with -Wno-attributes=vendor::, which covers both of these declarations:
[[vendor::safe]] void f();
[[vendor::unsafe]] void f2();
Just remember that -Wno-attributes= does not imply -Wno-attributes ๐
-Wno-builtin-declaration-mismatchโ built-in beef ๐ this warns if a built-in function is declared with an incompatible signature, or as something that isn't a function. It also fires when a built-in function declared without a prototype gets called with arguments 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 on by default ๐ธ To dodge it, include the right header so the built-in prototypes are in scope โจ
In this example, the memset call gets flagged because the function expects a size_t argument, but 32 is an int. With -Wextra, the declaration of the function gets flagged too ๐
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ stops warnings when certain built-in macros get redefined ๐ฆ This silences redefinitions of__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__๐-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 fine without a warning, as long as it's preceded by a declaration that does specify the argument types ๐-Wold-style-declaration(C and Objective-C only) โ this one goes after old C habits ๐ฐ๏ธ It warns about declarations the C Standard calls obsolescent, like a storage-class specifier such asstaticshowing up somewhere other than the very front of the declaration. It's also turned on by-Wextraโจ-Wold-style-definition(C and Objective-C only) โ warns whenever you write an old-style function definition, and it still speaks up even if you already gave that function a prototype ๐ Quick heads up: a definition using()isn't treated as old-style in C23 mode, since it means the same thing as(void)there. For older standards, though, it does count as old-style. ๐-Wmissing-parameter-type(C and Objective-C only) โ catches K&R-style functions where a parameter is declared without a type specifier, like this:
void foo(bar) { }
This warning is also enabled by -Wextra ๐
-Wno-declaration-missing-parameter-type(C and Objective-C only) โ the "don't yell at me" flag for function declarations that have a parameter name but no type. Those declarations don't give you a function prototype, so they block most type checking in function calls, which is literally chaos ๐
This warning is enabled by default. In C99 and later dialects of C, it's treated as an error ๐จ You can downgrade it to a warning with -fpermissive (along with certain other errors), or downgrade this one error alone with -Wno-error=declaration-missing-parameter-type.
This warning gets upgraded to an error by -pedantic-errors ๐ญ
-Wmissing-prototypes(C and Objective-C only) โ warns if a global function is defined without a previous prototype declaration. It still warns even when the definition itself has a prototype, so it's a great way to catch global functions that don't have a matching prototype in a header file ๐ฆ
This option isn't valid for C++, because all function declarations there provide prototypes, and a non-matching declaration just declares an overload instead of conflicting with an earlier one. For missing declarations in C++, use -Wmissing-declarations instead ๐ง
-Wmissing-variable-declarations(C and Objective-C only) โ warns if a global variable is defined without a previous declaration. Use it to catch global variables that don't have a matchingexterndeclaration in a header file ๐ธ-Wmissing-declarationsโ warns if a global function is defined without a previous declaration, and does so even if the definition provides a prototype. Use it to find global functions that aren't declared in header files ๐
In C, there are no warnings for functions with previous non-prototype declarations, so use -Wmissing-prototypes to catch missing prototypes there. In C++, there are no warnings for function templates, inline functions, or functions in anonymous namespaces โจ
-Wmissing-field-initializersโ warns if a structure's initializer is missing some fields. In this example,x.his implicitly zero, so it triggers the warning:
struct s { int f, g, h; };
struct s x = { 3, 4 };
In C, this option doesn't warn about designated initializers, so this modification doesn't trigger a warning:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, this option also doesn't warn about the universal zero initializer { 0 }:
struct s { int f, g, h; };
struct s x = { 0 };
Likewise, in C++ this option doesn't warn about the empty { } initializer:
struct s { int f, g, h; };
s x = { };
This warning is included in -Wextra. To get the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers ๐ซถ
-Wno-missing-requiresโ by default, the compiler warns about a concept-id showing up as a C++20 simple-requirement, like this:
bool satisfied = requires { C<T> };
Here, satisfied will be true if C<T> is a valid expression, which it is for all T. Presumably the user meant to write this:
bool satisfied = requires { requires C<T> };
That way, satisfied is only true if concept C is satisfied for type T ๐
This warning can be disabled with -Wno-missing-requires.
-Wno-missing-template-keywordโ the member access tokens.,->and::have to be followed by thetemplatekeyword if the parent object is dependent and the member being named is a template. Check out the vibe:
template <class X>
void DoStuff (X x)
{
x.template DoSomeOtherStuff<X>(); // Good.
x.DoMoreStuff<X>(); // Warning, x is dependent.
}
In rare cases, you can get false positives. To silence that, wrap the expression in parentheses. For example, the following is treated as a template, even where m and N are integers:
void NotATemplate (my_class t)
{
int N = 5;
bool test = t.m < N > (0); // Treated as a template.
test = (t.m < N) > (0); // Same meaning, but not treated as a template.
}
This warning can be disabled with -Wno-missing-template-keyword ๐
-Wno-multicharโ don't warn if a multicharacter constant ('FOOF') is used. These usually signal a typo in your code, since they have implementation-defined values and shouldn't be used in portable code ๐-Wnormalized=[none|id|nfc|nfkc]โ okay, this one is a whole mood ๐ In ISO C and ISO C++, two identifiers are different if they're different sequences of characters. But sometimes, when characters outside basic ASCII are used, you can get two different character sequences that look exactly the same. To avoid that confusion, the ISO 10646 standard sets normalization rules that turn look-alike sequences into the same sequence. GCC can warn you if your identifiers haven't been normalized, and this option controls that warning.
There are four levels of warning. The default is -Wnormalized=nfc, which warns about any identifier that isn't in the ISO 10646 "C" normalized form, NFC. NFC is the recommended form for most uses, and it's equivalent to -Wnormalized.
Unfortunately, some characters that ISO C and ISO C++ allow in identifiers stop being allowed once they're turned into NFC. So there's no way to use those symbols in portable ISO C or C++ and still have all your identifiers in NFC. -Wnormalized=id suppresses the warning for those characters. The hope is that future versions of the standards will fix this, which is why this option isn't the default ๐ฅบ
You can switch the warning off for all characters with -Wnormalized=none or -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 characters in ISO 10646 have distinct meanings but look identical in some fonts or display methods, especially once formatting has been applied. For instance, "\u207F", "SUPERSCRIPT LATIN SMALL LETTER N", displays just like a regular "n" that's been placed in a superscript. ISO 10646 defines the NFKC normalization scheme to convert all of these into a standard form too, and GCC warns if your code isn't in NFKC when you use -Wnormalized=nfkc. This is comparable to warning about every identifier that contains the letter O, because it might be confused with the digit 0. So it isn't the default, but it can be a useful local coding convention if your programming environment can't be fixed to display these characters distinctly ๐ค
-Wno-attribute-warningโ don't warn about usage of functions declared with the "warning" attribute. This warning is enabled by default. Use-Wno-attribute-warningto disable the warning, or-Wno-error=attribute-warningto disable the error when compiled with the-Werrorflag ๐ซง-Wno-deprecatedโ don't warn about usage of deprecated features ๐ฆ-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โ warns about One Definition Rule violations during link-time optimization. It's enabled by default โญ-Wopenacc-parallelismโ warns about potentially suboptimal choices related to OpenACC parallelism ๐-Wno-openmpโ warns about suspicious OpenMP code ๐ง-Wopenmp-simdโ warns if the vectorizer cost model overrides the OpenMP simd directive you set. The-fsimd-cost-model=unlimitedoption can be used to relax the cost model ๐-Woverride-init(C and Objective-C only) โ warns if an initialized field without side effects gets overridden when you're using designated initializers ๐
This warning is included in -Wextra. To get the other -Wextra warnings without this one, 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 you're using designated initializers. This warning is enabled by default ๐ญ-Wpackedโ warns if a structure is given thepackedattribute, but that attribute has no effect on the layout or size of the structure. Those structures may end up misaligned for little benefit ๐ฌ Here, the variablef.xinstruct 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 ignore thepackedattribute on bit-fields of typechar. That got fixed in GCC 4.4, but the change can lead to differences in structure layout. GCC tells you when the offset of such a field has changed in GCC 4.4. For example, in this structure there's no longer a 4-bit padding between fieldaandb:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This one's on by default, bestie ๐ but if it's being extra, you can mute it with -Wno-packed-bitfield-compat ๐
-Wpacked-not-alignedโ C, C++, Objective-C and Objective-C++ only ๐ Warns if a field with an explicitly set alignment, sitting inside a packed struct or union, ends up misaligned. In this code you'll get"warning: alignment 1 of 'struct S' is less than 8", so watch out ๐
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This one is enabled by -Wall โจ
-Wpaddedโ Flags any padding the compiler sneaks into a struct, whether it's lining up one element or the whole struct. Sometimes you can shuffle the fields around to cut the padding and make the struct smaller ๐ฆ-Wredundant-declsโ Warns if something gets declared more than once in the same scope, even when that's legal and changes nothing ๐-Wrestrictโ Warns when an object referenced by arestrict-qualified parameter (or a__restrict-qualified one in C++) gets aliased by another argument, or when copies between those objects overlap. In the example below,strcpyis trying to chop off the front of the string by copying the last four characters over the first ones. But the call also writes the terminating NUL intoa[4], so the copies overlap and GCC catches it ๐จ
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
-Wrestrict can catch some simple overlaps even without optimization, but it works best at -O2 and above. It's included in -Wall ๐
-Wnested-externsโ C and Objective-C only ๐ธ Warns if anexterndeclaration shows up inside a function-Winlineโ Warns if a function declaredinlinecan't actually be inlined. Even with this on, GCC won't warn about failures to inline functions declared in system headers ๐
GCC uses a whole bag of heuristics to decide whether to inline something. It looks at things like how big the function being inlined is, and how much inlining has already happened in the current function. So even seemingly tiny edits to your source can make -Winline warnings appear or disappear ๐
-Winterference-sizeโ Warns about using C++17'sstd::hardware_destructive_interference_sizewithout setting its value with--param destructive-interference-size. It also warns about questionable values for that option ๐ง
This is meant for class layout, so concurrent code doesn't suffer from false sharing ๐ซถ
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 idea is that one and two are far enough apart that a store to one won't force a reload of the cache line two lives on ๐
By default, --param destructive-interference-size and --param constructive-interference-size are set based on the current -mtune option. That's typically the L1 cache line size for the particular target CPU, though sometimes it's a range if you're tuning for a generic target.
So every translation unit that depends on ABI compatibility for these variables must be compiled with the same-mtune(or-mcpu). โ ๏ธ
If ABI stability matters, like if you're using this in a header for a library, you should probably not use the hardware interference size variables at all. Alternatively, you can force a particular value with --param ๐
If you're confident your use of the variable doesn't affect ABI outside a single build of your project, you can turn off the warning with -Wno-interference-size ๐ง
-Wint-in-bool-contextโ Warns about sus integer usage where a boolean is expected ๐ Think conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). Or left-shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. The same goes for all kinds of multiplications, no matter the data type. Enabled by-Wall๐ฅ-Wno-int-to-pointer-castโ Suppresses warnings about casts to a pointer type from an integer of a different size.
In C++, casting to a pointer type of smaller size is an error. ๐
-Wint-to-pointer-cast is enabled by default ๐
-Wno-pointer-to-int-castโ C and Objective-C only ๐ Suppresses warnings about casts from a pointer to an integer type of a different size-Winvalid-pchโ Warns if a precompiled header is found in the search path but can't be used ๐ฅฒ-Winvalid-utf8โ Warns if an invalid UTF-8 character is found. This one's on by default for C++23 when-finput-charset=UTF-8is used, and it gets turned into an 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 โจ-Wlong-longโ Warns if thelong longtype is used. This is enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. To inhibit the messages, use-Wno-long-long๐
This warning gets upgraded to an error by -pedantic-errors ๐ซ
-Wvariadic-macrosโ Warns if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode. This is enabled by either-Wpedanticor-Wtraditional. To inhibit the warning messages, use-Wno-variadic-macros๐งฉ-Wno-varargsโ Stops warnings about questionable usage of the macros that handle variable arguments, likeva_start. These warnings are enabled by default ๐-Wvector-operation-performanceโ Warns if a vector operation isn't implemented via the SIMD capabilities of the architecture. It's mainly useful for performance tuning ๐๏ธ A vector operation can be implemented "piecewise", meaning the scalar operation runs on every vector element. It can be implemented "in parallel", meaning it uses scalars of a wider type, which is normally more performance efficient. Or it can be implemented "as a single scalar", meaning the vector fits into a scalar type.-Wvlaโ Warns if a variable-length array is used in the code.-Wno-vlaprevents the-Wpedanticwarning about variable-length arrays. This warning is upgraded to an error by-pedantic-errors๐ซ-Wvla-larger-than=byte-sizeโ If you use this, the compiler warns for declarations of variable-length arrays whose size is either unbounded, or bounded by an argument that lets the array size exceedbyte-sizebytes. It's kind of like how-Walloca-larger-than=byte-sizeworks, but for VLAs ๐
GCC may optimize small variable-length arrays of a known value into plain arrays, so this warning may not get triggered 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-Wvla-larger-than=warnings. The option is equivalent to-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 detection of out-of-bounds accesses to those parameters by 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 the maximum number of elements it accesses. Passing arguments that are too small, or accessing more than that maximum, may be diagnosed.
For example, the warning triggers for these redeclarations. The first one allows an array of any size to be passed to f, while the second one says the array argument must have at least n elements. Calling f with the associated VLA bound parameter in excess of the actual VLA bound triggers a warning as well ๐ซ
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. -Warray-parameter triggers warnings for similar problems involving ordinary array arguments ๐
-Wvolatile-register-varโ Warns if a register variable is declaredvolatile. Heads up, thevolatilemodifier doesn't inhibit all optimizations that may 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, where it looks like you meant exponentiation. Specifically, the warning happens 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, whereas 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, as well as by compiling with -Wno-xor-used-as-pow ๐ซถ
-Wdisabled-optimizationโ Warns if a requested optimization pass is disabled. This doesn't generally mean anything is wrong with your code. 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, since GCC refuses to optimize programs when the optimization itself would likely take inordinate amounts of time.-Wpointer-sign(C and Objective-C only) โ okay bestie, this one yells when a pointer gets passed or assigned with a different signedness ๐- This only works for C and Objective-C ๐
- It's already switched on by
-Walland-Wpedantic, and you can turn it off with-Wno-pointer-sign๐ -pedantic-errorsupgrades it into an error ๐
-Wstack-protectorโ this one is only active when-fstack-protectoris on ๐ก๏ธ It warns about functions that aren't protected against stack smashing ๐ญ-Woverlength-stringsโ this one warns about string constants that go past the "minimum maximum" length from the C standard โจ- Modern compilers are super chill and let strings get way longer than that minimum, but very portable programs should avoid longer strings ๐ง
- The limit applies after string 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 set a normative minimum maximum, so GCC doesn't diagnose overlength strings in C++ ๐
-Wpedanticimplies it, and you can disable it with-Wno-overlength-strings๐ซถ
-Wunsuffixed-float-constants(C and Objective-C only) โ this warns for any floating constant that doesn't have a suffix ๐ฆ- Add
-Wsystem-headersand it'll also warn about those constants in system header files ๐ - It's giving prep work for the
"FLOAT_CONST_DECIMAL64"pragma from the decimal floating-point extension to C99 ๐
- Add
-Wno-lto-type-mismatchโ during link-time optimization, this stops GCC from warning about type mismatches in global declarations across different compilation units ๐ธ It needs-fltoto be enabled, and it's enabled by default โจ-Wno-designated-init(C and Objective-C only) โ this suppresses warnings when a positional initializer is used on a structure marked with the"designated_init"attribute ๐
๐ Options That Control Static Analysis
-fanalyzerโ okay this one is the big boss ๐ It enables a static analysis of program flow that hunts for "interesting" interprocedural paths through the code, and it warns you about problems it finds on them ๐ฅ- It's way more expensive than other GCC warnings, so be patient bestie โณ
- In technical terms, it does coverage-guided symbolic execution of the code being compiled ๐ค
- It is neither sound nor complete, so it can have false positives and false negatives ๐ It's a bug-finding tool, not a tool for proving program correctness ๐
- In this release, the analyzer is only suitable for use on C code ๐ธ
- Turning this on effectively enables these 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-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 only works if GCC was configured with analyzer support enabled ๐ง
-Wanalyzer-symbol-too-complexโ the analyzer uses heuristics to track the state of memory, but sufficiently complicated code can totally defeat them ๐ตโ๐ซ- By default, if an expression goes past the threshold set by
--param analyzer-max-svalue-depth=value, the analysis quietly stops tracking its values and falls back to an imprecise representation ๐ซ - This option warns you when that happens ๐จ
- By default, if an expression goes past the threshold set by
-Wanalyzer-too-complexโ the analyzer tries to explore control flow and data flow, but again, sufficiently complicated code can defeat it ๐- By default the analysis silently stops if the code is too complicated and it hits an internal limit ๐ค
- This option warns you when that happens ๐ฃ
-Wno-analyzer-allocation-sizeโ this warning needs-fanalyzerto be enabled, and you can switch it off with-Wno-analyzer-allocation-size๐ โโ๏ธ- It warns for paths through the code where a pointer to a buffer gets assigned to point at a buffer whose size isn't a multiple of
sizeof (*pointer)๐ - See CWE-131: Incorrect Calculation of Buffer Size,
"https://cwe.mitre.org/data/definitions/131.html"๐
- It warns for paths through the code where a pointer to a buffer gets assigned to point at a buffer whose size isn't a multiple of
-Wno-analyzer-deref-before-checkโ this one needs-fanalyzertoo, and you disable it with-Wno-analyzer-deref-before-check๐- It warns for paths where a pointer gets checked for
NULLafter it's already been dereferenced, which suggests the pointer could've been NULL all along ๐ณ Either the check is 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 to be non-NULL, so it'll complain if those values get checked forNULLafter the function call returns ๐ง - > This one is unlikely to show up when any level of optimization is on, because GCC's optimizer usually sees those
NULLchecks as redundant and deletes them before the analyzer gets a look ๐ So turn optimization off if you're trying to trigger it ๐
- It warns for paths where a pointer gets checked for
-Wno-analyzer-double-fcloseโ needs-fanalyzer, and you can disable it with-Wno-analyzer-double-fclose๐- It warns for paths where a
FILE *can havefclosecalled on it more than once ๐ - See CWE-1341: Multiple Releases of Same Resource or Handle,
"https://cwe.mitre.org/data/definitions/1341.html"๐
- It warns for paths where a
-Wno-analyzer-double-freeโ needs-fanalyzer, and use-Wno-analyzer-double-freeto disable it ๐งน- It warns for paths where a pointer can have a deallocator called on it more than once, either
free, or a deallocator referenced by attributemalloc๐๏ธ - See CWE-415: Double Free,
"https://cwe.mitre.org/data/definitions/415.html"๐
- It warns for paths where a pointer can have a deallocator called on it more than once, either
-Wno-analyzer-exposure-through-output-fileโ needs-fanalyzer, and you turn it off with-Wno-analyzer-exposure-through-output-file๐คซ- It warns for paths where a security-sensitive value gets written to an output file, like writing a password to a log file ๐
- See CWE-532: Information Exposure Through Log Files,
"https://cwe.mitre.org/data/definitions/532.html"๐
-Wanalyzer-exposure-through-uninit-copyโ this one needs both-fanalyzerand a plugin that specifies a function copying across a "trust boundary" ๐งฉ Use-Wno-analyzer-exposure-through-uninit-copyto disable it ๐ โโ๏ธ- It warns about "infoleaks", which are paths where uninitialized values get copied across a security boundary, like code inside an OS kernel copying a partially-initialized struct from the stack over to user space ๐ฑ
- See CWE-200: Exposure of Sensitive Information to an Unauthorized Actor,
"https://cwe.mitre.org/data/definitions/200.html"๐
-Wno-analyzer-fd-access-mode-mismatchโ needs-fanalyzer, and you can disable it with-Wno-analyzer-fd-access-mode-mismatch๐- It warns for paths where a "read" is attempted on a write-only file descriptor, or the other way around ๐
- It also warns for code paths where a function with attribute
fd_arg_read (N)is called with a file descriptor opened withO_WRONLYat referenced argumentN, or where a function with attributefd_arg_write (N)is called with a file descriptor opened withO_RDONLYat referenced argument N ๐งพ
-Wno-analyzer-fd-double-closeโ needs-fanalyzer, and you disable it with-Wno-analyzer-fd-double-closeโ๏ธ- It warns for paths where a file descriptor can be closed more than once ๐ช
- See CWE-1341: Multiple Releases of Same Resource or Handle,
"https://cwe.mitre.org/data/definitions/1341.html"๐
-Wno-analyzer-fd-leakโ needs-fanalyzer, and use-Wno-analyzer-fd-leakto disable it ๐ง- It warns for paths where an open file descriptor gets leaked ๐ซ
- See CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime,
"https://cwe.mitre.org/data/definitions/775.html"๐
-Wno-analyzer-fd-phase-mismatchโ needs-fanalyzer, and you disable it with-Wno-analyzer-fd-phase-mismatchโฐ- It warns for 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
accepton a stream socket that hasn't hadlistensuccessfully called on it yet ๐งฆ - See CWE-666: Operation on Resource in Wrong Phase of Lifetime,
"https://cwe.mitre.org/data/definitions/666.html"๐
- It warns for 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
-Wno-analyzer-fd-type-mismatch ๐ฆ
Okay so this one needs -fanalyzer to be switched on, which turns it on for you. To silence it, use -Wno-analyzer-fd-type-mismatch. ๐
It catches paths through your code where an operation gets run on the wrong type of file descriptor. Like trying socket operations on an fd you got from open, or doing a stream socket operation on a datagram socket. Not it. ๐
โโ๏ธ
-Wno-analyzer-fd-use-after-close ๐ธ
Also needs -fanalyzer to be enabled. Use -Wno-analyzer-fd-use-after-close to turn it off. ๐ซถ
This one flags paths where a read or write gets called on a file descriptor that's already been closed. ๐ It also catches functions with the attribute fd_arg (N), fd_arg_read (N), or fd_arg_write (N) getting called with a closed fd at the referenced argument N. Main character energy, but make it a closed file descriptor and it's a whole mess. ๐ญ
-Wno-analyzer-fd-use-without-check ๐ง
Needs -fanalyzer, obviously. Disable it with -Wno-analyzer-fd-use-without-check. โจ
This warns on paths where a file descriptor gets used without anyone checking whether it's valid first. ๐ It also warns when a function marked with fd_arg (N), fd_arg_read (N), or fd_arg_write (N) gets handed a file descriptor at referenced argument N without a validity check. Always check your fds, bestie. ๐ฅ
-Wno-analyzer-file-leak ๐
Requires -fanalyzer. Use -Wno-analyzer-file-leak to turn it off. ๐
This one lights up paths through the code where a FILE * stream object from <stdio.h> gets leaked. Like, you opened it and just... never let it go. ๐ค
Go peep CWE-775: Missing Release of File Descriptor or Handle after Effective Lifetime, which is at https://cwe.mitre.org/data/definitions/775.html. ๐
-Wno-analyzer-free-of-non-heap ๐
Needs -fanalyzer to run. Silence it with -Wno-analyzer-free-of-non-heap. ๐ฆ
It warns on paths where free gets called on a pointer that isn't on the heap. Think an on-stack buffer, or a global. You can't free something that was never heap-allocated, sweetie. ๐
See CWE-590: Free of Memory not on the Heap at https://cwe.mitre.org/data/definitions/590.html. ๐
-Wno-analyzer-imprecise-fp-arithmetic โญ
Requires -fanalyzer. Turn it off with -Wno-analyzer-imprecise-fp-arithmetic. ๐ธ
This one catches paths where floating-point arithmetic shows up in places that really need precise computation. ๐ง Right now, it only warns about floating-point operands used inside the calculation of an allocation size. That's the whole vibe for now. โจ
-Wno-analyzer-infinite-loop ๐ฅ
Needs -fanalyzer. Disable it with -Wno-analyzer-infinite-loop. ๐
This diagnostic warns on paths that seem to lead into an infinite loop. ๐
Specifically, the analyzer will throw this warning when it notices a loop where all of these are true:
- nothing externally visible can actually get done inside the loop
- there's no way to escape from the loop
- the analyzer is confident enough about the program state throughout the loop to know both of the above are true
One way this shows up is when there's a path through a loop where taking it on one iteration means the same path gets taken on every iteration after that. Honestly iconic, but also a trap. ๐ชค
Here's an example:
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 side-eye this one. If opcode ever matches none of the cases, the switch falls through to its implicit default case. That makes the loop body a no-op, cpu_state.pc never changes, and opcode stays the same on every iteration after. Now you're stuck in an infinite loop forever. ๐ญ
See CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop') at https://cwe.mitre.org/data/definitions/835.html. ๐ซถ
-Wno-analyzer-infinite-recursion ๐
Needs -fanalyzer. Use -Wno-analyzer-infinite-recursion to turn it off. ๐
This one flags paths that look like they're headed for infinite recursion. ๐ Here's how it works: 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 be changing, it warns. But if it spots any changes to parameters or globals, it assumes the recursion will eventually end and keeps quiet. ๐คซ
Heads up: this diagnostic is likely to miss infinite recursion that the optimizer turns into iteration before the analyzer gets a look. So if you're trying to trigger this one on purpose, disable optimization first. ๐
Compare this with -Winfinite-recursion, which gives you a similar diagnostic but is implemented in a totally different way. ๐
See CWE-674: Uncontrolled Recursion at https://cwe.mitre.org/data/definitions/674.html. ๐ธ
-Wno-analyzer-jump-through-null ๐ฆ
Requires -fanalyzer. Disable it with -Wno-analyzer-jump-through-null. ๐
This warns on paths where a NULL function pointer gets called. Calling nothing is not a vibe. ๐
โโ๏ธ
-Wno-analyzer-malloc-leak ๐
Needs -fanalyzer. Use -Wno-analyzer-malloc-leak to silence it. โจ
It warns on paths where a pointer allocated through an allocator gets leaked. The allocator can be malloc, or any function marked with the attribute malloc. ๐
See CWE-401: Missing Release of Memory after Effective Lifetime at https://cwe.mitre.org/data/definitions/401.html. ๐ซถ
-Wno-analyzer-mismatching-deallocation ๐ง
Requires -fanalyzer. Turn it off with -Wno-analyzer-mismatching-deallocation. ๐
This one warns on paths where the wrong deallocation function gets called on a pointer, based on which function originally allocated it. ๐ It will warn about mismatches between free, scalar delete, and vector delete[]. It also covers anything marked as an allocator/deallocator pair using the attribute malloc. Pair your allocs and deallocs properly, bestie. ๐ซถ
See CWE-762: Mismatched Memory Management Routines at https://cwe.mitre.org/data/definitions/762.html. ๐
-Wno-analyzer-out-of-bounds ๐ฅ
Needs -fanalyzer. Disable it with -Wno-analyzer-out-of-bounds. ๐
This diagnostic warns on paths where a buffer is definitely read or written out-of-bounds. It applies 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 some 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 at https://cwe.mitre.org/data/definitions/119.html. ๐ธ
When the analyzer can manage it, it'll even draw you a text art diagram of the memory involved. ๐จ It shows how the region the analyzer thinks gets accessed compares to the range that's actually valid: whether they overlap, touch, or sit far apart, which one comes first in memory, the relative sizes, whether it's a read or a write, and sometimes the data values involved. Lowkey the coolest part. โจ You can hide the diagram with -fdiagnostics-text-art-charset=none. ๐
-Wno-analyzer-overlapping-buffers ๐
Needs -fanalyzer. Use -Wno-analyzer-overlapping-buffers to turn it off. ๐ฆ
This one warns on paths where overlapping buffers get passed to an API that has undefined behaviour for that kind of input. ๐ฌ Specifically, it fires on calls to these functions:
memcpystrcatstrcpy
...but only when the buffers are known to overlap. ๐ซถ
-Wno-analyzer-possible-null-argument ๐
Requires -fanalyzer. Disable it with -Wno-analyzer-possible-null-argument. ๐
This warns on paths where a value that might be NULL gets passed to a function argument marked with __attribute__((nonnull)), which says it needs a non-NULL value. ๐ค
See CWE-690: Unchecked Return Value to NULL Pointer Dereference at https://cwe.mitre.org/data/definitions/690.html. ๐
-Wno-analyzer-possible-null-dereference ๐ธ
Needs -fanalyzer. Silence it with -Wno-analyzer-possible-null-dereference. โจ
This one warns on paths where a value that might be NULL gets dereferenced. ๐ฌ
See CWE-690: Unchecked Return Value to NULL Pointer Dereference at https://cwe.mitre.org/data/definitions/690.html. ๐ซถ
-Wno-analyzer-null-argument ๐ฆ
Requires -fanalyzer. Use -Wno-analyzer-null-argument to turn it off. ๐
This warns on paths where a value the analyzer knows is NULL gets passed to a function argument marked with __attribute__((nonnull)). ๐ซ
See CWE-476: NULL Pointer Dereference at https://cwe.mitre.org/data/definitions/476.html. ๐ฅ
-Wno-analyzer-null-dereference ๐
Needs -fanalyzer. Disable it with -Wno-analyzer-null-dereference. ๐
This one warns on paths where a value known to be NULL gets dereferenced. Big yikes. ๐
See CWE-476: NULL Pointer Dereference at https://cwe.mitre.org/data/definitions/476.html. ๐ง
-Wno-analyzer-putenv-of-auto-var โญ
This warning requires -fanalyzer, which enables it; use -Wno-analyzer-putenv-of-auto-var to disable it. ๐ธ
Okay so this bit is all about putenv ๐ธ It warns about paths through the code where a call to putenv gets handed a pointer to an automatic variable or an on-stack buffer. Big nope, bestie ๐
โโ๏ธ
See POS34-C. The rule is "Do not call putenv() with a pointer to an automatic variable as the argument" ๐
(https://wiki.sei.cmu.edu/confluence/x/6NYxBQ).
-Wno-analyzer-shift-count-negativeโ ๐ฅ This one needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-shift-count-negative. It flags paths where a shift is attempted with a negative count. It's the sibling of the-Wshift-count-negativewarning from the C/C++ front ends, except it works by analyzing interprocedural paths instead of just reading the syntax tree. Lowkey, the analyzer doesn't prioritise finding these, so false negatives are more likely than with other warnings ๐-Wno-analyzer-shift-count-overflowโ โจ Also requires-fanalyzer, which enables it, and you disable it with-Wno-analyzer-shift-count-overflow. This one catches paths where a shift count is greater than or equal to the precision of the operand's type. It's the analyzer's take on-Wshift-count-overflowfrom the C/C++ front ends, again built on interprocedural paths rather than the syntax tree. Same deal as before: the analyzer doesn't prioritise these, so false negatives are more likely compared to other warnings ๐-Wno-analyzer-stale-setjmp-bufferโ ๐ฆ Needs-fanalyzer, which enables it, and-Wno-analyzer-stale-setjmp-bufferturns it off. It warns for paths wherelongjmpis called to rewind to ajmp_buftied to asetjmpcall in a function that has already returned. Whensetjmprecords a rewind location on ajmp_buf, it records the stack frame, and that frame becomes invalid once the function containing thesetjmpcall returns. Trying to rewind to it withlongjmpmeans referencing a stack frame that doesn't exist anymore, which will likely lead to a crash (or worse) ๐ญ-Wno-analyzer-tainted-allocation-sizeโ ๐ง Requires-fanalyzer, which enables it, and you can silence it with-Wno-analyzer-tainted-allocation-size. It warns for paths where a value an attacker could control gets used as the size of an allocation without being sanitised, so an attacker could inject a massively huge allocation and cause a denial of service attack. See CWE-789: Memory Allocation with Excessive Size Value (https://cwe.mitre.org/data/definitions/789.html) ๐ซถ-Wno-analyzer-tainted-assertionโ ๐ This one also needs-fanalyzer, and-Wno-analyzer-tainted-assertionis how you disable it. It warns for paths where an attacker-controllable value gets used as part of a condition without being sanitised first, and that condition guards a call to a function marked with thenoreturnattribute (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 such cases:
- when assertion-checking is enabled: an attacker could trigger a denial of service by injecting an assertion failure
- when assertion-checking is disabled, such as by defining
NDEBUG, an attacker could inject data that subverts the process, since it presumably violates a precondition that is being assumed by the code.
Note that when assertion-checking is disabled, the assertions are typically removed by the preprocessor before the analyzer has a chance to "see" them, so this diagnostic can only generate warnings on builds in which assertion-checking is enabled ๐
For the purpose of this warning, any function marked with the noreturn attribute counts as a possible assertion failure handler, including __builtin_unreachable. These functions are sometimes removed by the optimizer before the analyzer "sees" them, so optimization should be disabled when you're trying to trigger this diagnostic.
See CWE-617: Reachable Assertion (https://cwe.mitre.org/data/definitions/617.html).
The warning can also report problematic constructions such as:
switch (some_tainted_value) {
case 0:
/* [...etc; various valid cases omitted...] */
break;
default:
__builtin_unreachable (); /* BUG: attacker can trigger this */
}
despite the above not being an assertion failure, strictly speaking ๐
-Wno-analyzer-tainted-array-indexโ ๐ Needs-fanalyzer, which enables it, and-Wno-analyzer-tainted-array-indexswitches it off. It warns for paths where an attacker-controllable value is used as the index of an array access without being sanitised, 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โ โญ Requires-fanalyzer, which enables it, and you disable it with-Wno-analyzer-tainted-divisor. It warns for paths where an attacker-controllable value is used as the divisor in a division or modulus operation without being sanitised, so 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โ ๐ธ Needs-fanalyzer, which enables it, and-Wno-analyzer-tainted-offsetturns it off. It warns for paths where an attacker-controllable value is used as a pointer offset without being sanitised, 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โ ๐ Requires-fanalyzer, which enables it, and you can silence it with-Wno-analyzer-tainted-size. It warns for paths where an attacker-controllable value is used as the size of an operation such asmemsetwithout being sanitised, 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-strtokโ ๐ฅ Needs-fanalyzer, which enables it, and-Wno-analyzer-undefined-behavior-strtokdisables it. It warns for paths where a call is made tostrtokthat has undefined behavior. Specifically, passing NULL as the first parameter for the initial call tostrtokwithin a process is undefined behavior, so watch out ๐-Wno-analyzer-unsafe-call-within-signal-handlerโ ๐ฆ Requires-fanalyzer, which enables it, and you turn it off with-Wno-analyzer-unsafe-call-within-signal-handler. It warns for paths where a function known to be async-signal-unsafe (likefprintf) 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-fanalyzer, which enables it, and-Wno-analyzer-use-after-freeis your off switch. It warns for paths where a pointer is used after a deallocator has been called on it, eitherfreeor a deallocator referenced by themallocattribute. 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, which enables it, and you disable it with-Wno-analyzer-use-of-pointer-in-stale-stack-frame. It warns for paths where a pointer is dereferenced that points to a variable in a stale stack frame.-Wno-analyzer-va-arg-type-mismatchโ ๐ Needs-fanalyzer, which enables it, and-Wno-analyzer-va-arg-type-mismatchturns it off. It warns for interprocedural paths where the analyzer detects an attempt to useva_argto extract a value passed to a variadic call, but the type used doesn't match the type of 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-fanalyzer, which enables it, and you can silence it with-Wno-analyzer-va-list-exhausted. It warns for interprocedural paths where the analyzer detects an attempt to useva_argto access the next value passed to a variadic call, but every value in theva_listhas already been consumed. See CWE-685: Function Call With Incorrect Number of Arguments (https://cwe.mitre.org/data/definitions/685.html) ๐ธ-Wno-analyzer-va-list-leakโ โจ Needs-fanalyzer, which enables it, and-Wno-analyzer-va-list-leakdisables it. It warns for interprocedural paths where the analyzer detects thatva_startorva_copyhas been called on ava_listwithout a corresponding call tova_end.-Wno-analyzer-va-list-use-after-va-endโ ๐ง Requires-fanalyzer, which enables it, and you turn it off with-Wno-analyzer-va-list-use-after-va-end. It warns for interprocedural paths where the analyzer detects an attempt to use ava_listafterva_endhas been called on it.va_list.-Wno-analyzer-write-to-constโ ๐ This warning requires-fanalyzer, which enables it; use-Wno-analyzer-write-to-constto disable it.
Okay bestie, this one's the analyzer side-eyeing your writes ๐. It warns about paths where it spots an attempt to write through a pointer to a const object ๐ The catch is that the analyzer doesn't prioritize hunting these down, so false negatives (missed issues) are more likely than with other warnings ๐
-Wno-analyzer-write-to-string-literal๐ธ This one needs-fanalyzerto be on, since that's what turns it on. Use-Wno-analyzer-write-to-string-literalto switch it off. It warns about paths where the analyzer sees a write through a pointer to a string literal. Same deal as before: it doesn't prioritize these paths, so false negatives are more likely than with other warnings.-Wno-analyzer-use-of-uninitialized-value๐ฆ Also requires-fanalyzer(which enables it), 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 already has hardcoded knowledge about how these memory-management functions behave ๐ง โจ
alloca- The built-in functions
__builtin_alloc,__builtin_alloc_with_align,__builtin_calloc,__builtin_free,__builtin_malloc,__builtin_memcpy,__builtin_memcpy_chk,__builtin_memset,__builtin_memset_chk,__builtin_realloc,__builtin_stack_restore, and__builtin_stack_save callocfreemallocmemsetoperator deleteoperator delete []operator newoperator new []reallocstrdupstrndup
It also knows about these file descriptor functions ๐ซถ
openclosecreatdup,dup2anddup3isattypipe, andpipe2readwritesocket,bind,listen,accept, andconnect
And these <stdio.h> stream functions ๐
- The built-in functions
__builtin_fprintf,__builtin_fprintf_unlocked,__builtin_fputc,__builtin_fputc_unlocked,__builtin_fputs,__builtin_fputs_unlocked,__builtin_fwrite,__builtin_fwrite_unlocked,__builtin_printf,__builtin_printf_unlocked,__builtin_putc,__builtin_putchar,__builtin_putchar_unlocked,__builtin_putc_unlocked,__builtin_puts,__builtin_puts_unlocked,__builtin_vfprintf, and__builtin_vprintf fopenfcloseferrorfgetsfgets_unlockedfilenofreadgetcgetcharfprintfprintffwrite
And finally, a grab bag of other functions ๐
- The built-in functions
__builtin_expect,__builtin_expect_with_probability,__builtin_strchr,__builtin_strcpy,__builtin_strcpy_chk,__builtin_strlen,__builtin_va_copy, and__builtin_va_start - The GNU extensions
erroranderror_at_line getpasslongjmpputenvsetjmpsiglongjmpsignalsigsetjmpstrcatstrchrstrlen
Also, various functions with an __analyzer_ prefix have special meaning to the analyzer. Those are described in the GCC Internals manual ๐๐ฅ
Pertinent parameters for controlling the exploration (aka how far the analyzer digs) are:
--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, so let's get into it ๐
-fanalyzer-call-summariesโ This simplifies interprocedural analysis (checking across function calls) by computing the effect of certain calls, instead of exploring every path through the function from the callsite to each possible return. ๐ง
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 running just the named checker, and enables it ๐ฏ-fanalyzer-debug-text-art-headingsโ This one's for analyzer developers ๐ ๏ธ When 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's a feasible control flow path for each diagnostic it emits, meaning the conditions that hold aren't mutually exclusive. Diagnostics where no feasible path can be found get rejected. This filtering can be suppressed with-fno-analyzer-feasibility, which is handy for debugging issues in this code ๐-fanalyzer-fine-grainedโ Developer-only again ๐ 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โ For analyzer developers: if multiple diagnostics have been detected as duplicates of each other, it emits a note when reporting the best diagnostic. That note gives the number of additional diagnostics the deduplication logic suppressed โจ-fanalyzer-show-events-in-system-headersโ By default the analyzer emits simplified diagnostic paths by hiding events fully located within a system header. With-fanalyzer-show-events-in-system-headers, those events are no longer suppressed ๐-fno-analyzer-state-mergeโ Developer territory ๐งโ๐ป 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-merge, that merging gets suppressed, which is useful for debugging state-handling issues.-fno-analyzer-state-purgeโ Also for developers ๐ซ By default the analyzer purges aspects of state at a program point that seem no longer relevant. For example, that's the values of locals that aren't accessed later in the function and aren't relevant to leak analysis. With-fno-analyzer-state-purge, that purging gets suppressed, for debugging state-handling issues.-fno-analyzer-suppress-followupsโ Developer-only ๐งช By default the analyzer stops exploring an execution path after hitting certain diagnostics, so it doesn't spam a cascade of follow-up diagnostics. The diagnostics that end analysis along a path are:-Wanalyzer-null-argument-Wanalyzer-null-dereference-Wanalyzer-use-after-free-Wanalyzer-use-of-pointer-in-stale-stack-frame-Wanalyzer-use-of-uninitialized-value
With -fno-analyzer-suppress-followups, the analyzer keeps exploring those paths even after such diagnostics. That can help with debugging the analyzer, or with microbenchmarks for detecting undefined behavior.
-fanalyzer-transitivityโ Turns on transitivity of constraints within the analyzer ๐-fno-analyzer-undo-inliningโ Developer-only ๐งฉ-fanalyzerruns relatively late compared to other code analysis tools, and some optimizations may have already been applied. In particular, function inlining may have happened, which can leave the interprocedural execution paths with function frames that don't match the original source code. By default the analyzer tries to reconstruct the original function frames and emits events showing the inlined calls. With-fno-analyzer-undo-inlining, that attempt to reconstruct the original frame information gets disabled, which can help when debugging analyzer issues.-fanalyzer-verbose-edgesโ For analyzer developers. It enables more verbose, lower-level detail in the descriptions of control flow within diagnostic paths ๐-fanalyzer-verbose-state-changesโ Also for analyzer developers. It enables more verbose, lower-level detail in the descriptions of state machine events within diagnostic paths ๐-fanalyzer-verbosity=levelโ This 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 for a diagnostic. For example, for a double-"free" diagnostic, both calls tofreewill be shown.1โ Same as the previous level, but it also shows events for the entry to each function.2โ Same as the previous level, but it also shows control flow events 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โ For analyzer developers. It 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 that's 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" sit in relation to the program source ๐-fdump-analyzer-exploded-nodes-2โ Dumps a textual representation of the "exploded graph" tofile.eg.txt๐-fdump-analyzer-exploded-nodes-3โ okay so this one dumps a textual version of the "exploded graph" with one dump file per node, namedfile.eg-id.txt๐. Heads up bestie, that's usually a huge pile of files ๐ญ๐.-fdump-analyzer-exploded-pathsโ dumps a textual "exploded path" for every diagnostic, intofile.idx.kind.epath.txtโจ.-fdump-analyzer-feasibilityโ this spills the tea on the analyzer's search for feasible paths ๐. It's written so you can view it with GraphViz, intofile.*.fg.dot,file.*.tg.dot, andfile.*.fpath.txt๐ฆ.-fdump-analyzer-infinite-loopโ internal details about the analyzer's hunt for infinite loops ๐. Also GraphViz-friendly, saved asfile.*.infinite-loop.dot๐.-fdump-analyzer-jsonโ a compressed JSON version of analyzer internals, saved tofile.analyzer.json.gz๐. The precise format is subject to change, so don't build your whole life on it ๐ .-fdump-analyzer-state-purgeโ same vibe as-fdump-analyzer-supergraph, a GraphViz-ready supergraph ๐ง, but this one is annotated with what state gets purged at each node ๐ซถ. It's written tofile.state-purge.dot.-fdump-analyzer-supergraphโ gives you GraphViz dumps of the "supergraph" infile.supergraph.dotandfile.supergraph-eg.dot๐. These show every control flow graph in the program, with interprocedural edges for calls and returns ๐. The second dump also has annotations showing nodes in the "exploded graph" and the diagnostics attached to them โจ.-fdump-analyzer-untrackedโ emits custom warnings packed with internal details, made for analyzer developers only ๐.
โจ Options for Debugging Your Program โจ
Okay so if you want GCC to hand your debugger all the info, bestie, you really only need to add -g to your other options ๐. Some debug formats can hang out together (like DWARF with CTF) as long as you turn each one on explicitly with its own command line option ๐ธ.
You're allowed to use -g with -O, and it's honestly kinda iconic ๐
. Optimized code gets a little sneaky though ๐ป: some variables you declared may not exist at all, flow of control might briefly 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 may run in different places since they got moved out of loops ๐. Still, you can debug optimized output, which makes the optimizer totally reasonable for programs that might have bugs ๐ฅ.
If you aren't using some other optimization option, consider using -Og with -g ๐ง. With no -O option at all, some compiler passes that collect debugging-friendly info don't run, so -Og may give you a better debugging experience ๐ฆ.
-gโ this makes debugging info in the operating system's native format (stabs, COFF, XCOFF, or DWARF), and GDB can work with it ๐.- On most systems that use stabs,
-gturns on extra info that only GDB can use ๐. That makes debugging way better in GDB, but other debuggers might crash or refuse to read the program ๐ญ. If you want to be 100% certain whether the extra info gets generated, use-gvms(see below).
- On most systems that use stabs,
-ggdbโ debugging info made 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 if at all possible โจ.-gdwarf,-gdwarf-versionโ debugging info in DWARF format, if that's supported ๐ฆ. Theversioncan be 2, 3, 4 or 5. The default is 5 for most targets, except VxWorks, TPF and Darwin / macOS (which default to version 2) and AIX (which defaults to version 4) ๐.- With DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables ๐ง.
- Version 4 may require GDB 7.0 and
-fvar-tracking-assignmentsto get the maximum benefit ๐ . Version 5 requires 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)still have 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 ๐.-gctf,-gctflevelโ requests CTF debug info, and theleveldecides how much CTF info you get ๐ธ. If you use-gctfwithout a value forlevel, 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. That includes callsite info, but not 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 the Alpha/VMS debug format (if that's supported) ๐. It's the format used by DEBUG on Alpha/VMS systems ๐.-gcodeviewโ produces debugging info in the CodeView debug format (if that's supported) ๐ช. It's the format Microsoft Visual C++ uses on Windows ๐.-glevel,-ggdblevel,-gvmslevelโ requests debugging info and useslevelto decide how much info you get ๐ซถ. The default level is 2 ๐ .- Level 0 produces no debug info at all, so
-g0negates-g๐. - Level 1 produces minimal info, enough for making backtraces in parts of the program you don't plan to debug ๐. That includes descriptions of functions and external variables, plus line number tables, but no info about local variables ๐.
- Level 3 includes extra info, such as all the macro definitions present in the program ๐. Some debuggers support macro expansion when you use
-g3โจ. - If you use multiple
-goptions, with or without level numbers, the last one is the one that takes effect โญ. -gdwarfdoes not accept a concatenated debug level, to avoid confusion with-gdwarf-level. Instead, use an additional-gleveloption to change the debug level for DWARF ๐ฆ.
- Level 0 produces no debug info at all, so
-fno-eliminate-unused-debug-symbolsโ by default, no debug info is produced for symbols that aren't actually used ๐งน. Use this if you want debug info for all symbols ๐ธ.-femit-class-debug-alwaysโ instead of emitting 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 the way GCC normally emits class debug info, because it increases the size of debugging info by as much as a factor of two ๐ญ.-fno-merge-debug-stringsโ tells the linker not to merge together strings in the debugging info that are identical across different object files ๐งต. Merging isn't supported by all assemblers or linkers ๐. It decreases the size of the debug info in the output file, at the cost of longer link processing time ๐ข. Merging is enabled by default โจ.-fdebug-prefix-map=old=newโ when compiling files in directoryold, debugging info describes them as if they lived in directorynewinstead ๐บ๏ธ. This is handy for swapping a build-time path for an install-time path in the debug info ๐ซถ. You can also turn an absolute path into a relative one by using.fornew๐ฆ. This can give you more reproducible builds, which are location independent, but you might need an extra command to tell GDB where to find the source files ๐. See also-ffile-prefix-mapand-fcanon-prefix-map๐.-fvar-trackingโ runs the variable tracking pass, which computes where variables are stored at each position in the code ๐ง . Better debug info gets generated afterwards (if the debugging info format supports it) ๐.- It's enabled by default when compiling with optimization (
-Os,-O,-O2, ...), debugging info (-g), and a debug info format that supports it ๐.
- It's enabled by default when compiling with optimization (
-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-4is recommended alongside it ๐ .- It can be enabled even if 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.dwoextension ๐ฆ. This lets the build system avoid linking files with debug info ๐งต. To be useful, it requires a debugger that can read.dwofiles ๐.-gdwarf32,-gdwarf64โ if DWARF debug info is enabled,-gdwarf32selects the 32-bit DWARF format and-gdwarf64selects the 64-bit one ๐ธ. The default is target specific, but on most targets it's-gdwarf32๐.- The 32-bit format is smaller, but it can't support more than 2GiB of debug info in any of the DWARF debug info sections ๐ญ.
- The 64-bit format allows larger debug info, but it might not be well supported by all consumers yet ๐ข.
-gdescribe-diesโ adds description attributes to some DWARF DIEs that have no name attribute ๐ง. Examples are artificial variables, external references and call site parameter DIEs โจ.-gpubnamesโ generates the DWARF ".debug_pubnames" and ".debug_pubtypes" sections ๐.-ggnu-pubnamesโ okay bestie, this one makes the.debug_pubnamesand.debug_pubtypessections in a format that can get turned into a GDB index ๐ง. Heads up though, 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_typessection instead of living in.debug_info๐ฆ It's more efficient to stick them in a separate comdat section, since the linker can then remove duplicates โจ But not every DWARF consumer supports.debug_typesyet, and on some objects it makes the debugging 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 debugging info ๐ They're joined with spaces, separating them from each other and from the compiler version. It's on by default! Also see-frecord-gcc-switchesif you want another way to store compiler options in the object file ๐ธ-gstrict-dwarfโ no extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ โโ๏ธ On most targets, using non-conflicting extensions from later standard versions is totally allowed.-gno-strict-dwarfโ the opposite energy: you are allowed to use extensions from a later DWARF standard version than the one picked with-gdwarf-version๐-gas-loc-supportโ tells the compiler that your assembler supports.locdirectives, so it can use them to generate DWARF2+ line number tables ๐ง This is usually the move, because assembler-generated line-number tables are way more compact than the ones the compiler makes itself ๐ It's enabled by default if the assembler was found to support these directives when GCC was configured โจ-gno-as-loc-supportโ forces GCC to generate DWARF2+ line number tables internally, if they're going to be generated at all ๐-gas-locview-supportโ tells the compiler your assembler supports "view" assignment and reset assertion checking in.locdirectives ๐ฆ It's enabled by default if the assembler was found to support them at configure time ๐-gno-as-locview-supportโ forces GCC to assign view numbers internally, if you've explicitly asked for-gvariable-location-views๐ซถ-gcolumn-info,-gno-column-infoโ puts location column information into your DWARF debugging info, not just file and line ๐ It's on by default, bestie ๐-gstatement-frontiers,-gno-statement-frontiersโ GCC drops markers in its internal representation at the start of statements and keeps them roughly in place through the whole compile ๐ง It uses them to guide where theis_stmtmarkers show up in the line number table. This is 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 by the line number table ๐ฅ This lets debug info consumers inspect state at certain points in the program, even when no instructions tied to those source locations exist there ๐ If the assembler can't handle view numbers in line number tables, the compiler has to emit the line number table itself, which makes things a little less compact ๐ญ The augmented tables and location lists are fully backward-compatible, so older consumers can read them, but they also won't get any benefit from them ๐ซ
This is enabled by default at the normal level of DWARF 2 debug output, as long as the assembler supports it, -fvar-tracking-assignments is enabled, and -gstrict-dwarf isn't. If the assembler doesn't support it, the option can still be on, but it forces GCC to output internal line number tables. And if -ginternal-reset-location-views isn't enabled too, that will most certainly lead to silently mismatching location views ๐จ
There's also a proposed representation for view numbers that isn't 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 a reference implementation of the proposed representation. Debug info consumers aren't expected to support this extended format, so they'd be unable to decode location lists that use it ๐
-ginternal-reset-location-views,-gno-internal-reset-location-viewsโ this one tries to figure out which location views can be dropped from the location view lists โ๏ธ It needs the compiler to have very accurate insn length estimates, which isn't always the case. It may 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" ๐ It's only enabled on ports that define a reliable estimation function ๐-ginline-points,-gno-inline-pointsโ generates extended debug info for inlined functions ๐ง Location view tracking markers get inserted at inlined entry points, so address and view numbers can be computed and output in the debug info. This can be turned on 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 you don't give a type, the default depends on what the assembler and linker can do. type can benone(don't compress debug sections) orzlib(use zlib compression in ELF gABI format). If the linker can't write 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 drastically shrinks your debug info, but there can be a big loss in the type info the debugger gets ๐ฌ For a less aggressive option, check out-femit-struct-debug-reduced, and for more detailed control, see-femit-struct-debug-detailed. This option only works 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. The exception is if the struct is a template or is defined in a system header ๐งธ This significantly shrinks your debug info, with some potential loss in type info. For a more aggressive option, see-femit-struct-debug-baseonly, and for more detailed control, see-femit-struct-debug-detailed. Only works with DWARF debug output ๐-femit-struct-debug-detailed[=spec-list]โ lets you pick which struct-like types the compiler generates debug info for โจ The goal is to cut down on duplicate struct debug info across 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 this syntax: [dir:|ind:][ord:|gen:](any|sys|base|none)
The optional first word limits the spec 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 a member. Indirect uses come through pointers to structs. In other words, when using an incomplete struct is valid, the use is indirect. For example: struct one direct; struct two * indirect;
The optional second word limits the spec to ordinary structs (ord:) or generic structs (gen:). Generic structs are a little complicated to explain ๐ค In C++, these are non-explicit specializations of template classes, or non-template classes within the above. Other programming languages have generics too, but -femit-struct-debug-detailed doesn't implement them yet ๐
The third word says which source files the structs should get debug info for. none and any have their normal meanings. base means the base of the name of the file where the type declaration appears has to match the base of the name of the main compilation file. In practice, that means when you compile foo.c, debug info gets generated for types declared in that file and in foo.h, but not in other header files ๐ sys means those types that satisfy base, or that are declared in system or compiler headers, count too.
You may need to experiment to find the best settings for your app ๐งช The default is -femit-struct-debug-detailed=all. This option only works with DWARF debug output ๐
-fno-dwarf2-cfi-asmโ emits DWARF unwind info as a compiler-generated.eh_framesection, instead of using the GAS.cfi_*directives ๐ง-fno-eliminate-unused-debug-typesโ okay so, normally when producing DWARF output, GCC skips debug symbol output for types that are nowhere used in the source file being compiled ๐ โโ๏ธ Sometimes you actually want debug info for every type declared in the compilation unit, even unused ones. For example, if you want to cast a value to a type in the debugger that's declared but never used in your program ๐ฎ More often, though, this just wastes a ton of space ๐
โจ Options That Control Optimization โจ
These options control various sorts of optimizations ๐ฅ They're the glow-up knobs, bestie ๐
๐ธ The Vibe Without Any -O Flag ๐ธ
Okay so, bestie, if you don't pass any optimization flag at all, the compiler's whole thing is keeping compilation cheap and making debugging act the way you expect ๐. Statements are basically their own little islands ๐๏ธ. Stop at a breakpoint between statements and you can change a variable's value or move the program counter to any other statement in the function, and you'll get exactly what the source code promised โจ.
Turning on optimization flags is a total glow-up ๐ . The compiler tries to boost performance and/or shrink the code size, but the tradeoff is longer compile times and maybe a harder time debugging ๐ญ.
The compiler optimizes based on what it knows about your program ๐ง . If you compile multiple files at once into a single output file, it can use info from all of those files when it works on each one ๐ซถ.
Not every optimization has its own flag ๐. This section only covers the ones that do.
Most optimizations are completely switched off at -O0, or whenever no -O level is set on the command line, even if you add individual optimization flags yourself ๐. And -Og skips plenty of optimization passes too ๐ฆ.
Depending on the target and how GCC was configured, the set of optimizations enabled at each -O level might be a little different from what's listed here ๐. If you want the exact lineup for your setup, invoke GCC with -Q --help=optimizers and it'll spill every enabled optimization at each level ๐.
๐ -O and -O1 ๐
-O,-O1โ Optimize! This one takes a bit more time to compile, and a lot more memory for a big function ๐ง .
With -O, the compiler tries to shrink the code and speed up execution ๐โโ๏ธ, but it skips any optimization that would take forever to compile โจ.
-O turns on the following 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 -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 ๐
-O2โ Optimize even more! GCC does nearly every supported optimization that doesn't involve a space-speed tradeoff ๐ฅ. Compared to-O, it makes compilation slower but gives you faster generated code ๐.
-O2 turns on all optimization flags specified by -O1. It also turns on the following optimization flags:
-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-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
Heads up, bestie ๐ซฃ: please read the warning under-fgcseabout turning on-O2for programs that use computed gotos. It's important!
NOTE ๐ : On Ubuntu 8.10 and later,-D_FORTIFY_SOURCE=2is set by default. On Ubuntu 24.04 and later,-D_FORTIFY_SOURCE=3is set by default instead. Either one kicks in when-Ois set to 2 or higher and adds extra compile-time and run-time checks for several libc functions ๐ก๏ธ. Want it gone? Specify either-U_FORTIFY_SOURCEor-D_FORTIFY_SOURCE=0๐ โโ๏ธ.
NOTE ๐: On Debian 13 and Ubuntu 24.04 and later,-D_TIME_BITS=64together with-D_FILE_OFFSET_BITS=64is set by default on the 32bit architectures armel, armhf, hppa, m68k, mips, mipsel, powerpc and sh4 ๐ง.
๐ฅ -O3 ๐ฅ
-O3โ Optimize yet more!-O3turns on everything-O2does, plus the following optimization flags ๐:
-fgcse-after-reload -fipa-cp-clone -floop-interchange
-floop-unroll-and-jam -fpeel-loops -fpredictive-commoning
-fsplit-loops -fsplit-paths -ftree-loop-distribution
-ftree-partial-pre -funswitch-loops -fvect-cost-model=dynamic
-fversion-loops-for-strides
๐ -O0 ๐
-O0โ Reduce compilation time and make debugging produce the expected results โจ. This is the default! ๐
๐ง -Os ๐ง
-Osโ Optimize for size ๐ฆ.-Osenables all-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, tells the compiler to tune for code size instead of execution speed, and runs extra optimizations designed to shrink the code ๐ธ.
๐ -Ofast ๐
-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-racesand the Fortran-specific-fstack-arrays(unless-fmax-stack-var-sizeis specified), and-fno-protect-parens. It turns off-fsemantic-interposition๐.
๐ฆ -Og ๐ฆ
-Ogโ Optimize the debugging experience ๐.-Ogshould be your go-to level for the standard edit-compile-debug cycle ๐. You get 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 do nothing. Otherwise, -Og enables all -O1 optimization flags except the ones that might 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 ๐ซง
-Ozโ Optimize aggressively for size rather than speed ๐ฐ. This may increase the number of instructions executed if those instructions take fewer bytes to encode.-Ozbehaves similarly to-Os, including turning on most-O2optimizations โจ.
If you use multiple -O options, with or without level numbers, the last one is the one that counts ๐. Periodt ๐
.
๐ -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 the form you'll typically use, but you can figure out the other one by either removing no- or adding it ๐.
The following options control specific optimizations. They're either turned on by -O options or related to ones that are. You only need these in the rare cases where you want to "fine-tune" which optimizations get performed ๐.
-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 ๐.
-ffp-contract=styleโ-ffp-contract=offdisables floating-point expression contraction ๐ซ.-ffp-contract=fastenables it, such as forming fused multiply-add operations if the target has native support for them ๐ฅ.-ffp-contract=onenables contraction if the language standard allows it ๐โโ๏ธ. This is implemented for C and C++, where it allows 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 ๐ฆ. That 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 ๐.
Heads up: -fno-omit-frame-pointer doesn't guarantee the frame pointer gets used in every function. Several targets always omit it in leaf functions ๐.
Enabled by default at -O1 and higher ๐.
-foptimize-sibling-callsโ Optimizes sibling and tail recursive calls ๐. Enabled at levels-O2,-O3,-Osโจ.-foptimize-strlenโ Optimizes various standard C string functions (e.g."strlen","strchr"or"strcpy") and their_FORTIFY_SOURCEcounterparts into faster 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 to need looping ๐งต. This is most useful along with-ffreestandingand-fno-builtin๐.
In some circumstances it lets the compiler generate code that takes advantage of known alignment and length multipliers. But even then, it may be less efficient than optimized runtime implementations, and it can grow the code so much that a less performant but shared implementation runs faster thanks to better use of code caches ๐ญ. This option is disabled by default ๐.
-fno-inlineโ โจ Okay bestie, this one says don't inline anything unless it's marked with thealways_inlineattribute ๐ โโ๏ธ. It's the default when you're not optimizing ๐ . If you want one specific function to sit out, tag it with thenoinlineattribute ๐ซถ.-finline-small-functionsโ ๐ฆ The compiler copies a function into its callers when the body is smaller than the code it'd take to call it, so the whole program actually gets smaller ๐. The compiler makes this call heuristically ๐ง , and it applies to every function, even the ones that aren't declaredinline. Enabled at levels-O2,-O3,-Os๐ฅ.-findirect-inliningโ ๐ This one inlines indirect calls that become known at compile time because of earlier inlining. It only does anything when inlining is already switched on by-finline-functionsor-finline-small-functions๐. Enabled at levels-O2,-O3,-Osโจ.-finline-functionsโ ๐ Every function is up for inlining, even the ones not declaredinline๐ . The compiler heuristically picks which ones are worth it. If every call to a given function gets inlined and that function isstatic, it normally won't be emitted as its own assembler code ๐ง. Enabled at levels-O2,-O3,-Os, and also turned on by-fprofile-useand-fauto-profile๐.-finline-functions-called-onceโ ๐ Anystaticfunction that's called exactly once gets inlined into its caller, even if it isn't markedinline๐ซถ. Once that call is inlined, the function isn't output as assembler code on its own ๐. Enabled at levels-O1,-O2,-O3, and-Os, but not-Og๐ โโ๏ธ.-fearly-inliningโ โญ Functions markedalways_inline, plus functions whose body looks smaller than the call overhead, get inlined early, before-fprofile-generateinstrumentation and the real inlining pass ๐ธ. That makes profiling way cheaper and usually makes inlining faster for programs with big chains of nested wrapper functions ๐ญ. Enabled by default ๐.-fipa-sraโ ๐ฅ Interprocedural scalar replacement of aggregates ๐ง, removal of unused parameters ๐๏ธ, and swapping parameters passed by reference for parameters passed by value ๐. Enabled at levels-O2,-O3,-Osโจ.-finline-limit=nโ ๐ This gives you a coarse dial for how big a function can be and still get inlined.nis the size measured in pseudo instructions ๐. Inlining is really controlled by a bunch of parameters you can set one at a time with--param name=value. The-finline-limit=noption sets a couple of them for you:max-inline-insns-singleis set ton/2.max-inline-insns-autois set ton/2.
Check out the individual inlining parameters below for their docs and defaults ๐.
Heads up: there may be no value of -finline-limit that gives you the default behavior ๐.
Also, a "pseudo instruction" is just an abstract measure of how big a function is ๐งโโ๏ธ. It has nothing to do with counting assembly instructions, so what it means can change from one release to another ๐.
-fno-keep-inline-dllexportโ ๐ฆ This is the more fine-grained cousin of-fkeep-inline-functions. It only touches functions declared with thedllexportattribute ordeclspec๐ .-fkeep-inline-functionsโ ๐ In C,staticfunctions declaredinlinestill get emitted into the object file, even if they were inlined into every single caller ๐ฆ. This doesn't change functions using theextern inlineextension in GNU C90 ๐ โโ๏ธ. In C++, it emits any and all inline functions into the object file ๐.-fkeep-static-functionsโ ๐ซถ Emitsstaticfunctions into the object file even if nothing ever uses them ๐งน.-fkeep-static-constsโ โจ Emits variables declaredstatic constwhen optimization is off, even if nothing references them ๐. GCC turns this on by default ๐. If you want the compiler to check whether a variable is referenced no matter what optimization level you're on, 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 builds if the assembler and linker support it ๐. To stop it, use-fno-merge-constants๐ โโ๏ธ. Enabled at levels-O1,-O2,-O3,-Osโจ.-fmerge-all-constantsโ ๐ญ Tries to merge identical constants and identical variables ๐งจ. It implies-fmerge-constants, and on top of that it looks at things like constant initialized arrays and initialized constant variables with integral or floating-point types ๐งฑ.
Danger zone ๐: C and C++ require each variable to have its own distinct location, including multiple instances of the same variable in recursive calls. Using this option results in non-conforming behavior, so it's not a vibe ๐.
-fmodulo-schedโ ๐ Runs swing modulo scheduling right before the first scheduling pass ๐ข. It looks at the innermost loops and reorders their instructions by overlapping different iterations ๐ซ.-fmodulo-sched-allow-regmovesโ ๐ This goes harder with SMS-based modulo scheduling and lets register moves happen ๐ . Turning it on deletes certain anti-dependence edges, which triggers reg-move generation based on life-range analysis ๐ง . It only works if-fmodulo-schedis also on ๐ซถ.-fno-branch-count-regโ ๐ โโ๏ธ Turns off the pass that hunts for chances to use "decrement and branch" instructions on a count register ๐ข. Those replace the usual sequence of decrementing a register, comparing it to zero, then branching on the result ๐. This only matters on architectures that have those instructions, like x86, PowerPC, IA-64, and S/390 ๐ฅ๏ธ. Heads up:-fno-branch-count-regdoesn't remove decrement and branch instructions that other optimization passes already put into the stream ๐โโ๏ธ. The default is-fbranch-count-regat-O1and higher, except for-Ogโจ.-fno-function-cseโ ๐ง Don't stash function addresses in registers. Instead, every instruction that calls a constant function spells out the function's address explicitly ๐. This makes the code less efficient ๐ฉ, but some strange hacks that mess with the assembler output can get confused by the optimizations you'd get without this flag ๐. The default is-ffunction-cse๐.-fno-zero-initialized-in-bssโ ๐งธ If the target has a BSS section, GCC normally tosses zero-initialized variables in there, which can save space ๐ฆ. This option turns that off ๐ซ. Why? Some programs explicitly count on variables landing in the data section ๐ซฃ, like when the executable needs to find the start of that section or makes assumptions based on it ๐บ๏ธ. The default is-fzero-initialized-in-bss๐.-fthread-jumpsโ ๐งต Checks whether a jump lands on a spot where another comparison that the first one already covers shows up ๐. If it does, the first branch gets redirected to the second branch's destination or to the spot right after it ๐โโ๏ธ. Which one depends on whether the condition is known to be true or false ๐ฏ. Enabled at levels-O1,-O2,-O3,-Osโจ.-fsplit-wide-typesโ ๐งฉ When a type takes up multiple registers, likelong longon a 32-bit system, this splits those registers apart and allocates them independently ๐ฐ. That usually makes better code for those types ๐, but debugging can get harder ๐ตโ๐ซ. Enabled at levels-O1,-O2,-O3,-Os๐ .-fsplit-wide-types-earlyโ โฐ Fully splits wide types early instead of waiting until very late ๐ . It does nothing unless-fsplit-wide-typesis on ๐ โโ๏ธ. This one is the default on some targets ๐.-fcse-follow-jumpsโ ๐ฆ During common subexpression elimination (CSE), this scans through jump instructions when nothing else reaches the jump's target ๐. Like, when CSE hits anifwith anelseclause, it follows the jump when the tested condition is false ๐ช. Enabled at levels-O2,-O3,-Osโจ.-fcse-skip-blocksโ ๐ท Kind of like-fcse-follow-jumps, but this one follows jumps that conditionally skip over blocks ๐. When CSE sees a simpleifwith no else clause, it follows the jump around the body of theif๐. Enabled at levels-O2,-O3,-Os๐ฅ.-frerun-cse-after-loopโ ๐ Re-runs common subexpression elimination after loop optimizations are done ๐ข. Enabled at levels-O2,-O3,-Os๐.-fgcseโ ๐ Performs a global common subexpression elimination pass ๐ง . This pass also does global constant and copy propagation ๐.
Note ๐
: If your program uses computed gotos (a GCC extension), you might get better run-time performance by disabling the global CSE pass with -fno-gcse on the command line ๐๏ธ.
Enabled at levels -O2, -O3, -Os โจ.
-fgcse-lmโ ๐ When this is on, global CSE tries to move loads that only get killed by stores into themselves ๐งฒ. That lets a loop with a load/store sequence turn into a load outside the loop and a copy/store inside it ๐ซถ. Enabled by default whenever-fgcseis on ๐.-fgcse-smโ ๐ When this is on, a store motion pass runs after global CSE ๐ฆ. It tries to move stores out of loops ๐โโ๏ธ. Combined with-fgcse-lm, loops with a load/store sequence can become a load before the loop and a store after it ๐. Not enabled at any optimization level ๐.-fgcse-lasโ ๐งน When this is on, the global CSE pass gets rid of redundant loads that come right after stores to the same memory location ๐งผ. That covers both partial and full redundancies ๐ฏ. Not enabled at any optimization level ๐.-fgcse-after-reloadโ okay so when this is turned on, a redundant load elimination pass runs after reload ๐ . Its whole job is cleaning up redundant spilling โจ- Enabled by
-O3,-fprofile-useand-fauto-profile๐
- Enabled by
-faggressive-loop-optimizationsโ the loop optimizer gets bold and uses language constraints to figure out bounds for how many times a loop runs ๐ฅ Those bounds steer loop unrolling, peeling and loop exit test optimizations- It assumes your loop code never triggers undefined behavior, like signed integer overflows or out-of-bound array accesses ๐
- This option is enabled by default ๐
-funconstrained-commonsโ tells the compiler that variables in common blocks (e.g. Fortran) might get overridden later with longer trailing arrays ๐ฆ Because of that, certain optimizations that rely on knowing the array bounds get switched off-fcrossjumpingโ performs the cross-jumping transformation, which unifies equivalent code and saves code size ๐ธ Heads up, bestie: the result may or may not run better than without it ๐คทโโ๏ธ- Enabled at levels
-O2,-O3,-Os
- Enabled at levels
-fauto-inc-decโ combines increments or decrements of addresses with memory accesses โจ This pass is always skipped on architectures that don't have instructions to support it- Enabled by default at
-O1and higher on architectures that support this ๐
- Enabled by default at
-fdceโ performs dead code elimination (DCE) on RTL ๐งน- Enabled by default at
-O1and higher
- Enabled by default at
-fdseโ performs dead store elimination (DSE) on RTL ๐- Enabled by default at
-O1and higher
- Enabled by default at
-fif-conversionโ attempts to turn conditional jumps into branch-less equivalents ๐ฆ That includes conditional moves, min, max, set flags and abs instructions, plus some tricks you can pull off with standard arithmetic ๐ง Whether conditional execution gets used on chips that have it is controlled by-fif-conversion2- Enabled at levels
-O1,-O2,-O3,-Os, but not with-Og๐ โโ๏ธ
- Enabled at levels
-fif-conversion2โ uses conditional execution (where available) to turn conditional jumps into branch-less equivalents ๐ซถ- Enabled at levels
-O1,-O2,-O3,-Os, but not with-Og
- Enabled at levels
-fdeclone-ctor-dtorโ the C++ ABI wants multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that callsoperator deleteafterwards ๐ญ For a hierarchy with virtual bases, the base and complete variants are clones, meaning two copies of the function. With this option, those base and complete variants become thunks that call a common implementation ๐- Enabled by
-Os
- Enabled by
-fdelete-null-pointer-checksโ assumes programs can't safely dereference null pointers, and that no code or data element lives at address zero ๐ This option turns on simple constant folding optimizations at all optimization levels. On top of that, other optimization passes in GCC use this flag to control global dataflow analyses that axe useless null pointer checks ๐ช Those analyses assume 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- > ๐ Note however that in some environments this assumption is not true. Use
-fno-delete-null-pointer-checksto disable this optimization for programs that depend on that behavior. - This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR and MSP430, this option is completely disabled ๐
- Passes that use the dataflow information are enabled independently at different optimization levels ๐
- > ๐ Note however that in some environments this assumption is not true. Use
-fdevirtualizeโ attempts to convert calls to virtual functions into direct calls ๐ฆ This happens both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp)- Enabled at levels
-O2,-O3,-Os
- Enabled at levels
-fdevirtualize-speculativelyโ attempts to convert calls to virtual functions into speculative direct calls ๐ง Based on analysis of the type inheritance graph, GCC figures out the set of likely targets for a given call. If the set is small, preferably of size 1, the call gets changed into a conditional that decides between a direct and an indirect call ๐ 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โ streams extra information needed for aggressive devirtualization when the link-time optimizer runs in local transformation mode ๐ธ This gives you more devirtualization, but it significantly increases the size of the streamed data ๐ค For that reason it's disabled by default-fexpensive-optimizationsโ performs a bunch of minor optimizations that are relatively expensive ๐ธ- Enabled at levels
-O2,-O3,-Os
- Enabled at levels
-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
- Enabled for Alpha, AArch64, LoongArch, PowerPC, RISC-V, SPARC, h83000 and x86 at levels
-fno-lifetime-dseโ in C++, an object's value is only affected by changes within its lifetime ๐ฆ When the constructor begins, the object has an indeterminate value, and any changes made during its lifetime are dead once the object is destroyed. Normally dead store elimination takes advantage of this. If your code relies on the value of the object storage sticking around beyond the object's lifetime, use this flag to turn that optimization off ๐ โโ๏ธ- To keep stores made before the constructor starts (e.g. because your
operator newclears the object storage) but still treat the object as dead after the destructor, use-flifetime-dse=1๐ - The default behavior can be explicitly selected with
-flifetime-dse=2โจ -flifetime-dse=0is equivalent to-fno-lifetime-dse๐ซถ
- To keep stores made before the constructor starts (e.g. because your
-flive-range-shrinkageโ attempts to decrease register pressure through register live range shrinkage ๐ท This is helpful for fast processors with small or moderate-size register sets ๐๏ธ-fira-algorithm=algorithmโ picks the coloring algorithm for the integrated register allocator ๐จ Thealgorithmargument can bepriority, which means Chow's priority coloring, orCB, which means Chaitin-Briggs coloring- Chaitin-Briggs coloring isn't implemented for every architecture, but for targets that do support it, it's the default because it generates better code ๐
-fira-region=regionโ picks the regions used by the integrated register allocator ๐บ๏ธ Theregionargument 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 setmixedโ uses all loops except loops with small register pressure as the regions โจ This usually gives the best results in most cases and for most architectures, and it's enabled by default when compiling with optimization for speed (-O,-O2, ...) ๐ฅoneโ uses all functions as a single region ๐ฐ This typically results in the smallest code size, and it's enabled by default for-Osor-O0
-fira-hoist-pressureโ uses IRA to evaluate register pressure in the code hoisting pass when deciding whether to hoist expressions ๐งบ This usually results in smaller code, but it can slow the compiler down ๐ข- This option is enabled at level
-Osfor all targets
- This option is enabled at level
-fira-loop-pressureโ uses IRA to evaluate register pressure in loops when deciding whether to move loop invariants ๐ This usually results in faster and smaller code on machines with large register files (>= 32 registers), but it can slow the compiler down ๐- This option is enabled at level
-O3for some targets
- This option is enabled at level
-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 function stack frames end up larger ๐ฆ-flra-rematโ enables CFG-sensitive rematerialization in LRA ๐ Instead of loading the values of spilled pseudos, LRA tries to rematerialize (recalculate) values when that's profitable- Enabled at levels
-O2,-O3,-Os
- Enabled at levels
-fdelayed-branchโ if the target machine supports it, GCC tries to reorder instructions to take advantage of instruction slots available after delayed branch instructions ๐งฉ- Enabled at levels
-O1,-O2,-O3,-Os, but not at-Og
- Enabled at levels
-fschedule-insnsโ if the target machine supports it, GCC tries to reorder instructions to eliminate execution stalls caused by required data being unavailable ๐ฅฑ This helps machines with slow floating point or memory load instructions, by letting other instructions issue until the result of the load or floating-point instruction is actually needed ๐ซ- Enabled at levels
-O2,-O3
- Enabled at levels
-fschedule-insns2โ similar to-fschedule-insns, but it requests an additional pass of instruction scheduling after register allocation is done ๐ This is especially useful on machines with a relatively small number of registers, where memory load instructions take more than one cycle ๐- Enabled at levels
-O2,-O3,-Os
- Enabled at levels
-fno-sched-interblockโ disables instruction scheduling across basic blocks ๐ซ This is normally enabled when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐ซ-fno-sched-specโ disables speculative motion of non-load instructions ๐ โโ๏ธ This is normally enabled when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher โจ-fsched-pressureโ okay bestie, this one turns on register-pressure-aware scheduling ๐ before register allocation even starts ๐ธ. It only slaps when scheduling before register allocation is on, so think-fschedule-insnsor-O2or higher. The payoff is that your code can get better and smaller ๐ฆ because it stops register pressure from climbing past the number of available hard registers, which means fewer annoying spills during register allocation ๐ฅน.-fsched-spec-loadโ lowkey a spicy one โจ. It lets some load instructions get speculatively moved around. Same rule as before: this only makes sense when scheduling happens before register allocation, so-fschedule-insnsor-O2or higher ๐ซถ.-fsched-spec-load-dangerousโ the more chaotic sibling ๐. This one allows speculative motion of more load instructions. Same vibe check applies, though: it only makes sense when scheduling before register allocation, aka-fschedule-insnsor-O2or higher ๐ฅ.-fsched-stalled-insns,-fsched-stalled-insns=nโ this one controls how many stalled instructions can be yeeted early from the stalled queue into the ready list during the second scheduling pass ๐.-fno-sched-stalled-insnsmeans no instructions get moved early at all ๐ โโ๏ธ.-fsched-stalled-insns=0means there's no limit on how many queued instructions can jump the line โจ. And if you just write-fsched-stalled-insnswith no value, it's the same as-fsched-stalled-insns=1๐.-fsched-stalled-insns-dep,-fsched-stalled-insns-dep=nโ this one decides how many instruction groups (cycles) get checked for a dependency on a stalled instruction that's a candidate for early removal from the queue ๐ง. It only matters 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๐. Writing-fsched-stalled-insns-depwith no value is the same as-fsched-stalled-insns-dep=1๐.-fsched2-use-superblocksโ when scheduling after register allocation, this one uses superblock scheduling ๐ฆ. The glow-up is that instructions can move across basic block boundaries, which gives you faster schedules โจ. BUT it's experimental ๐, because not every machine description GCC uses models the CPU closely enough to avoid unreliable results. This only makes sense when scheduling after register allocation, so-fschedule-insns2or-O2or higher.
โ ๏ธ bestie, read that experimental part twice. Some machine descriptions don't model the CPU closely enough, so results can be unreliable. Proceed with caution ๐ญ.
-fsched-group-heuristicโ turns on the group heuristic in the scheduler ๐ธ. It favors the instruction that belongs to a schedule group. This one is on by default whenever scheduling is enabled, so-fschedule-insns,-fschedule-insns2, or-O2or higher ๐.-fsched-critical-path-heuristicโ enables the critical-path heuristic, which favors instructions sitting on the critical path ๐ฃ๏ธ. Also on by default whenever scheduling is enabled, aka-fschedule-insns,-fschedule-insns2, or-O2or higher ๐.-fsched-spec-insn-heuristicโ enables the speculative instruction heuristic, which favors speculative instructions with greater dependency weakness ๐ง . Enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐.-fsched-rank-heuristicโ enables the rank heuristic, which favors instructions belonging to a basic block with greater size or frequency ๐. On by default whenever scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐.-fsched-last-insn-heuristicโ enables the last-instruction heuristic ๐ซง. It favors the instruction that's less dependent on the last instruction scheduled. It's on by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐.-fsched-dep-count-heuristicโ enables the dependent-count heuristic, which favors the instruction that has more instructions depending on it ๐งโโ๏ธ. Enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐.-freschedule-modulo-scheduled-loopsโ here's the tea โ: modulo scheduling happens before traditional scheduling ๐ซ. If a loop gets modulo scheduled, later scheduling passes might change its schedule ๐. Use this option to control that behavior ๐ .-fselective-schedulingโ schedules instructions using the selective scheduling algorithm ๐ฆ. It runs instead of the first scheduler pass โจ.-fselective-scheduling2โ same energy, but this one schedules instructions with the selective scheduling algorithm and runs instead of the second scheduler pass ๐.-fsel-sched-pipeliningโ turns on software pipelining of innermost loops during selective scheduling ๐. Heads up, though: it does absolutely nothing unless-fselective-schedulingor-fselective-scheduling2is on ๐.-fsel-sched-pipelining-outer-loopsโ when pipelining loops during selective scheduling, this one also pipelines the outer loops ๐ช. It has no effect unless-fsel-sched-pipeliningis turned on ๐ฅฒ.-fsemantic-interpositionโ okay, this one is a lot, so get comfy ๐งธ. Some object formats, like ELF, let the dynamic linker interpose symbols. So 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 later ๐ฉ. That's actually useful, like if you want to swap in a debugging version of a memory allocation function ๐ ๏ธ, but it's expensive when it comes to 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) ๐ซถ. Same deal for variables: the constructor of the variable will be the same ๐ธ. This flag has no effect on functions explicitly declared inline, where interposition is never allowed to change semantics โจ, and it also does nothing for symbols explicitly declared weak ๐
โโ๏ธ.
-fshrink-wrapโ emits function prologues only before the parts of the function that actually need them, instead of at the very top ๐. It's enabled by default at-Oand higher ๐ฅ.-fshrink-wrap-separateโ shrink-wraps the prologue and epilogue parts separately, so those parts only run when they're needed ๐. It's on by default, but it does nothing unless-fshrink-wrapis also on and the target supports this ๐ซ .-fcaller-savesโ this one lets values live in registers that get clobbered by function calls ๐งบ. To make that work, it emits extra instructions to save and restore those registers around the calls ๐ . The allocation only happens when it seems to result in better code โจ. It's always on by default on certain machines, usually the ones that don't have call-preserved registers to use instead ๐ฆ. Enabled at levels-O2,-O3,-Os๐.-fcombine-stack-adjustmentsโ tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐งฉ. Enabled by default at-O1and higher ๐.-fipa-raโ uses caller-save registers for allocation if those registers aren't used by any called function ๐ง . The payoff is that they don't have to be saved and restored 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 ๐ฆ. It's enabled at-O2,-O3,-Os, however it gets switched off 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, even if that makes the program slower ๐ข. This one implies setting thelarge-stack-frameparameter to100and thelarge-stack-frame-growthparameter to400๐งฎ.-ftree-reassocโ performs reassociation on trees ๐ณ. Enabled by default at-O1and higher ๐.-fcode-hoistingโ performs code hoisting ๐ช. It tries to move the evaluation of expressions that get executed 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โ performs full redundancy elimination (FRE) on trees ๐งฝ. Here's the difference between FRE and PRE ๐ค: FRE only considers expressions computed on all paths leading to the redundant computation. That makes it faster than PRE, though it exposes fewer redundancies ๐. Enabled by default at-O1and higher ๐ธ.-ftree-phipropโ performs hoisting of loads from conditional pointers on trees ๐ช. This pass is enabled by default at-O1and higher โจ.-fhoist-adjacent-loadsโ speculatively hoists loads from both branches of an if-then-else, but only if the loads are from adjacent locations in the same structure AND the target architecture has a conditional move instruction ๐ญ. Enabled by default at-O2and higher ๐ .-ftree-copy-propโ performs copy propagation on trees ๐. This pass gets rid of unnecessary copy operations, which is so iconic ๐. Enabled by default at-O1and higher ๐ซถ.-fipa-pure-constโ discovers which functions are pure or constant ๐. Enabled by default at-O1and higher ๐.-fipa-referenceโ discovers which static variables do not escape the compilation unit ๐ช. Enabled by default at-O1and higher ๐ฆ.-fipa-reference-addressableโ discovers read-only, write-only, and non-addressable static variables ๐ต๏ธโโ๏ธ. Enabled by default at-O1and higher ๐.-fipa-stack-alignmentโ reduces stack alignment on call sites if possible ๐. Enabled by default ๐.-fipa-ptaโ performs interprocedural pointer analysis, plus interprocedural modification and reference analysis ๐ฌ. Fair warning, though ๐จ: this can cause excessive memory and compile-time usage on large compilation units. It is not enabled by default at any optimization level ๐.
๐จ bestie, -fipa-pta can absolutely eat your memory and your compile time on big compilation units. It's off by default at every optimization level, so you have to ask for it on purpose ๐ญ๐.
-fipa-profileโ okay so this one does 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 ๐ฏ. Then the cold functions and the loop-less parts of run-once functions get optimized for size ๐. It's enabled by default at-O1and higher ๐ .-fipa-modrefโ this is giving interprocedural mod/ref analysis ๐ต๏ธโโ๏ธ It looks at the side effects of functions (the memory locations they modify or reference) so the compiler can optimize better across the function call boundary ๐ฆ. Enabled by default at-O1and higher ๐ธ.-fipa-cpโ interprocedural constant propagation ๐ The compiler checks when the values passed into functions are constants and optimizes around that ๐ง . This can seriously boost performance if your app is passing constants into functions ๐ฅ. Enabled by default at-O2,-Osand-O3, and also turned on by-fprofile-useand-fauto-profile๐.-fipa-cp-cloneโ function cloning to make interprocedural constant propagation even stronger ๐ฏโโ๏ธ When it's on, the compiler clones externally visible functions that can be called with constant arguments ๐งฌ. Because it can make multiple copies of functions, it may significantly increase code size (see--param ipa-cp-unit-growth=value) ๐ฆ. Enabled by default at-O3, and also by-fprofile-useand-fauto-profile๐.-fipa-bit-cpโ when enabled, you get interprocedural bitwise constant propagation ๐ Enabled by default at-O2, and by-fprofile-useand-fauto-profileโจ. It requires that-fipa-cpis enabled ๐ซถ.-fipa-vrpโ when enabled, the compiler 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 reduces code size, but it can disturb unwind stacks because it swaps a function out for an equivalent one with a different name ๐ฌ. It works better with link-time optimization turned on ๐.
Okay so this is similar to the Gold Linker's ICF optimization, but GCC's ICF works on different levels, so the optimizations aren't the same. There are equivalences only GCC finds and equivalences only Gold finds ๐ค.
Enabled by default at -O2 and -Os ๐.
-flive-patching=level โ tells GCC to control its optimizations so the output is suitable for live-patching ๐ฉนโจ
If an optimization uses a function's body (or info pulled from that body) to change another function, that other function is called an impacted function of the first one. If a function gets patched, its impacted functions should get patched too ๐จ. Which functions count as impacted is decided by the 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 is used to optimize its direct or indirect callers, and so on ๐งฉ.
Usually, the more IPA optimizations you have on, the more impacted functions each function has. 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 are enabled, which covers 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 ๐.
โ ๏ธ-flive-patching=inline-clonedisables these optimization flags:-fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment -fipa-modref
inline-only-staticโ only inlining of static functions is enabled ๐ง. So when you patch a static function, all its callers are impacted and need patching as well ๐ซ .
On top of everything -flive-patching=inline-clone disables, -flive-patching=inline-only-static also disables these extra flags: -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 ๐ฅ.
๐ซ-flive-patchingis not supported with link-time optimization (-flto). Do not mix these two, bestie ๐.
-fisolate-erroneous-paths-dereferenceโ this one 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โ similar vibe, but this one detects paths where a null value gets used in a way forbidden by a "returns_nonnull" or "nonnull" attribute ๐ . It isolates those paths and turns the statement into a trap ๐ชค. This is not currently enabled, but it may be enabled by-O2in the future ๐ฎ.-ftree-sinkโ performs forward store motion on trees ๐. Enabled by default at-O1and higher ๐.-ftree-bit-ccpโ sparse conditional bit constant propagation on trees, plus it propagates pointer alignment information ๐. This pass only operates on local scalar variables ๐. It's enabled by default at-O1and higher, except for-Og๐. It requires that-ftree-ccpis enabled ๐ซถ.-ftree-ccpโ sparse conditional constant propagation (CCP) on trees ๐. It only operates on local scalar variables and is 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 ๐งฉ. It's 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 it 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 in this pass can be limited with themax-tail-merge-comparisonsparameter and themax-tail-merge-iterationsparameter โฑ๏ธ.-ftree-dceโ dead code elimination (DCE) on trees ๐๏ธ Enabled by default at-O1and higher โจ.-ftree-builtin-call-dceโ conditional dead code elimination (DCE) for calls to built-in functions that may set "errno" but are otherwise free of side effects ๐งน. Enabled by default at-O2and higher, if-Osis not also specified ๐ซ .-ffinite-loopsโ the compiler assumes that a loop with an exit will eventually take the exit and won't loop forever ๐โ . This lets it remove loops that otherwise have no side effects, without treating eventual endless looping as a side effect ๐๏ธ.
This option is enabled by default at -O2 for C++ with -std=c++11 or higher ๐
.
-ftree-dominator-optsโ a bunch of simple scalar cleanups (constant/copy propagation, redundancy elimination, range propagation and expression simplification) based on a dominator tree traversal ๐ณ. It also does jump threading (to reduce jumps to jumps) ๐ฆ. Enabled by default at-O1and higher ๐ธ.-ftree-dseโ dead store elimination (DSE) on trees ๐. A dead store is a store into a memory location that gets overwritten later by another store with no loads in between, so the earlier store can be deleted ๐๏ธ. Enabled by default at-O1and higher ๐.-ftree-chโ loop header copying on trees ๐. This is great because it increases the effectiveness of code motion optimizations, and it also saves one jump ๐ซถ. Enabled by default at-O1and higher. It's not enabled for-Os, since it usually increases code size ๐.-ftree-loop-optimizeโ 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 use this code transformation, GCC has to be configured with--with-islto enable the Graphite loop transformation infrastructure ๐ ๏ธ.-fgraphite-identityโ enables the identity transformation for Graphite ๐ช. For every SCoP, it generates the polyhedral representation and transforms it back to GIMPLE ๐. You can use-fgraphite-identityto check the costs or benefits of the GIMPLE -> GRAPHITE -> GIMPLE transformation ๐ง. Some minimal optimizations are also performed by the isl code generator, like index splitting and dead code elimination in loops โจ.-floop-nest-optimizeโ turns on the isl based loop nest optimizer ๐. It's a generic loop nest optimizer based on the Pluto optimization algorithms, and it calculates a loop structure optimized for data locality and parallelism ๐ง ๐. 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 to not contain loop carried dependences, without checking whether parallelizing them is profitable ๐ซฃ. Yikes, bestie, that's a bold move ๐ .-ftree-coalesce-varsโ okay so when GCC is turning the program out of SSA form, it tries to cut down on copying by merging versions of different user-defined variables, not just compiler temporaries ๐ง. Heads up though, this can seriously 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 on, and it does very little otherwise ๐ .-ftree-loop-if-convertโ this one tries to turn conditional jumps in the innermost loops into branch-less equivalents ๐ฆ. The whole point is to strip control flow out of those loops so the vectorization pass can handle them better โจ. It's enabled by default if vectorization is enabled.-ftree-loop-distributionโ loop distribution, bestie ๐ธ. It can improve cache performance on big loop bodies and open the door for more loop optimizations, like parallelization or vectorization, to take place ๐ฅ. This flag is enabled by default at-O3, and also by-fprofile-useand-fauto-profile. Here's the glow-up:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
becomes
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
-ftree-loop-distribute-patternsโ this one distributes loops that can be code generated as calls to a library ๐. It's enabled by default at-O2and higher, and by-fprofile-useand-fauto-profile. This pass splits up the initialization loops and generates a call tomemsetzero ๐งธ. Check out the vibe:
DO I = 1, N
A(I) = 0
B(I) = A(I) + I
ENDDO
becomes
DO I = 1, N
A(I) = 0
ENDDO
DO I = 1, N
B(I) = A(I) + I
ENDDO
The initialization loop gets transformed into a call to memset zero. This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile โจ.
-floop-interchangeโ loop interchange outside of graphite, and it's giving performance ๐ฅ. It can improve cache performance on loop nests and let further loop optimizations, like vectorization, take place ๐. Look at this swap:
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];
is transformed to
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 flag is enabled by default at -O3. It is also enabled 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 ๐. It's enabled by default at-O3, and also by-fprofile-useand-fauto-profile.-ftree-loop-imโ loop invariant motion on trees, and it's lowkey picky about what it moves ๐. It only moves invariants that are hard to handle at the RTL level, like function calls or 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 loop unswitching can use just trivial invariantness analysis ๐ฆ. The pass also includes store motion ๐.-ftree-loop-ivcanonโ creates a canonical counter for the number of iterations in loops where figuring out that number needs complicated analysis ๐ธ. Later optimizations can then determine the number easily. It's especially useful in connection with unrolling ๐ซถ.-ftree-scev-cpropโ performs final value replacement ๐ . If a variable gets modified in a loop in such a way that its value on exit can be determined using only its initial value and the number of loop iterations, 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. It's enabled by default at-O1and higher.-fivoptsโ performs induction variable optimizations on trees, which means strength reduction, induction variable merging, and induction variable elimination ๐ฅ.-ftree-parallelize-loops=nโ parallelizes loops by splitting their iteration space to run innthreads ๐งต. This is only possible for loops whose iterations are independent and can be arbitrarily reordered ๐. It's only profitable on multiprocessor machines, for loops that are CPU-intensive, rather than constrained by things like memory bandwidth ๐. This option implies-pthread, so it's only supported on targets that have support for-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 for scalars so structures don't get committed to memory too early ๐ฆ. It's enabled by default at-O1and higher, except for-Og.-fstore-mergingโ merges narrow stores to consecutive memory addresses ๐. It squishes contiguous stores of immediate values, narrower than a word, into fewer wider stores, which cuts down on the number of instructions ๐ . This is 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 on, which leads to better RTL generation ๐. This is enabled by default at-O1and higher.-ftree-slsrโ performs straight-line strength reduction on trees ๐ธ. It recognizes related expressions involving multiplications and replaces them with less expensive calculations when possible ๐. This is enabled by default at-O1and higher.-ftree-vectorizeโ performs vectorization on trees, and it's the main character of this group ๐. This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified ๐.-ftree-loop-vectorizeโ performs loop vectorization on trees ๐. It's enabled by default at-O2, and also by-ftree-vectorize,-fprofile-use, and-fauto-profile๐ซถ.-ftree-slp-vectorizeโ performs basic block vectorization on trees ๐ฅ. It's enabled by default at-O2, and also by-ftree-vectorize,-fprofile-use, and-fauto-profile๐.
-ftrivial-auto-var-init=choiceโ okay this one is a whole security glow-up ๐ก๏ธ๐ . It initializes automatic variables with either a pattern or zeroes, so your program is more secure and predictable by preventing uninitialized memory from being disclosed and used ๐ญ. GCC still considers an automatic variable without an explicit initializer to be uninitialized, and-Wuninitializedand-Wanalyzer-use-of-uninitialized-valuewill still report warnings on those variables. The compiler will also still optimize as if the variable were uninitialized ๐. With this option, GCC will also initialize any padding of automatic variables that have structure or union types to zeroes โจ. However, the current implementation cannot initialize automatic variables declared between the controlling expression and the firstcaseof a"switch"statement, so use-Wtrivial-auto-var-initto report all such cases ๐.
The three values of choice are:
uninitializeddoesn't initialize any automatic variables. This is C and C++'s default ๐ฅฑ.patterninitializes 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 useful program semantics ๐. The current value is a byte-repeatable pattern with byte0xFE. The values used for pattern initialization might be changed in the future ๐.zeroinitializes automatic variables with zeroes ๐ซง.
The default is uninitialized.
Note that the initializer values, whether zero or pattern, refer to data representation (in memory or machine registers), rather than to their interpretation as numerical values. This distinction may be important in languages that support types with biases or implicit multipliers, and with extensions such as 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 these representations stand for values in that range. And even if they do, the interpretation of the value held by the variable will depend 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. In other words, zero initialization will not convert to the representation for "false", even if 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 is that (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โ okay bestie, this one lets you tweak the cost model the vectorizer uses ๐ฆ Themodelargument has to beunlimited,dynamic,cheaporvery-cheap. Withunlimited, the vectorized code path is just assumed to be profitable, no questions asked ๐ Withdynamic, a runtime check guards the vectorized path so it only switches on for iteration counts that will likely run faster than the original scalar loop โจ
The cheap model is the cautious one ๐งธ It turns off vectorization for loops where it would be cost prohibitive, like when it needs runtime checks for data dependence or alignment, but otherwise it's exactly the same as dynamic. Then there's very-cheap, the most picky of the bunch ๐ It only allows vectorization if the vector code would entirely replace the scalar code being vectorized. For example, if each iteration of a vectorized loop can only handle exactly four iterations of the scalar loop, very-cheap only says yes if the scalar iteration count is known to be a multiple of four.
The default cost model depends on your other optimization flags and is either dynamic or cheap ๐ธ
-fsimd-cost-model=modelโ same vibe, but for loops marked with the OpenMPsimddirective ๐ Themodelargument should beunlimited,dynamicorcheap(novery-cheaphere, sorry bestie ๐ซถ). All of them mean the same thing as in-fvect-cost-model, and by default, the cost model you set with-fvect-cost-modelis the one that gets used ๐-ftree-vrpโ this one does Value Range Propagation on trees ๐ It's kinda like constant propagation, except instead of tracking single values, it tracks ranges of values. That lets the optimizers delete stuff like array bound checks and null pointer checks when they're unnecessary ๐ญ It's on by default at-O2and higher. Heads up, though: null pointer check elimination only happens if-fdelete-null-pointer-checksis turned on ๐-fsplit-pathsโ splits paths that lead to loop backedges โ๏ธ This can level up your dead code elimination and common subexpression elimination. It's enabled by default at-O3and above ๐-fsplit-ivs-in-unrollerโ when a loop gets unrolled, this lets the compiler express the values of induction variables in later iterations using the value from the first iteration ๐ง That breaks up long dependency chains, which helps the scheduling passes run more efficiently.
A combo of -fweb and CSE is often enough to get the same effect. Still, it's not reliable when the loop body is more complicated than a single basic block ๐ And on some architectures, it doesn't work at all because of restrictions in the CSE pass.
This optimization is enabled by default โจ
-fvariable-expansion-in-unrollerโ with this one, the compiler makes multiple copies of some local variables when it unrolls a loop, which can give you superior code ๐
It's enabled by default for PowerPC targets, but disabled by default everywhere else ๐
-fpartial-inliningโ inlines parts of functions ๐ฆ This only does anything if inlining itself is turned on with-finline-functionsor-finline-small-functions.
Enabled at levels -O2, -O3, -Os ๐
-fpredictive-commoningโ performs predictive commoning, which means reusing computations (especially memory loads and stores) that were done in previous iterations of loops ๐
This 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 improve loops that access large arrays ๐ฅ
Fair warning: this may generate better or worse code, because the results are highly dependent on how the loops are structured in your source code ๐
Disabled at level -Os ๐
-fno-printf-return-valueโ do not substitute constants for the known return value of formatted output functions like"sprintf","snprintf","vsprintf"and"vsnprintf"(but not"printf"or"fprintf") ๐ง This substitution lets GCC optimize or even eliminate branches based on the known return value of these functions, as long as the arguments are either constant or have values 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,-fno-peephole2โ these disable any machine-specific peephole optimizations ๐ง The difference between them 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โ do not guess branch probabilities using heuristics ๐
GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (-fprofile-arcs). These heuristics are based on the control flow graph. If some branch probabilities are specified by "__builtin_expect", 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 messy, so sometimes it's helpful to turn the heuristics off 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โ 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โ picks the algorithm used for basic block reordering ๐ Thealgorithmargument can besimple, which doesn't increase code size (except sometimes because of secondary effects like alignment), orstc, the "software trace cache" algorithm.stctries to put all the often executed code together, which minimizes the number of branches executed, but it does this by making extra copies of code ๐ฅ
The default is simple at levels -O1, -Os, and stc at levels -O2, -O3 โจ
-freorder-blocks-and-partitionโ on top of reordering basic blocks, this one partitions hot and cold basic blocks into separate sections of the assembly and.ofiles, to improve paging and cache locality performance ๐ง
This optimization gets turned off automatically in a few situations: when there's exception handling or unwind tables (on targets using setjump/longjump or a target specific scheme), for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections ๐ญ When -fsplit-stack is used, this option isn't enabled by default (to avoid linker errors), but you can still enable it explicitly if you're using a working linker ๐ซถ
Enabled for x86 at levels -O2, -O3, -Os ๐
-freorder-functionsโ reorders functions in the object file to improve code locality ๐ It's done using special subsections:".text.hot"for the most frequently executed functions, and".text.unlikely"for the unlikely executed ones. The linker does the reordering, so the object file format must 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โ lets the compiler assume the strictest aliasing rules that apply to the language being compiled ๐ฅ For C (and C++), this turns on optimizations based on the type of expressions. In particular, 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;
}
Similarly, accessing something by taking its 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-aliasingare applied across function boundaries ๐ง Keep in mind that 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 it's only effective 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โ okay bestie, this one lines up the start of your functions ๐ It nudges them to the next power-of-two boundary that's greater than or equal to n, skipping up tom-1bytes ๐ฆ The goal is that at least the first m bytes of the function can be fetched by the CPU without crossing an n-byte alignment boundary ๐ง It's a code performance optimization โจ and alignment gets ignored for functions considered cold ๐ง If you need alignment on every function, reach for-fmin-function-alignmentinstead ๐- If m isn't specified, it defaults to n ๐
- Examples ๐ธ:
-falign-functions=32aligns functions to the next 32-byte boundary-falign-functions=24aligns to the next 32-byte boundary only if that can be done by skipping 23 bytes or less-falign-functions=32:7aligns to the next 32-byte boundary only if that can be done by skipping 6 bytes or less
- The second n2:m2 pair gives you a secondary alignment ๐
-falign-functions=64:7:32:3aligns to the next 64-byte boundary if that can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if that can be done by skipping 2 bytes or less - If m2 isn't specified, it defaults to n2 ๐
- Some assemblers only support this flag when n is a power of two. In that case, the value gets rounded up ๐
-fno-align-functionsand-falign-functions=1are equivalent and mean functions are not aligned ๐- If n isn't specified or is zero, the compiler uses a machine-dependent default ๐ค The max allowed n value is
65536 - Enabled at levels
-O2,-O3โจ
-flimit-function-alignmentโ if this one's on, the compiler tries not to overalign functions when it doesn't need to ๐ โโ๏ธ It asks the assembler to align by the amount set with-falign-functions, but it won't skip more bytes than the size of the function itself ๐-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 work just like the ones for-falign-functions๐-fno-align-labelsand-falign-labels=1are equivalent and mean labels aren't aligned ๐ซถ- If
-falign-loopsor-falign-jumpsapply and are greater than this value, their values get used instead ๐ - If n isn't specified or is zero, a machine-dependent default is used. That default is very likely
1, which means no alignment ๐ The max allowed n value is65536 - Enabled at levels
-O2,-O3๐ฅ
- If
-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 the dummy padding instructions ๐ญ It's a code performance optimization, and alignment is ignored for loops considered cold ๐ง- If
-falign-labelsis greater than this value, its value is used instead ๐ - The parameters are analogous to the
-falign-functionsoption ๐-fno-align-loopsand-falign-loops=1are equivalent and mean loops are not aligned ๐ The max allowed n value is65536 - If n isn't specified or is zero, a machine-dependent default is used ๐ค
- Enabled at levels
-O2,-O3โจ
- If
-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 that case, no dummy operations need to be executed ๐ It's a code performance optimization, and alignment is ignored for jumps considered cold ๐ง- If
-falign-labelsis greater than this value, its value is used instead ๐ - The parameters are analogous to the
-falign-functionsoption ๐-fno-align-jumpsand-falign-jumps=1are equivalent and mean that loops are not aligned ๐ - If n isn't specified or is zero, a machine-dependent default is used. The max allowed n value is
65536 - Enabled at levels
-O2,-O3๐ธ
- If
-fmin-function-alignmentโ sets the minimal alignment of functions to the next power-of-two boundary greater than or equal to n ๐ Unlike-falign-functions, this applies to all functions, even the cold ones ๐ฅถ It also isn't affected by-flimit-function-alignment๐-fno-allocation-dceโ don't remove unused C++ allocations during dead code elimination ๐๏ธ-fallow-store-data-racesโ lets the compiler do optimizations that might introduce new data races on stores, without proving the variable can't be accessed by other threads at the same time ๐งต It doesn't affect optimization of local data ๐ It's only safe to use if you know global data won't be accessed by multiple threads ๐ฌ- Examples include hoisting, or if-conversions that might cause a value already in memory to be written back with that same value. That 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 to enable vectorization โก
- Enabled at level
-Ofast๐ฅ
-funit-at-a-timeโ only here for compatibility reasons ๐ฐ๏ธ It has no effect.-fno-unit-at-a-time, on the other hand, implies-fno-toplevel-reorderand-fno-section-anchors๐ Enabled by default ๐-fno-toplevel-reorderโ don't reorder top-level functions, variables, and"asm"statements. Output them in the same order they appear in the input file ๐ When this is used, unreferenced static variables are not removed ๐ โโ๏ธ It's meant to support existing code that relies on a particular ordering. For new code, attributes are the better move when possible ๐ก-ftoplevel-reorderis the default at-O1and higher, and also at-O0if-fsection-anchorsis explicitly requested โจ-fno-toplevel-reorderalso implies-fno-section-anchors๐ซถ
-funreachable-trapsโ turns calls to"__builtin_unreachable"into traps, instead of using them for optimization ๐จ This also affects any such calls the compiler generates implicitly ๐ It has the same effect as-fsanitize=unreachable -fsanitize-trap=unreachable, but it doesn't change the values of those options. If-fsanitize=unreachableis enabled, that option takes priority over this one ๐ Enabled by default at-O0and-Og๐-fwebโ constructs webs, the way they're commonly used for register allocation, and gives each web its own pseudo register ๐ธ๏ธ That lets the register allocation pass work on pseudos directly, and it also strengthens several other passes like CSE, the loop optimizer, and the trivial dead code remover ๐ช The catch: it can make debugging impossible, since variables no longer stay in a "home register" ๐ญ Enabled by default with-funroll-loops๐-fwhole-programโ assumes the current compilation unit is the whole program being compiled ๐ All public functions and variables, exceptmainand anything merged by the attribute"externally_visible", become static functions. That means the interprocedural optimizers can go harder on them โก- With
-flto, this option has limited use ๐ฅฑ In most cases, the precise list of symbols used or exported from the binary is already known from the resolution info the linker plugin passes to the link-time optimizer ๐งฉ - It's still useful if no linker plugin is used, or during the incremental link step when the final code is produced (with
-flto -flinker-output=nolto-rel) ๐ฆ
- With
-flto[=n]โ runs the standard link-time optimizer ๐ง When it's invoked with source code, it generates GIMPLE (one of GCC's internal representations) and writes it into special ELF sections in the object file โจ When the object files get linked together, all the function bodies are read back from those ELF sections and instantiated as if they had been part of the same translation unit ๐ฆ
To use link-time optimization, -flto and your optimization options should be specified at compile time and during the final link ๐ซถ It's recommended that you compile all the files in the same link with the same options, and 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 save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o ๐ The final invocation reads that GIMPLE bytecode from foo.o and bar.o, merges the two files into a single internal image, and compiles the result as usual. Since both files get merged into one image, all the interprocedural analyses and optimizations in GCC work across the two files as if they were a single one ๐ฅ So, for example, the inliner can inline functions in bar.o into functions in foo.o, and vice-versa ๐
Another (simpler) way to enable link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
That generates bytecode for foo.c and bar.c, merges them together into a single GIMPLE representation, and optimizes them as usual to produce myprog โจ
The important thing to keep in mind: to enable link-time optimizations, you need to use the GCC driver to perform the link step ๐จ GCC automatically performs link-time optimization if any of the objects involved were compiled with the-fltocommand-line option. You can always override that automatic decision by passing-fno-ltoto the link command ๐ โโ๏ธ
Okay so bestie, whole program optimization is a total main character move, but it needs some big assumptions ๐
. The compiler has to know which functions and variables outside the link-time optimized unit can reach them, like libraries and runtime stuff. When your linker supports it, the linker plugin (see -fuse-linker-plugin) hands the compiler a list of used and externally visible symbols, which is so helpful ๐ซถ. If there's no linker plugin, use -fwhole-program so the compiler can make those assumptions and go way more aggressive with its optimization choices ๐ฅ.
When you compile with -flto and skip -fuse-linker-plugin, the object file ends up bigger than a regular one ๐. That's because it has GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). The upside is that these LTO-aware objects can still be linked like normal objects. Just know that if you pass -fno-lto to the linker, no interprocedural optimizations happen at all ๐. Also, if -fno-fat-lto-objects is on, the compile stage is faster, but you can't do a regular, non-LTO link with those files.
When GCC builds the final binary, it only runs link-time optimizations on the files that have bytecode in them โจ. So you can totally mix and match object files and libraries, with GIMPLE bytecode and final object code living side by side. GCC figures out on its own which files get the LTO treatment and which ones just link straight through ๐ง.
Generally, options you give at link time beat the ones you gave at compile time ๐. Sometimes though, GCC tries to guess link-time options from the settings used to compile the input files, so it's giving detective energy ๐.
If you don't pass an optimization level -O at link time, GCC uses the highest level that was used when compiling the object files ๐ฆ. Heads up, though: it's pretty ineffective to set an optimization level only at link time and not at compile time. There are two reasons for this. First, compiling without optimization skips the compiler passes that collect the info needed for good link-time optimization. Second, some early optimization passes can only run at compile time, not at link time ๐ญ.
GCC keeps some code generation flags around inside the bytecode, because they're needed during the final link ๐. Right now, these are taken from the first object file that explicitly sets them: -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm and all the -m target flags.
The PIC and PIE flags (-fPIC, -fpic, -fpie and -fPIE) get combined using this scheme, and it's kind of a vibe ๐:
-fPIC + -fpic = -fpic
-fPIC + -fno-pic = -fno-pic
-fpic/-fPIC + (no option) = (no option)
-fPIC + -fPIE = -fPIE
-fpic + -fPIE = -fpie
-fPIC/-fpic + -fpie = -fpie
Some ABI-changing flags have to match across all compilation units. If you try to override them at link time with a conflicting value, it gets ignored ๐
โโ๏ธ. This includes stuff like -freg-struct-return and -fpcc-struct-return.
Other options, like -ffp-contract, -fno-strict-overflow, -fwrapv, -fno-trapv or -fno-strict-aliasing, get passed through to the link stage and merged conservatively when translation units conflict ๐ธ. Specifically, -fno-strict-overflow, -fwrapv and -fno-trapv take precedence. For example, -ffp-contract=off beats -ffp-contract=fast. You can still override these at link time if you need to.
Diagnostic options like -Wstringop-overflow also get passed through to the link stage, and their setting matches the compile step at function granularity ๐. This only matters for diagnostics emitted during optimization. Also, code transforms like inlining can end up turning warnings on or off for regions when the code doesn't match the compile-time setting, so keep an eye on that ๐.
If you need to pass options to the assembler using -Wa or -Xassembler, you have two choices. You can either compile those translation units with -fno-lto, or use the same assembler options on every translation unit consistently ๐ง. You can also specify assembler options at LTO link time instead.
To get debug info, you need to supply -g at compile time ๐. If any input file at link time was built with debug info, the link turns debug info generation on too. Fancy debug info settings, like the DWARF level -gdwarf-5, need to be repeated explicitly on the linker command line. Mixing different settings across translation units is discouraged, so don't do it, bestie ๐
โโ๏ธ.
๐ If LTO runs into objects with C linkage that are declared with incompatible types across separate translation units being linked together, that's undefined behavior according to ISO C99 6.2.7. A non-fatal diagnostic may be issued, but the behavior is still undefined at run time. Similar diagnostics may pop up for other languages too.
Another feature of LTO is that you can apply interprocedural optimizations to files written in different languages ๐:
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice the final link is done with g++ to pull in the C++ runtime libraries, and -lgfortran is added to get the Fortran runtime libraries ๐ฆ. In general, when you mix languages in LTO mode, use the same link command options you'd use when mixing languages in a regular, non-LTO compilation.
If object files with GIMPLE bytecode are stored in a library archive, like libfoo.a, you can extract and use them in an LTO link as long as you're using a linker with plugin support ๐ซถ. To make static libraries that work with LTO, use gcc-ar and gcc-ranlib instead of ar and ranlib. To see the symbols in object files with GIMPLE bytecode, use gcc-nm. These commands need ar, ranlib and nm to have been compiled with plugin support. At link time, use -fuse-linker-plugin so the library joins the LTO optimization process โจ:
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin on, the linker pulls the needed GIMPLE files out of libfoo.a and hands them to the running GCC so they become part of the aggregated GIMPLE image that gets optimized ๐.
If you aren't using a linker with plugin support, and/or you don't enable the linker plugin, the objects inside libfoo.a get extracted and linked as usual. They just won't take part in the LTO optimization process ๐ญ. To make a static library that works for both LTO optimization and usual linkage, compile its object files with -flto -ffat-lto-objects ๐.
Link-time optimizations don't need the whole program to be present in order to work ๐ธ. If your program doesn't need any symbols exported, you can combine -flto and -fwhole-program so the interprocedural optimizers can use more aggressive assumptions, which may lead to better optimization opportunities ๐ฅ. You don't need -fwhole-program when the linker plugin is active (see -fuse-linker-plugin).
The current LTO implementation doesn't try to make bytecode that's portable between different host types ๐. The bytecode files are versioned with a strict version check, so bytecode generated by one GCC version won't work with an older or newer GCC version. Not a vibe!
Link-time optimization doesn't work super well with debug info generation on systems other than the ones using ELF and DWARF together ๐.
If you specify the optional n, the optimization and code generation done at link time runs in parallel using n jobs, by using an installed make program ๐ง. You can use the environment variable MAKE to override which program gets used.
You can also use -flto=jobserver to let GNU make's job server mode decide how many parallel jobs to run ๐. This is clutch when the Makefile calling GCC is already running in parallel. You have to prepend a + to the command recipe in the parent Makefile for this to work. This option likely only works if MAKE is GNU make. Even without the option value, GCC tries to automatically detect a running GNU make's job server โจ.
Use -flto=auto to use GNU make's job server if it's available, or otherwise fall back to autodetecting the number of CPU threads on your system ๐ฆ.
-flto-partition=algโ Okay, this one picks the partitioning algorithm the link-time optimizer uses ๐. Your choices are1to1, which mirrors the original source files,balanced, which splits things into equally sized chunks whenever that's possible, ormax, which makes a new partition for every symbol where possible. Pickingnoneturns partitioning and streaming off completely ๐ . The default isbalanced.1to1can be used as a workaround for various code ordering issues, butmaxpartitioning is only meant for internal testing, so don't go there ๐. The valueonemeans exactly one partition gets used, whilenoneskips partitioning and runs the link-time optimization step straight from the WPA phase ๐ธ.-flto-compression-level=nโ This one controls how much the intermediate language written to LTO object files gets compressed ๐. It only matters when you're in LTO mode (-flto). GCC currently supports two LTO compression algorithms. Forzstd, valid values are0(no compression) up to19(maximum compression), andzlibsupports values from0to9. Values outside the range get clamped to the minimum or maximum of whatever's supported. If you don't give the option, a default balanced compression setting gets used ๐.-fuse-linker-pluginโ This turns on a linker plugin during link-time optimization ๐. It relies on plugin support in the linker, which is available ingoldor in GNUld2.21 or newer โจ.
The -fuse-linker-plugin deal is that GCC can dig into library archives and pull out the object files carrying GIMPLE bytecode ๐ง. That gives the link-time optimizer way more code to work with, so the results are glow-up levels โจ. The info also says which symbols can be accessed from outside, by non-LTO object files or during dynamic linking ๐ฆ. Binaries (and shared libraries that use hidden visibility) get code quality improvements that are similar to -fwhole-program ๐ฅ. Check -flto for the full tea on what this flag does and how to use it ๐ซถ.
This option is on by default when LTO support is enabled in GCC and GCC was set up for a linker that supports plugins (GNU ld 2.21 or newer, or gold) ๐.
-ffat-lto-objectsโ okay so fat LTO objects are object files that hold both the intermediate language and the object code ๐. That makes them usable for LTO linking and normal linking, which is so iconic. This only matters when you're compiling with-flto, and it gets ignored at link time ๐.
-fno-fat-lto-objects improves compilation time over plain LTO, but the complete toolchain has to be aware of LTO for it to work ๐ง. It needs a linker with linker plugin support for basic functionality. nm, ar and ranlib also need to support linker plugins if you want a full-featured build environment (one that can build static libraries etc). GCC gives you the gcc-ar, gcc-nm, gcc-ranlib wrappers to pass the right options to these tools. With non fat LTO, makefiles need to be modified to use them.
Modern binutils has a plugin auto-load mechanism, so 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 hunts down arithmetic instructions that compute processor flags in a way that looks like a comparison based on that arithmetic ๐. If possible, it eliminates the explicit comparison operation ๐ .
This pass only applies to certain targets that can't explicitly represent the comparison operation before register allocation is complete.
Enabled at levels -O1, -O2, -O3, -Os.
-ffold-mem-offsets,-fno-fold-mem-offsetsโ tries to eliminate add instructions by folding them into memory loads and stores ๐ง.
Enabled at levels -O2, -O3.
-fcprop-registersโ after register allocation and post-register allocation instruction splitting, GCC runs a copy-propagation pass to try to reduce scheduling dependencies and occasionally eliminate the copy ๐ธ.
Enabled at levels -O1, -O2, -O3, -Os.
-fprofile-correctionโ profiles collected from an instrumented binary for multi-threaded programs can be inconsistent because of missed counter updates ๐. With this option, GCC uses heuristics to correct or smooth out those inconsistencies. By default, GCC emits an error message when it detects an inconsistent profile.
This option is enabled by -fauto-profile.
-fprofile-partial-trainingโ with"-fprofile-use", all portions of the program that weren't executed during the train run get optimized aggressively for size rather than speed ๐. Sometimes it's not practical to train every possible hot path. For example, a program may contain functions specific to certain hardware, and training may not cover every hardware configuration the program runs on ๐ฅ๏ธ. With"-fprofile-partial-training", profile feedback is ignored for all functions not executed during the train run, so they're optimized as if they were compiled without profile feedback. This leads to better performance when the train run isn't representative, but it also leads to significantly bigger code ๐ฆ.-fprofile-use,-fprofile-use=pathโ turns on profile feedback-directed optimizations, plus the following optimizations, many of which are usually only worth it when profile feedback is available ๐:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Before you can use this option, you must 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.
Note this may result in poorly optimized code ๐ฌ.
Also by default, GCC emits a warning message if the feedback profiles don't exist (see -Wmissing-profile).
If path is specified, GCC looks there for 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 usually only worth it when profile feedback is available โจ:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-correction
path is the name of a file containing AutoFDO profile information. If you leave it out, it defaults to fbdata.afdo in the current directory ๐.
Producing an AutoFDO profile data file requires running your program with the perf utility on a supported GNU/Linux target system. For more info, check 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 compiler behavior around floating-point arithmetic ๐งฎ. They trade off speed against correctness, and you have to turn every single one of them on yourself ๐.
-ffloat-storeโ do not store floating-point variables in registers, and stop other options that might change whether a floating-point value is pulled from a register or from memory ๐ง.
This option prevents the undesirable excess precision you get on machines like the 68000, where the floating registers (of the 68881) keep more precision than a "double" is supposed to have ๐ญ. The same goes for the x86 architecture. For most programs the excess precision only does good, but a few programs rely on the precise definition of IEEE floating point. For those, use -ffloat-store after modifying them to store all pertinent intermediate computations into variables.
-fexcess-precision=styleโ this gives you more control over 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 ๐ง . By default,-fexcess-precision=fastis in effect, which means operations may be carried out in a wider precision than the types in the source if that makes the code faster, and it's unpredictable when rounding to the source types takes place.
When compiling C or C++, if -fexcess-precision=standard is specified, excess precision follows the rules of ISO C99 or C++. In particular, both casts and assignments 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 such as -std=c99 or -std=c++17 is used. -ffast-math enables -fexcess-precision=fast by default regardless of whether a strict conformance option is used. If -fexcess-precision=16 is specified, constants and the results of expressions with 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 has no effect if -mfpmath=sse or -mfpmath=sse+387 is specified. In the former case, IEEE semantics apply without excess precision, and in the latter, rounding is unpredictable.
-ffast-mathโ sets-fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans,-fcx-limited-rangeand-fexcess-precision=fast๐.
This option causes the preprocessor macro "__FAST_MATH__" to be defined.
This option is not turned on by any-Ooption besides-Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications ๐.
-fno-math-errnoโ do not seterrnoafter calling math functions that are executed with a single instruction, e.g.,sqrt. A program that relies on IEEE exceptions for math error handling may want this flag for speed while keeping IEEE arithmetic compatibility ๐๏ธ.
This option is not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications.
The default is -fmath-errno.
On Darwin systems, the math library never sets errno. There's therefore no reason for the compiler to consider the possibility that it might, so -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.
Be careful with this one ๐ฑ. When used at link time, it may include libraries or startup files that change the default FPU control word or other similar optimizations.
This one's the "not turned on by any -O option" energy again, bestie ๐ -funsafe-math-optimizations is never switched on by an -O flag because it can give you wrong output for programs that depend on the exact IEEE or ISO math rules ๐ It might make faster code for programs that don't need those guarantees though โจ and it turns on -fno-signed-zeros, -fno-trapping-math, -fassociative-math and -freciprocal-math all at once ๐ซถ
The default is -fno-unsafe-math-optimizations ๐
-fassociative-mathโ okay so this lets the compiler regroup operands in a chain of floating-point operations ๐ฆ It breaks the ISO C and C++ standard because the result can change ngl ๐ญ- NOTE: reordering can flip the sign of zero, ignore NaNs, and cause or hide underflow and overflow ๐ So it's a no-go for code that relies on rounding tricks like
(x + 2**52) - 2**52. It can also reorder floating-point comparisons, so don't use it where ordered comparisons are required ๐ โโ๏ธ - It requires both
-fno-signed-zerosand-fno-trapping-mathto be in effect, and it doesn't really make sense with-frounding-math๐ธ - For Fortran, it gets switched on automatically when both
-fno-signed-zerosand-fno-trapping-mathare in effect โจ - The default is
-fno-associative-math.
- NOTE: reordering can flip the sign of zero, ignore NaNs, and cause or hide underflow and overflow ๐ So it's a no-go for code that relies on rounding tricks like
-freciprocal-mathโ this one lets the compiler use the reciprocal of a value instead of dividing, if that unlocks some optimizations ๐ง Sox / ycan becomex * (1/y), which is super handy when(1/y)can be pulled out as a common subexpression ๐ The catch is that it loses precision and adds more flops on the value ๐ฌ- The default is
-fno-reciprocal-math.
- The default is
-ffinite-math-onlyโ allows optimizations that assume arguments and results are never NaNs or+-Infs๐- It's not turned on by any
-Ooption, same as before, because it can give wrong output for programs that need the exact IEEE or ISO math rules ๐ It might still give faster code for programs that don't need those guarantees ๐ฆ - The default is
-fno-finite-math-only.
- It's not turned on by any
-fno-signed-zerosโ allows optimizations that don't care about whether zero is signed ๐ซง IEEE says distinct+0.0and-0.0have their own behaviour, which stops the compiler from simplifying things likex+0.0or0.0*x(even with-ffinite-math-only) ๐ This option basically says the sign of a zero result doesn't matter ๐- The default is
-fsigned-zeros.
- The default is
-fno-trapping-mathโ tells the compiler to assume floating-point operations can't cause user-visible traps ๐ Those traps are division by zero, overflow, underflow, inexact result and invalid operation ๐ฑ It requires-fno-signaling-nansto be in effect, and it can make faster code if you rely on "non-stop" IEEE arithmetic ๐๏ธ- > Warning: this should never be turned on by any
-Ooption, because it can give wrong output for programs that depend on the exact IEEE or ISO math rules ๐ - The default is
-ftrapping-math. - Future GCC versions might give finer control over this using C99's
FENV_ACCESSpragma ๐ฎ This flag will then be used along with-frounding-mathto set the default state forFENV_ACCESSโจ
- > Warning: this should never be turned on by any
-frounding-mathโ disables transformations and optimizations that assume the default floating-point rounding behaviour ๐ธ That default is round-to-zero for all floating-point to integer conversions, and round-to-nearest for all other arithmetic truncations ๐ Use this if your program changes the FP rounding mode dynamically, or might run with a non-default rounding mode ๐ซถ- It turns off compile-time constant folding of floating-point expressions (since rounding mode can change those), plus arithmetic transformations that are unsafe with sign-dependent rounding modes ๐ โโ๏ธ
- The default is
-fno-rounding-math. - > Experimental: this doesn't currently guarantee to disable every GCC optimization affected by rounding mode ๐ฅบ
- Future versions might give finer control using C99's
FENV_ACCESSpragma ๐ฎ This flag will be used along with-ftrapping-mathto set the default state forFENV_ACCESSโจ
-fsignaling-nansโ compiles assuming IEEE signaling NaNs may cause user-visible traps during floating-point operations ๐ฅ Turning it on disables optimizations that might change how many exceptions are visible with signaling NaNs ๐ It implies-ftrapping-math, and it defines the preprocessor macro__SUPPORT_SNAN__๐ง- The default is
-fno-signaling-nans. - > Experimental: this doesn't currently guarantee to disable every GCC optimization that affects signaling NaN behaviour ๐
- The default is
-fno-fp-int-builtin-inexactโ stops the built-in functionsceil,floor,roundandtrunc(plus theirfloatandlong doublevariants) from generating code that raises theinexactfloating-point exception for non-integer arguments ๐ช ISO C99 and C11 let these raiseinexact, but ISO/IEC TS 18661-1:2014 (the C bindings to IEEE 754-2008, now part of ISO C23) doesn't ๐ โโ๏ธ- The default is
-ffp-int-builtin-inexact, which lets the exception be raised, unless C23 or a later C standard is selected ๐ - This option does nothing unless
-ftrapping-mathis in effect ๐คทโโ๏ธ - Even with
-fno-fp-int-builtin-inexact, if these functions end up calling a library function,inexactmay still be raised if that library doesn't follow TS 18661 ๐ญ
- The default is
-fsingle-precision-constantโ treats floating-point constants as single precision, instead of quietly converting them to double-precision constants ๐ฆ-fcx-limited-rangeโ when this is on, the compiler is told that a range reduction step isn't needed for complex division ๐ It also skips checking whether the result of a complex multiplication or division isNaN + I*NaNand trying to rescue it ๐ซง- The default is
-fno-cx-limited-range, but-ffast-mathturns it on โจ - This controls the default setting of the ISO C99
CX_LIMITED_RANGEpragma ๐ It applies to all languages, though ๐
- The default is
-fcx-fortran-rulesโ complex multiplication and division follow Fortran rules ๐ง Range reduction happens as part of complex division, but there's still no checking for aNaN + I*NaNresult or any attempt to rescue it ๐- The default is
-fno-cx-fortran-rules.
- The default is
The following options control optimizations that may improve performance, but none of them are enabled by any -O option ๐ This section also includes experimental options that may produce broken code, so be careful bestie โ ๏ธ
-fbranch-probabilitiesโ okay this one is a whole glow-up ๐ First you run a program compiled with-fprofile-arcs, then you compile it a second time with-fbranch-probabilitiesso the optimizations can use how many times each branch was 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 ๐ซถ Check-fprofile-arcsfor the details on file naming ๐- 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: inreorg.cc, where instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to figure out exactly which path is taken more often ๐ฏ - Enabled by
-fprofile-useand-fauto-profile.
- With
-fprofile-valuesโ if you combine it with-fprofile-arcs, it adds code that gathers some data about the values of expressions in the program ๐ฅ With-fbranch-probabilities, it reads that data back and uses it for optimizations ๐- Enabled by
-fprofile-generate,-fprofile-use, and-fauto-profile.
- Enabled by
-fprofile-reorder-functionsโ function reordering based on profile instrumentation records the first time each function runs, then sorts those functions in ascending order ๐๏ธ- Enabled with
-fprofile-use.
- Enabled with
-fvptโ with-fprofile-arcs, this tells the compiler to add code that gathers information about expression values ๐ต๏ธโโ๏ธ With-fbranch-probabilities, it reads that data back and actually performs optimizations based on it ๐ Right now those optimizations include specialising division operations using what it knows about the denominator's value ๐- Enabled with
-fprofile-useand-fauto-profile.
- Enabled with
-frename-registersโ tries to avoid false dependencies in scheduled code by using registers left over after register allocation ๐ It mostly helps processors with loads of registers ๐ช Heads up though: depending on the debug information format the target uses, it can make debugging impossible, because variables no longer stay in a "home register" ๐ญ- Enabled by default with
-funroll-loops.
- Enabled by default with
-fschedule-fusionโ runs a target-dependent pass over the instruction stream to group instructions of the same type together ๐งฉ The target machine can run them more efficiently when they're next to each other in the flow ๐โโ๏ธ- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-ftracerโ performs tail duplication to enlarge the superblock size ๐ฐ This simplifies the function's control flow, so other optimizations can do a better job ๐- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-funroll-loopsโ okay bestie, this one unrolls loops whose number of iterations is known at compile time or when the loop gets entered ๐ It also implies-frerun-cse-after-loop,-fweband-frename-registers, so it brings its whole squad โจ It also switches on complete loop peeling, which fully removes loops that only run a small constant number of times. > Heads up: this makes your code bigger, and it may or may not make it run faster ๐ It's enabled by-fprofile-useand-fauto-profile.-funroll-all-loopsโ the no-chill version ๐ This unrolls every loop, even when the iteration count is still a mystery when the loop starts. > This usually makes programs run more slowly ๐ญ It implies the same options as-funroll-loops.-fpeel-loopsโ this peels loops that don't roll much, going off profile feedback or static analysis ๐ธ It also turns on complete loop peeling, meaning loops with a small constant number of iterations get fully removed. It's enabled by-O3,-fprofile-use, and-fauto-profile.-fmove-loop-invariantsโ turns on the loop invariant motion pass in the RTL loop optimizer ๐ง It's enabled at level-O1and higher, except for-Og.-fmove-loop-storesโ enables the loop store motion pass in the GIMPLE loop optimizer ๐ฆ It moves invariant stores to after the end of the loop, trading that for keeping the stored value in a register across each iteration. Note that for this to actually do anything,-ftree-loop-imhas to be enabled too. It's enabled at level-O1and higher, except for-Og.-fsplit-loopsโ if a loop has a condition that's always true on one side of the iteration space and always false on the other, this splits the loop into two โ๏ธ It's enabled by-fprofile-useand-fauto-profile.-funswitch-loopsโ this yanks branches with loop invariant conditions out of the loop ๐ซถ You get duplicates of the loop on both branches, each tweaked to match what the condition came out to be. It's enabled by-fprofile-useand-fauto-profile.-fversion-loops-for-stridesโ if a loop walks an array with a variable stride, GCC makes a second copy of the loop that assumes the stride is always one ๐ Here's the vibe:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
This is especially iconic for Fortran's assumed-shape arrays, since it lets the compiler vectorize better when it can assume contiguous access ๐ It's enabled by default at -O3, and it's also enabled by -fprofile-use and -fauto-profile.
-ffunction-sections,-fdata-sectionsโ these put each function or data item into its own section in the output file, but only if the target supports arbitrary sections ๐งฉ The function or data item's name decides the section name.- Use these where the linker can optimize for locality of reference in the instruction space. Most ELF object format systems have linkers that can do this. On AIX, the linker rearranges sections (CSECTs) based on the call graph, and the performance impact varies ๐ฅ
- Paired with linker garbage collection (the
linker --gc-sectionsoption), these can lead to smaller statically-linked executables (after stripping) ๐ - On ELF/DWARF systems, these don't make the debug info worse. Other object file or debug info formats might have issues ๐
- > Only use these when there are significant benefits, bestie ๐ซถ They make the assembler and linker produce larger object and executable files, and they're also slower. They also affect code generation: they stop the compiler and assembler from using relative locations inside a translation unit, since those aren't known until link time. One example of an optimization that gets blocked is relaxing calls to short call instructions.
-fstdarg-optโ optimizes the prologue of variadic argument functions based on how those arguments are actually used โจ-fsection-anchorsโ this tries to cut down on symbolic address calculations by using shared "anchor" symbols to reach nearby objects ๐ฆ It can reduce GOT entries and GOT accesses on some targets. Say you have this function "foo":
static int a, b, c;
int foo (void) { return a + b + c; }
Normally it calculates the addresses of all three variables, but with -fsection-anchors it reads them from one common anchor point instead. The effect is similar to this pseudocode (which isn't valid C, so don't try it ๐):
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
Not every target supports this one, so check before you get too attached ๐
-fzero-call-used-regs=choiceโ zeroes the call-used registers when a function returns, which boosts program security ๐ It either helps mitigate Return-Oriented Programming (ROP) attacks or stops information from leaking out through registers. The possible values ofchoiceare the same as for thezero_call_used_regsattribute, and the default isskip. You can control this per function with the function attributezero_call_used_regs๐--param name=valueโ GCC uses a bunch of internal constants to decide how much optimization to do. For example, it won't inline functions that have more than a certain number of instructions ๐ You can tweak some of these from the command line with--param. Heads up: the names and meanings are tied to compiler internals and can change without notice in future releases ๐ญ To see the minimal, maximal, and default value of a parameter, use--help=param -Q. The value is always an integer, and these names are recognized for all targets:predictable-branch-outcomeโ if a branch is predicted to be taken with a probability lower than this threshold (in percent), it counts as well predictable ๐ฏmax-rtl-if-conversion-insnsโ RTL if-conversion tries to get rid of conditional branches around a block by swapping them for conditionally executed instructions. This sets the max number of instructions in a block that get considered for if-conversion. The compiler also uses other heuristics to decide whether it's actually worth it โจmax-rtl-if-conversion-predictable-costโ RTL if-conversion will try to remove conditional branches around a block the same way. These parameters cap the cost of the sequence it would generate, depending on whether the branch is statically determined to be predictable or not. The units match GCC's internal seq_cost metric. The compiler tries to pick a reasonable default for this using theBRANCH_COSTtarget macro ๐max-crossjump-edgesโ the max number of incoming edges to consider for cross-jumping. The algorithm behind-fcrossjumpingisO(N^2)in the number of edges coming into each block ๐ซ Bigger values mean more aggressive optimization, with compile time going up for probably a small size win.min-crossjump-insnsโ the min number of instructions that must match at the end of two blocks before cross-jumping happens on them. This 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 to duplicate into a block that jumps to a computed goto. To avoidO(N^2)behavior in several passes, GCC factors computed gotos early and unfactors them as late as possible. Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsinstructions get unfactored ๐ฆmax-delay-slot-insn-searchโ the max number of instructions to check when hunting for something to fill a delay slot. If you search past this arbitrary number, the time saved by filling the slot is tiny, so GCC just stops searching ๐ Bigger values mean more aggressive optimization, with compile time going up for probably a small execution time win.max-delay-slot-live-searchโ when filling delay slots, the max number of instructions to check while looking for a block with valid live register information. Raising this arbitrarily chosen value means more aggressive optimization but longer compile times. This parameter 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 inkBthat can be allocated for global common subexpression elimination. If the optimization needs more memory than this, it just doesn't happen ๐งmax-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is bigger than this value for any expression, RTL PRE inserts or removes that expression, which leaves partially redundant computations sitting in the instruction stream ๐
max-pending-list-lengthโ bestie, this is the cap on how many pending dependencies scheduling is allowed to hold ๐ Once it hits the limit, it flushes the current state and starts over. Huge functions with barely any branches or calls can build up massive lists that waste memory and resources for no reason ๐ญmax-modulo-backtrack-attemptsโ the max number of backtrack attempts the scheduler will make while modulo scheduling a loop ๐ Go too high and your compile time can blow up exponentially ๐max-inline-functions-called-once-loop-depthโ the maximal loop depth of a call that the inline heuristics will consider when they're trying to inline every function that's called once ๐งmax-inline-functions-called-once-insnsโ the maximal estimated size of functions that come out of inlining the functions called once ๐ธmax-inline-insns-singleโ okay so the tree inliner has a whole squad of parameters ๐ This one sets the max number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will even look at for inlining. It only affects functions declaredinlineand methods implemented right inside a class declaration (C++) ๐max-inline-insns-autoโ when you turn on-finline-functions(which comes with-O3), a whole bunch of functions that the compiler wouldn't normally think about inlining suddenly get checked ๐ For those, a different, more restrictive limit applies than for functions declaredinline(--param max-inline-insns-auto) ๐ฆmax-inline-insns-smallโ the bound that applies to calls considered relevant when you use-finline-small-functions๐max-inline-insns-sizeโ the bound that applies to calls being optimized for size ๐ A little bit of growth can actually be a good thing here, since it can open up optimization opportunities that inlining exposes โจuninlined-function-insnsโ the number of instructions the inliner counts as overhead for a function, like its prologue and epilogue ๐ซถuninlined-function-timeโ the extra time the inliner counts as overhead for a function, like the time it takes to run that prologue and epilogue โฑ๏ธinline-heuristics-hint-percentโ the scale (in percents) applied toinline-insns-single,inline-insns-single-O2, andinline-insns-autowhen the inline heuristics hint that inlining is super profitable and will enable later optimizations ๐ฅuninlined-thunk-insns,uninlined-thunk-timeโ same deal as--param uninlined-function-insnsand--param uninlined-function-time, except these are applied to function thunks ๐งตinline-min-speedupโ if 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 ๐ Main character move, honestly ๐large-function-insnsโ the limit that defines a really large function ๐ For functions bigger than this after inlining, inlining gets constrained by--param large-function-growth. This one is mostly there to stop extreme compile times caused by the non-linear algorithms the back end uses ๐large-function-growthโ the max growth of a large function caused by inlining, in percents ๐ 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 limit might be too tight ๐ฌ Say you've got a unit with function A (inline) and function B that just calls A three times. If B is small compared to A, the unit's growth is 300%, and honestly that kind of inlining is totally sane ๐ But for huge units full of tiny inlineable functions, the overall unit growth limit is what stops an exponential explosion of code size ๐ So for smaller units, the size gets bumped up to--param large-unit-insnsbefore the--param inline-unit-growthlimit gets applied ๐งlazy-modulesโ the max number of C++ module files that can be open at the same time 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 (either marked cold with an attribute or flagged 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 at which the IPA-CP pass considers a translation unit to be large ๐large-stack-frameโ the limit that defines large stack frames ๐ฅ While it's inlining, the algorithm tries really hard not to grow past this limit too much ๐ซฃlarge-stack-frame-growthโ the max growth of large stack frames caused by inlining, in percents ๐ 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 is allowed to grow into by doing recursive inlining ๐--param max-inline-insns-recursiveapplies to functions declaredinline. For functions not declaredinline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and then--param max-inline-insns-recursive-autois the one that applies instead ๐max-inline-recursive-depth,max-inline-recursive-depth-autoโ the max recursion depth used for recursive inlining ๐ช--param max-inline-recursive-depthapplies to functions declaredinline. For functions not declaredinline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and--param max-inline-recursive-depth-autoapplies instead ๐min-inline-recursive-probabilityโ recursive inlining is only worth it for functions that recurse deeply on average ๐ For functions with a shallow recursion depth it can actually hurt, because it bumps up the prologue size or makes the function body more complicated for other optimizers ๐ต 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 limits inlining to only those call expressions whose probability goes over the threshold (in percent) ๐ฏearly-inlining-insnsโ how much growth the early inliner is allowed to make ๐ท Basically, it ramps up the amount of inlining for code that has a large abstraction penalty ๐๏ธmax-early-inliner-iterationsโ the limit on how many iterations the early inliner runs ๐ This basically caps how many nested indirect calls the early inliner can resolve ๐งฉ Deeper chains still get handled later, by late inlining ๐ฆ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 max number of base pointers, references, and accesses stored for a single function by mod/ref analysis ๐๏ธmodref-max-testsโ the max number of tests the alias oracle can run to tell memory locations apart using the mod/ref info ๐ต๏ธโโ๏ธ This one ought to be bigger than--param modref-max-basesand--param modref-max-refs, so keep that in mind ๐ซถmodref-max-depthโ the max depth of the DFS walk used by modref escape analysis ๐ Setting it to0disables the analysis completely ๐ซmodref-max-escape-pointsโ the max number of escape points tracked by modref per SSA-name ๐modref-max-adjustmentsโ the max amount the access range gets enlarged during modref dataflow analysis ๐profile-func-internal-idโ controls whether the function's internal id gets used in the profile database lookup ๐๏ธ If the value is0, the compiler uses an id based on the function's assembler name and filename instead ๐ง That makes old profile data way more forgiving of source changes, like function reordering and stuff ๐ซmin-vect-loop-boundโ the min number of iterations below which loops don't get vectorized when-ftree-vectorizeis in use ๐ถ The iteration count after vectorization has to be greater than this value for vectorization to happen ๐ชgcse-cost-distance-ratioโ a scaling factor used when calculating how far an expression can get moved by GCSE optimizations ๐ It's only supported in the code hoisting pass for now ๐ช The bigger the ratio, the more aggressively code gets hoisted for simple expressions (ones that cost less thangcse-unrestricted-cost) ๐ฅ Setting it to0disables hoisting of simple expressions completely ๐ โโ๏ธgcse-unrestricted-costโ the cost, roughly measured as the cost of a single typical machine instruction, at which GCSE optimizations stop constraining how far an expression can travel ๐ Also only supported in the code hoisting pass ๐ช The lower the cost, the more aggressive the hoisting gets ๐ Setting it to0lets every expression travel an unrestricted distance ๐ฆmax-hoist-depthโ the depth of the search in the dominator tree for expressions to hoist ๐ณ It's there to avoid quadratic behavior in the hoisting algorithm ๐งฎ A value of0doesn't limit the search at all, but it might slow down compilation of huge functions ๐ขmax-tail-merge-comparisonsโ the max number of similar basic blocks to compare any one basic block against ๐ง It's used to avoid quadratic behavior in tree tail merging ๐max-tail-merge-iterationsโ the cap on how many passes over the function the tree tail merging can make ๐ It's basically a compile-time leash so this doesn't go on forever โฑ๏ธstore-merging-allow-unalignedโ lets the store merging pass create unaligned stores, but only when that's legal ๐งฉmax-stores-to-mergeโ how many stores the store merging pass will try to squish together into wider stores ๐ซถmax-store-chains-to-trackโ how many store chains the store merging pass can track at once while trying to merge them into wider stores ๐max-stores-to-trackโ how many stores get tracked at the same time while the store merging pass tries to merge them into wider stores ๐max-unrolled-insnsโ the most instructions a loop can have and still get unrolled ๐ If the loop does get unrolled, this same number also decides how many times the loop body is copied ๐max-average-unrolled-insnsโ like the one above, but counts instructions weighted by how likely they are to run ๐ Again, if a loop gets unrolled, this value also sets how many times the loop code is unrolled ๐ธmax-unroll-timesโ the max number of times a single loop can be unrolled ๐ฆmax-peeled-insnsโ the most instructions a loop can have and still get peeled ๐ If it does get peeled, this also decides how many times the loop code is peeled ๐งmax-peel-timesโ the max number of times a single loop can be peeled ๐ซงmax-peel-branchesโ the max number of branches allowed on the hot path through the peeled sequence ๐max-completely-peeled-insnsโ the max number of instructions a completely peeled loop can have ๐max-completely-peel-timesโ the max number of iterations a loop can have and still be a good candidate for complete peeling โญmax-completely-peel-loop-nest-depthโ the deepest a loop nest can be and still be suitable for complete peeling ๐ชmax-unswitch-insnsโ the max number of instructions an unswitched loop can have ๐max-unswitch-depthโ the deepest a loop nest can be and still get unswitched ๐lim-expensiveโ the minimum cost for an expression to count as expensive in loop invariant motion ๐ธmin-loop-cond-split-probโ when FDO profile information is available, this sets the minimum probability a semi-invariant condition statement needs before it triggers a loop split โ๏ธiv-consider-all-candidates-boundโ if there are this many induction variable candidates or fewer, every candidate gets considered for each use in the induction variable optimizations ๐ง If there are more than that, only the most relevant ones get looked at, so the time complexity doesn't go quadratic ๐ญiv-max-considered-usesโ the induction variable optimizations just give up on any loop that has more induction variable uses than this ๐ณ๏ธiv-always-prune-cand-set-boundโ if the candidate set is smaller than this value, the compiler always tries to clear out unnecessary ivs from the set whenever it adds a new one ๐งนavg-loop-niterโ the average number of iterations a loop is expected to run ๐ขdse-max-object-sizeโ the biggest object (in bytes) that dead store elimination will track byte by byte ๐ฆ Bigger values can mean bigger compilation times, so keep that in mind ๐ขdse-max-alias-queries-per-storeโ the max number of queries sent to the alias oracle for each store ๐ Larger values can take longer to compile but may remove more dead stores ๐scev-max-expr-sizeโ the upper bound on how big expressions can be in the scalar evolutions analyzer ๐ Big expressions slow the analyzer down ๐scev-max-expr-complexityโ the upper bound on how complex expressions can be in the scalar evolutions analyzer ๐งถ Complicated expressions slow the analyzer down too ๐ฉmax-tree-if-conversion-phi-argsโ the max 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 max number of possible vector layouts, such as permutations, that get considered when optimizing code that's about to be vectorized ๐จvect-max-version-for-alignment-checksโ the max number of run-time checks allowed when the vectorizer does loop versioning for alignment ๐ ๏ธvect-max-version-for-alias-checksโ the max number of run-time checks allowed when the vectorizer does loop versioning for alias ๐ต๏ธvect-max-peeling-for-alignmentโ the max number of loop peels the vectorizer can do to improve access alignment ๐ซง A value of-1means there's no limit ๐max-iterations-to-trackโ the max number of iterations of a loop that the brute-force algorithm for figuring out a loop's iteration count will try to evaluate ๐งฎhot-bb-count-fractionโ thenin the fraction1/nof the maximal execution count of a basic block in the whole program. A basic block has to hit at least that to count as hot ๐ฅ The default is10000, which means a basic block is hot if its execution count is greater than1/10000of the maximal execution count ๐ A value of0means it's never considered hot ๐ฅถ This one is used in non-LTO mode ๐งhot-bb-count-ws-permilleโ how many of the most-executed permilles, from0to1000, of the profiled execution of the whole program a basic block's execution count has to be part of to count as hot ๐ก๏ธ The default is990, which means a basic block is hot if its count contributes to the upper 990 permilles, or 99.0%, of the profiled execution of the whole program โจ A value of0means it's never hot ๐ซ This one is used in LTO mode ๐hot-bb-frequency-fractionโ thenin the fraction1/nof the entry block's execution frequency in a function that a basic block in that function has to reach to be hot ๐ The default is1000, which means a basic block is hot in a function if it runs more often than1/1000of the entry block's frequency ๐ A value of0means it's never hot ๐ โโ๏ธunlikely-bb-count-fractionโ thenin the fraction1/nof the number of profiled runs of the whole program. If a basic block's execution count is below that, it counts as unlikely to run ๐ด The default is20, meaning a basic block is unlikely if it runs in fewer than1/20, or 5%, of the program's runs ๐ A value of0means it's always considered unlikely ๐ซmax-predicted-iterationsโ the max number of loop iterations the compiler predicts 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 it is that an expression has the specified value ๐ฏ This takes a percentage, from 0 to 100 ๐ฏbuiltin-string-cmp-inline-lengthโ the max length of a constant string for a builtin string cmp call that's eligible for inlining ๐งตalign-thresholdโ picks a fraction of the maximal execution frequency of a basic block in a function to decide whether that block gets aligned ๐align-loop-iterationsโ any loop expected to iterate at least this many times gets aligned ๐ชtracer-dynamic-coverage,tracer-dynamic-coverage-feedbackโ these limit superblock formation once the given percentage of executed instructions is covered ๐ง That keeps the code from ballooning in size for no reason ๐
The tracer-dynamic-coverage-feedback parameter only gets used when profile feedback is available ๐ Real profiles, unlike statically estimated ones, are much less balanced, so the threshold can be set to a larger value ๐ช
tracer-max-code-growthโ stops tail duplication once code growth reaches the given percentage ๐ฑ It's a pretty artificial limit, since most of the duplicates get cleaned up later in cross jumping, so it can be set way higher than the code growth you actually want ๐tracer-min-branch-ratioโ stops reverse growth when the reverse probability of the best edge drops below this threshold, given as a percent ๐tracer-min-branch-probability,tracer-min-branch-probability-feedbackโ stops forward growth if the best edge has a probability lower than this threshold ๐ฆ
Like tracer-dynamic-coverage, there are two versions of this one. tracer-min-branch-probability-feedback is for compiling with profile feedback, and tracer-min-branch-probability is for compiling without it ๐ง The feedback value needs to be more conservative, meaning higher, so the tracer actually works well ๐
stack-clash-protection-guard-sizeโ the size of the operating system's stack guard, written as 2 raised to num bytes ๐ก๏ธ Higher values can reduce the number of explicit probes โจ
โ ๏ธ If this value is larger than the operating system's guard, the code is left vulnerable to stack clash style attacks. Not it! ๐ โโ๏ธ
stack-clash-protection-probe-intervalโ stack clash protection probes the stack space as it gets allocated ๐ This sets the max distance between probes into the stack, written as 2 raised to num bytes ๐ Higher values can reduce the number of explicit probes ๐ท
โ ๏ธ If this value is larger than the operating system's guard, the code is left vulnerable to stack clash style attacks. Bestie, don't let that happen ๐ญ
max-cse-path-lengthโ โจ okay so this is the max number of basic blocks on a path that CSE is allowed to look at ๐งmax-cse-insnsโ ๐ the max number of instructions CSE chews through before it flushes everything and starts fresh ๐ซงggc-min-expandโ ๐ง GCC runs its own garbage collector to handle its memory, and this one sets the minimum percentage the GC heap can grow by between collections. Tuning it might speed up compilation, but it has zero effect on code generation, so no cap ๐- Default:
30% + 70% * (RAM/1GB), with an upper bound of 100% when RAM >= 1GB. Ifgetrlimitis available, "RAM" means the smallest of actual RAM andRLIMIT_DATAorRLIMIT_AS. If GCC can't work out RAM on a platform, the 30% lower bound kicks in. - Setting this and
ggc-min-heapsizeto zero forces a full collection at every opportunity. That's extremely slow ๐ but it can be useful for debugging ๐
- Default:
ggc-min-heapsizeโ ๐ธ the minimum size the GC heap has to reach before it even starts bothering to collect garbage. The first collection happens once the heap grows byggc-min-expand% beyondggc-min-heapsize. Again, tuning this may speed up compilation and has no effect on code generation ๐ฆ- Default: the smaller of RAM/8,
RLIMIT_RSS, or a limit that tries to make sureRLIMIT_DATAorRLIMIT_ASdon't get exceeded. It has a lower bound of 4096 (four megabytes) and an upper bound of 131072 (128 megabytes). If GCC can't calculate RAM on a platform, the lower bound is used. - Setting this very large effectively disables garbage collection ๐
- Setting this and
ggc-min-expandto zero causes a full collection at every opportunity.
- Default: the smaller of RAM/8,
max-reload-search-insnsโ ๐ the max number of instructions reload will look backward through to find an equivalent register. Higher numbers mean more aggressive optimization, so compile time goes up for probably slightly better performance ๐max-cselib-memory-locationsโ ๐งฉ the max number of memory locations cselib will take into account. Higher values mean more aggressive optimization, which bumps up compile time for probably slightly better performance โจmax-sched-ready-insnsโ ๐ the max number of instructions that are ready to be issued that the scheduler will consider at any given moment during the first scheduling pass. Higher values mean more thorough searches, so compile time climbs with probably little benefit ๐ฅฑmax-sched-region-blocksโ ๐บ๏ธ the max number of blocks in a region that gets considered for interblock scheduling ๐ฉทmax-pipeline-region-blocksโ ๐ฐ the max number of blocks in a region that gets considered for pipelining in the selective scheduler ๐max-sched-region-insnsโ ๐ฏ the max number of insns in a region that gets considered for interblock scheduling ๐max-pipeline-region-insnsโ ๐ ๏ธ the max number of insns in a region that gets considered for pipelining in the selective scheduler ๐ซถmin-spec-probโ ๐ฒ the minimum probability (in percents) of reaching a source block for interblock speculative scheduling ๐ฎmax-sched-extend-regions-itersโ ๐ the max number of iterations through the CFG when extending regions. Setting this to0disables region extensions completely ๐ซmax-sched-insn-conflict-delayโ โณ the max conflict delay an insn can have and still be considered for speculative motion ๐ทsched-spec-prob-cutoffโ โ๏ธ the minimal probability of speculation success (in percents) needed before speculative insns actually get scheduled ๐ฆsched-state-edge-prob-cutoffโ ๐ the minimum probability an edge has to have before the scheduler saves its state across it ๐sched-mem-true-dep-costโ ๐ฐ๏ธ the minimal distance (in CPU cycles) between a store and a load that target the same memory locations ๐พselsched-max-lookaheadโ ๐ the max size of the lookahead window for selective scheduling. Basically, it's how deep the search for available instructions goes ๐ต๏ธโโ๏ธselsched-max-sched-timesโ ๐ the max number of times an instruction gets scheduled during selective scheduling. This is the cap on how many iterations an instruction can be pipelined through ๐งselsched-insns-to-renameโ โ๏ธ the max number of best instructions in the ready list that get considered for renaming in the selective scheduler ๐ซsms-min-scโ ๐ the minimum stage count value that the swing modulo scheduler generates ๐max-last-value-rtlโ ๐ the max size, counted as the number of RTLs, that the combiner can record in an expression for a pseudo register as that register's last known value ๐งถmax-combine-insnsโ ๐ง the max number of instructions the RTL combiner tries to combine together ๐นinteger-share-limitโ ๐ค small integer constants can use a shared data structure, which saves the compiler memory and makes it faster. This sets the max value of a shared integer constant ๐ขssp-buffer-sizeโ ๐ก๏ธ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectoris used- Before Ubuntu 10.10 the default was "8". Right now it's "4", so more functions get protected ๐ฅน
min-size-for-stack-sharingโ ๐ฅ the minimum size of variables that take part in stack slot sharing when you're not optimizing ๐max-jump-thread-duplication-stmtsโ ๐งต the max number of statements a block can have and still be allowed to get duplicated when threading jumps ๐ชกmax-jump-thread-pathsโ ๐ค๏ธ the max number of paths to consider when hunting for jump threading opportunities. When the compiler arrives at a block, it only considers incoming edges if (paths searched so far) ร (number of incoming edges) doesn't blow past this max ๐ฆmax-fields-for-field-sensitiveโ ๐ท๏ธ the max number of fields in a structure that gets treated in a field-sensitive way during pointer analysis ๐ฌprefetch-latencyโ โฑ๏ธ an estimate of the average number of instructions executed before a prefetch finishes. The distance prefetched ahead is proportional to this number. Increasing it may also mean fewer streams get prefetched (seesimultaneous-prefetches) ๐โโ๏ธsimultaneous-prefetchesโ ๐ the max number of prefetches that can run at the same time ๐ฅl1-cache-line-sizeโ ๐ the size of a cache line in the L1 data cache, in bytes ๐งฑl1-cache-sizeโ ๐๏ธ the size of the L1 data cache, in kilobytes ๐ฐl2-cache-sizeโ ๐๏ธ the size of the L2 data cache, in kilobytes ๐งprefetch-dynamic-stridesโ ๐ whether the loop array prefetch pass should issue software prefetch hints for strides that aren't constant. Sometimes that's a win, but a non-constant stride can make it hard to tell when the hints will actually help ๐ค- Set to
1if prefetch hints should be issued for non-constant strides. - Set to
0if prefetch hints should only be issued for strides that are known to be constant and belowprefetch-minimum-stride.
- Set to
prefetch-minimum-strideโ ๐ฃ๏ธ the minimum constant stride, in bytes, before prefetch hints start getting used. If the stride is under this threshold, no prefetch hints get issued ๐ง- This one's super useful for processors with hardware prefetchers, since the hardware and software prefetchers can clash. If the hardware prefetchers have a max stride they can handle, put that number here so the software prefetchers get used better ๐ค
- A value of
-1means there's no threshold, so prefetch hints can go out for any constant stride โจ - This 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 are 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 range of L1 cache line sizes, the constructive size is 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 be 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, you can lock the value in place with this option. - The constructive interference size is way less sensitive. It's usually only used in a
static_assertto make sure a type fits inside a cache line ๐ - See also
-Winterference-size.
- The destructive interference size is meant for layout, so it has ABI impact. Its default isn't expected to be stable, and on some targets it changes with
loop-interchange-max-num-stmtsโ ๐ the max number of statements in a loop that can be interchanged ๐งฎloop-interchange-stride-ratioโ โ๏ธ the minimum ratio between the strides of two loops for an interchange to be profitable ๐min-insn-to-prefetch-ratioโ ๐งฎ the minimum ratio between the number of instructions and the number of prefetches needed to enable prefetching 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 enable prefetching in a loop ๐use-canonical-typesโ okay so this one is a toggle for whether the compiler uses the "canonical" type system ๐ It should always be1, because that's the more efficient internal way of comparing types in C++ and Objective-C++ โจ But if bugs in the canonical type system are causing compilation failures, set it to0to turn canonical types off ๐switch-conversion-max-branch-ratioโ switch initialization conversion won't create arrays bigger thanswitch-conversion-max-branch-ratiotimes the number of branches in the switch ๐max-partial-antic-lengthโ caps the length of the partial antic set built during tree partial redundancy elimination (-ftree-pre) when you're optimizing at-O3and up ๐ฅ Some code makes this optimization run totally wild and eat all the memory on the host machine ๐ This limit stops that runaway behavior. Setting it to0means the set length is unlimited ๐ฆrpo-vn-max-loop-depthโ the maximum loop depth that gets value-numbered optimistically ๐ When the limit is hit, the innermostrpo-vn-max-loop-depthloops and the outermost loop in the loop nest get value-numbered optimistically, and the remaining ones don'tsccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries allowed while hunting for redundancies in loads and stores ๐ง If the limit is hit, the search is aborted and that load or store isn't considered redundant. The number of queries is algorithmically capped at the number of stores on all paths from the load to the function entryira-max-loops-numโ IRA uses regional register allocation by default โจ If a function has more loops than this number, only that many of the most frequently executed loops form regions for regional register allocationira-max-conflict-table-sizeโ IRA is super smart about compressing its conflict table, but huge functions can still eat way too much memory ๐ญ If the conflict table for a function could be bigger than this many MB, the register allocator switches to a faster, simpler, lower-quality algorithm that doesn't build a pseudo-register conflict tableira-loop-reserved-regsโ IRA can estimate more accurate register pressure in loops, which helps it decide when to move loop invariants (see-O3) ๐ This sets how many available registers are reserved for other purposes. The default is the best value found from numerous experimentsira-consider-dup-in-all-altsโ makes IRA take matching constraints (duplicated operand numbers) seriously across all available alternatives for the preferred register class ๐ When set to zero, IRA only respects the matching constraint when it's the only available alternative with an appropriate register class. Otherwise, IRA checks every available alternative for the preferred register class, even after it has found a qualified choice, and respects that qualified matching constraintira-simple-lra-insn-thresholdโ the approximate number of function insns, counted in 1K units, that triggers simple local RA ๐ธlra-inheritance-ebb-probability-cutoffโ LRA tries to reuse values that were reloaded into registers in later insns, and this trick is called inheritance ๐ซถ EBB is the region used for this optimization. This parameter sets the minimum fall-through edge probability, as a percentage, needed to add a BB to an inheritance EBB in LRA. The default was picked from numerous SPEC2000 runs onx86-64loop-invariant-max-bbs-in-loopโ loop invariant motion can get really expensive for very large loops, both in compile time and in compile-time memory ๐ Loops with more basic blocks than this parameter won't get loop invariant motion performed on themloop-max-datarefs-for-datadepsโ building data dependencies is expensive for huge loops ๐ This caps the number of data references in loops that get considered for data dependence analysis. Those big loops aren't handled by the optimizations that use loop data dependenciesmax-vartrack-sizeโ the max number of hash table slots allowed while variable tracking dataflow analysis runs on any function ๐ง If this limit gets exceeded with variable tracking at assignments enabled, the analysis for that function is retried without it, after removing all debug insns from the function. If the limit is still exceeded without debug insns, var tracking analysis is completely disabled for that function. Setting it to zero makes it unlimitedmax-vartrack-expr-depthโ the max number of recursion levels when mapping variable names or debug temporaries to value expressions ๐ฆ This trades compile time for more complete debug information. If it's set too low, value expressions that are available and could go in the debug info might not get used. Setting it higher may let the compiler find more complex debug expressions, but compile time and memory use may growmax-debug-marker-countโ a threshold on the number of debug markers (like begin stmt markers) so things don't blow up at inlining or RTL expansion ๐ 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 expansionmin-nondebug-insn-uidโ uids start at this value for nondebug insns โจ The range below it is reserved exclusively for debug insns created by-fvar-tracking-assignments. Debug insns can still get (non-overlapping) uids above it if that reserved range runs outipa-sra-deref-prob-thresholdโ IPA-SRA swaps a pointer that's known not to be NULL for one or more new parameters only when the probability of it being dereferenced (in percent, relative to function entry) is higher than this parameter ๐ฅipa-sra-ptr-growth-factorโ IPA-SRA swaps a pointer to an aggregate for one or more new parameters only when their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter ๐ipa-sra-ptrwrap-growth-factorโ the extra maximum growth allowed in the total size of new parameters that ipa-sra swaps a pointer to an aggregate for ๐ This applies when the pointer points to a local variable that the caller only writes to and passes along as an argument to other functionsipa-sra-max-replacementsโ the max number of pieces of an aggregate that IPA-SRA tracks ๐ง That also makes it the max number of replacements for a formal parametersra-max-scalarization-size-Ospeed,sra-max-scalarization-size-Osizeโ the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) try to swap scalar parts of aggregates for uses of independent scalar variables ๐ซถ These parameters set the max size, in storage units, of an aggregate considered for replacement when compiling for speed (sra-max-scalarization-size-Ospeed) or for size (sra-max-scalarization-size-Osize), respectivelysra-max-propagationsโ the max number of artificial accesses that Scalar Replacement of Aggregates (SRA) tracks per local variable, so copy propagation can happen ๐tm-max-aggregate-sizeโ when making copies of thread-local variables inside a transaction, this is the size in bytes after which variables get saved with the logging functions instead of save/restore code sequence pairs ๐ฅ This only applies when using-fgnu-tmgraphite-max-nb-scop-paramsโ to avoid exponential effects in the Graphite loop transforms, the number of parameters in a Static Control Part (SCoP) is capped ๐ฆ A value of zero lifts the cap. A variable whose value is unknown at compile time and is defined outside a SCoP counts as a parameter of the SCoPhardcfr-max-blocksโ disables-fharden-control-flow-redundancyfor functions with more blocks than this value ๐ Zero removes any limithardcfr-max-inline-blocksโ forces-fharden-control-flow-redundancyto use out-of-line checking for functions with more basic blocks than this value ๐loop-block-tile-sizeโ loop blocking or strip mining (turned on with-floop-blockor-floop-strip-mine) strip mines each loop in the loop nest by a given number of iterations ๐ธ You can change that strip length with this parameteripa-jump-function-lookupsโ the number of statements visited during jump function offset discovery ๐ง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 do devirtualization ๐ This is the max number of values and types it stores for each formal parameter of a functionipa-cp-eval-thresholdโ IPA-CP calculates its own score for cloning profitability, and it goes ahead with 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 ๐ipa-cp-min-recursive-probabilityโ recursive cloning only happens when the probability of the call being executed is higher than this parameter ๐ipa-cp-profile-count-baseโ okay bestie, ๐ when you compile with-fprofile-use, IPA-CP looks at the measured execution count of a call graph edge at this percentage spot in its histogram and uses that as the basis for its heuristics ๐โจipa-cp-recursive-freq-factorโ the number of times interprocedural copy propagation expects recursive functions to call themselves ๐๐ธipa-cp-recursion-penaltyโ the percentage penalty recursive functions take when they're being evaluated for cloning ๐๐ฆipa-cp-single-call-penaltyโ the percentage penalty that functions containing a single call to another function get when they're evaluated for cloning ๐๐ipa-max-agg-itemsโ IPA-CP can also propagate a bunch of scalar values passed inside an aggregate ๐งบ, and this one caps how many of those values you get per parameter ๐ipa-cp-loop-hint-bonusโ when IPA-CP realizes a cloning candidate would make a loop's number of iterations known, it adds this bonus to the 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 IPA-CP analyzes function bodies, it uses alias analysis to track values pointed to by function parameters ๐. To avoid spending forever on huge functions, it gives up after examining this many statements that modify memory and just treats all memory as clobbered ๐ipa-max-switch-predicate-boundsโ the max number of boundary endpoints of case ranges in a switch statement ๐. If a switch goes over this limit, IPA-CP won't build the cloning cost predicate for its default case ๐ โโ๏ธipa-max-param-expr-opsโ IPA-CP looks at conditional statements that reference a function parameter to estimate the benefit of cloning for a certain constant value ๐. But if a parameter expression has more operations than this, it's considered too complicated and IPA analysis skips it ๐ซ
lto-partitionsโ the desired number of partitions made during WHOPR compilation ๐งฉ. It should be bigger than the number of CPUs you're compiling with ๐ปlto-min-partitionโ the minimum size of a WHOPR partition, measured in estimated instructions ๐. This stops tiny programs from getting chopped into way too many pieces ๐lto-max-partitionโ the max size of a WHOPR partition, in estimated instructions ๐. It's basically an upper bound for how big any single partition can get ๐ซถ. It's only meant to be used with balanced partitioning โ๏ธlto-max-streaming-parallelismโ the max number of parallel processes used for LTO streaming ๐โจcxx-max-namespaces-for-diagnostic-helpโ when C++ name lookup fails for an identifier, this is the max number of namespaces the compiler will check for suggestions ๐๐
sink-frequency-thresholdโ the max relative execution frequency (in percent) of the target block compared to a statement's original block, which decides whether a statement can get sunk ๐. Bigger numbers mean more aggressive sinking ๐ฅ. Statements with memory operands get a small positive adjustment, since sinking them is even more profitable ๐max-stores-to-sinkโ the max number of conditional store pairs that can be sunk ๐ณ๏ธ. It's set to0if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is turned off ๐ซcase-values-thresholdโ the smallest number of different values where a jump table is the better move over a tree of conditional branches ๐ณ. If it's0, the compiler uses the default for the machine ๐ฅ๏ธjump-table-max-growth-ratio-for-sizeโ the max code size growth ratio (in percent) when expanding into a jump table ๐ฆ. This one is used when you're optimizing for size ๐คjump-table-max-growth-ratio-for-speedโ same deal as above: the max code size growth ratio (in percent) when expanding into a jump table ๐. This one is used when you're 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, it overrides the target-dependent heuristics that would normally be used ๐sched-pressure-algorithmโ picks between the two available implementations of-fsched-pressure๐ง . Algorithm 1 is the original one, and it's the more likely of the two to stop instructions from getting reordered ๐ . Algorithm 2 was designed as a compromise between algorithm 1's pretty conservative approach and the rather aggressive approach of the default scheduler ๐ข. It leans harder on having a regular register file and accurate register pressure classes ๐. For more details, check outhaifa-sched.ccin the GCC sources ๐๏ธ
The default choice depends on the target ๐ฏ.
max-slsr-cand-scanโ the max number of existing candidates considered when hunting for a basis for a new straight-line strength reduction candidate ๐โจ
asan-globalsโ turns on buffer overflow detection for global objects ๐. This protection is on by default when you use-fsanitize=address. To turn off global objects protection, use--param asan-globals=0๐ โโ๏ธasan-stackโ turns on buffer overflow detection for stack objects ๐ฅ. This is on by default when using-fsanitize=address. To turn off stack protection, use--param asan-stack=0๐ซasan-instrument-readsโ turns on buffer overflow detection for memory reads ๐. It's on by default when using-fsanitize=address. To turn off memory reads protection, use--param asan-instrument-reads=0๐asan-instrument-writesโ turns on buffer overflow detection for memory writes โ๏ธ. It's on by default when using-fsanitize=address. To turn off memory writes protection, use--param asan-instrument-writes=0๐ซasan-memintrinโ turns on detection for built-in functions ๐งฐ. It's on by default when using-fsanitize=address. To turn off built-in functions protection, use--param asan-memintrin=0โasan-use-after-returnโ turns on detection of use-after-return ๐. This is on by default when you use the-fsanitize=addressoption. To turn it off, use--param asan-use-after-return=0๐
Heads up: this check is disabled at run time by default ๐ญ. To enable it, add"detect_stack_use_after_return=1"to theASAN_OPTIONSenvironment variable ๐ธ.
asan-instrumentation-with-call-thresholdโ if a function being instrumented has at least this many memory accesses, the compiler uses callbacks instead of inline checks ๐. For example, to disable inline code, use--param asan-instrumentation-with-call-threshold=0๐งasan-kernel-mem-intrinsic-prefixโ if it's nonzero, calls to"memcpy","memset"and"memmove"get prefixed with__asan_or__hwasan_for-fsanitize=kernel-addressor-fsanitize=kernel-hwaddress, respectively ๐งฉ
hwasan-instrument-stackโ turns on hwasan instrumentation for statically sized stack-allocated variables ๐ฅ. This is enabled by default with-fsanitize=hwaddressand disabled by default with-fsanitize=kernel-hwaddress๐. To turn stack instrumentation off, use--param hwasan-instrument-stack=0, and to turn it on, use--param hwasan-instrument-stack=1๐hwasan-random-frame-tagโ when stack instrumentation is on, tags for stack variables come from a deterministic sequence that starts at a random tag for each frame ๐ฒ. If this parameter isn't set, the tags use the same sequence but start from11๏ธโฃ. It's enabled by default for-fsanitize=hwaddressand unavailable for-fsanitize=kernel-hwaddress๐ . To turn it off, use--param hwasan-random-frame-tag=0๐ซถhwasan-instrument-allocasโ turns on hwasan instrumentation for dynamically sized stack-allocated variables ๐. Like the stack one, it's enabled by default with-fsanitize=hwaddressand disabled 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โ turns on hwasan checks on memory reads ๐๏ธ. Read instrumentation is enabled by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddressโจ. To stop checking memory reads, use--param hwasan-instrument-reads=0๐hwasan-instrument-writesโ turns on hwasan checks on memory writes โ๏ธ. Write instrumentation is 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โ turns on hwasan instrumentation for built-in functions ๐งฐ. This is enabled by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress๐. To turn off instrumentation of built-in functions, use--param hwasan-instrument-mem-intrinsics=0โ
use-after-scope-direct-emission-thresholdโ if a local variable's size in bytes is less than or equal to this number, the 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()๐ฆ๐ฅ
๐ Parloops, Vectorizer, and Friends ๐
okay bestie, this next batch is all --param knobs, and they're giving tuning fork energy ๐ถ each one controls how a specific optimization pass behaves ๐
max-fsm-thread-path-insns๐ฆ โ the max number of instructions copied when duplicating blocks on a finite state automaton jump thread path.threader-debug๐ โthreader-debug=[none|all]turns on verbose dumping for the threader solver. Super useful when you're trying to see what it's thinking ๐งparloops-chunk-size๐งฉ โ the chunk size of the omp schedule for loops thatparloopsparallelizes.parloops-schedule๐ โ the schedule type of the omp schedule for those same parallelized loops. You can pickstatic,dynamic,guided,auto, orruntime๐parloops-min-per-thread๐งต โ the minimum number of iterations per thread for an innermost parallelized loop, where the parallel version beats the single-threaded one. Heads up: for a parallelized loop nest, the minimum iterations of the outermost loop per thread is two โจmax-ssa-name-query-depth๐ โ how deep the recursion can go when querying properties of SSA names in things like fold routines. One level of recursion means following a use-def chain ๐max-speculative-devirt-maydefs๐ โ the max number of may-defs we analyze while hunting for a must-def that tells us the dynamic type of an object making a virtual call we might speculatively devirtualize. Big brain stuff ๐ง ๐ranger-debug๐จ๏ธ โ picks the type of debug output printed for ranges.unroll-jam-min-percent๐ โ the minimum percentage of memory references that have to get optimized away for unroll-and-jam to count as profitable.unroll-jam-max-unroll๐ โ the max number of times the outer loop can be unrolled by unroll-and-jam.max-rtl-if-conversion-unpredictable-cost๐ธ โ the most expensive the sequence from the RTL if-conversion pass can be for a branch that's considered unpredictable.max-variable-expansions-in-unroller๐ช โ if-fvariable-expansion-in-unrolleris on, this caps how many times one variable gets expanded during loop unrolling.partial-inlining-entry-probability๐ฏ โ the max 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๐ โ how many strings the strlen optimization pass will track lengths for.gcse-after-reload-partial-fractionโ๏ธ โ the threshold ratio for doing partial redundancy elimination after reload.gcse-after-reload-critical-fraction๐ค๏ธ โ the threshold ratio of critical edge execution count that lets redundancy elimination happen after reload.max-loop-header-insns๐งพ โ the max number of insns in a loop header that the copy loop headers pass will duplicate.vect-epilogues-nomask๐ง โ turns on loop epilogue vectorization using a smaller vector size.vect-partial-vector-usage๐งฉ โ decides when the loop vectorizer will use partial vector loads and stores instead of falling back to scalar code:0means the vectorizer never uses partial vector loads and stores ๐ซ1allows them only if vectorizing removes the need for the code to iterate2allows them in all loops
This only does something on targets that actually support partial vector loads and stores ๐ฏ
vect-inner-loop-cost-factor๐งฎ โ the max factor the loop vectorizer applies to the cost of statements in an inner loop, compared to the loop being vectorized. The factor used is the max of the estimated inner loop iteration count and this parameter. The default value is50๐ฏvect-induction-float๐ โ enables loop vectorization of floating point inductions.vrp-sparse-threshold๐ธ๏ธ โ the max number of basic blocks before VRP switches to a sparse bitmap cache.vrp-switch-limit๐ โ the max number of outgoing edges in a switch before VRP just skips it.vrp-vector-threshold๐ฆ โ the max number of basic blocks for VRP to use a basic cache vector.avoid-fma-max-bits๐ โโ๏ธ โ the max number of bits for which we avoid creating FMAs.fully-pipelined-fma๐ฐ โ whether the target fully pipelines FMA instructions. If it's non-zero, reassociation weighs the benefit of parallelizing the FMUL part and the FADD part, assuming FMUL and FMA use the same units that can also do FADD ๐งsms-loop-average-count-threshold๐ข โ a threshold on the average loop count the swing modulo scheduler considers.sms-dfa-history๐ฐ๏ธ โ how many cycles the swing modulo scheduler looks at when checking for conflicts using DFA.graphite-allow-codegen-errors๐จ โ whether codegen errors should be ICEs when-fcheckingis on.sms-max-ii-factor๐๏ธ โ a factor for tuning the upper bound the swing modulo scheduler uses when scheduling a loop.lra-max-considered-reload-pseudos๐ โ the max number of reload pseudos considered while spilling a non-reload pseudo.max-pow-sqrt-depth๐ณ โ the max depth of sqrt chains used when synthesizing exponentiation by a real constant.max-dse-active-local-stores๐๏ธ โ the max number of active local stores in RTL dead store elimination.asan-instrument-allocas๐ก๏ธ โ turns on asan protection for allocas and VLAs.max-iterations-computation-cost๐ฐ โ a bound on the cost of an expression used to compute the number of iterations.max-isl-operationsโพ๏ธ โ the max number of isl operations.0means unlimited.graphite-max-arrays-per-scop๐งบ โ the max 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 comparing against--param=max-jump-thread-duplication-stmts.uninit-control-dep-attempts๐ โ the max number of nested calls used to search for control dependencies during uninitialized variable analysis.uninit-max-chain-lenโ๏ธ โ the max number of predicates anded together for each predicate ored in the normalized predicate chain.uninit-max-num-chains๐ โ the max number of predicates ored together in the normalized predicate chain.sched-autopref-queue-depth๐งญ โ a control flag for the hardware autoprefetcher scheduler model. It's the number of lookahead cycles the model looks into. At' ', it only enables the instruction sorting heuristic ๐loop-versioning-max-inner-insns๐ช โ the max number of instructions an inner loop can have before the loop versioning pass decides it's too big to copy.loop-versioning-max-outer-insns๐ช โ the max number of instructions an outer loop can have before the loop versioning pass decides it's too big to copy. Any instructions in inner loops that directly benefit from versioning don't count toward this ๐ssa-name-def-chain-limitโ๏ธโ๐ฅ โ the max number of SSA_NAME assignments to follow when figuring out a property of a variable, like its value. This caps the iterations or recursive calls GCC makes when optimizing certain statements or checking whether they're valid before issuing diagnostics ๐งstore-merging-max-size๐ฆ โ the max size of a single store merging region, in bytes.hash-table-verification-limitโ โ the number of elements that get hash table verification for each searched element.max-find-base-term-values๐ โ the max number of VALUEs handled during a singlefind_base_termcall.analyzer-max-enodes-per-program-point๐ โ the max number of exploded nodes per program point in the analyzer. Once it hits this, analysis of that point stops ๐analyzer-max-constraints๐งฑ โ the max number of constraints per state.analyzer-min-snodes-for-call-summary๐ โ the min number of supernodes inside a function before the analyzer considers summarizing its effects at call sites.analyzer-max-enodes-for-full-dump๐บ๏ธ โ the max 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 max number of times a callsite can appear in a call stack within the analyzer. Past that, analysis of a call that would recurse deeper gets terminated ๐analyzer-max-svalue-depth๐ช โ the max depth of a symbolic value before the analyzer approximates it as unknown โanalyzer-max-infeasible-edges๐ซ โ the max number of infeasible edges to put up with before a diagnostic gets declared infeasible.gimple-fe-computed-hot-bb-threshold๐ฅ โ the number of executions of a basic block that counts as hot. This parameter is only used in the GIMPLE FE ๐งชanalyzer-bb-explosion-factor๐ฅ โ the max number of "after supernode" exploded nodes per supernode in the analyzer, before analysis gets terminated.analyzer-text-art-string-ellipsis-thresholdโ๏ธ โ the number of bytes where string literals get ellipsized in analyzer text art diagrams.analyzer-text-art-ideal-canvas-width๐ผ๏ธ โ the ideal width, in characters, of text art diagrams the analyzer generates.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 max depth of logical expression evaluation that ranger looks through when evaluating outgoing edge ranges.ranger-recompute-depth๐ โ the max depth of instruction chains considered for recomputation in the outgoing range calculator.relation-block-limit๐ง โ the max number of relations the oracle will register in a basic block.min-pagesizeโ the minimum page size, used for warning purposes ๐โจopenacc-kernelsโ this one decides how OpenACCkernelsconstructs get handled ๐--param=openacc-kernels=decomposeโ thekernelsconstructs get split into parts, a sequence of compute constructs, and each part is handled individually. This is work in progress ๐ง--param=openacc-kernels=parloopsโ thekernelsconstructs are handled by the parloops pass, en bloc. This is the current default ๐
openacc-privatizationโ controls whether-fopt-info-omp-noteand applicable-fdump-tree-*-detailsoptions print OpenACC privatization diagnostics ๐--param=openacc-privatization=quietโ no diagnostics. This is the current default ๐คซ--param=openacc-privatization=noisyโ yep, do diagnose ๐ข
The following choices of name are available on AArch64 targets ๐ฆพ
aarch64-vect-compare-costsโ when vectorizing, GCC can try a bunch of 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, instead of 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 used to calculate 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 used to calculate 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. It accepts values from0to4, inclusive ๐ง0โ use the default heuristics1โ use only Advanced SIMD for auto-vectorization2โ use only SVE for auto-vectorization3โ use both Advanced SIMD and SVE, and prefer Advanced SIMD when the costs are deemed equal4โ use both Advanced SIMD and SVE, and prefer SVE when the costs are deemed equal
The default value is 0.
aarch64-ldp-policyโ the fine-grained policy for load pairs ๐--param=aarch64-ldp-policy=defaultโ use the policy of the tuning structure. This is the current default ๐--param=aarch64-ldp-policy=alwaysโ emitldpregardless of alignment--param=aarch64-ldp-policy=neverโ do not emitldp--param=aarch64-ldp-policy=alignedโ emitldponly if the source pointer is aligned to at least double the alignment of the type
aarch64-stp-policyโ the fine-grained policy for store pairs ๐--param=aarch64-stp-policy=defaultโ use the policy of the tuning structure. This is the current default ๐--param=aarch64-stp-policy=alwaysโ emitstpregardless of alignment--param=aarch64-stp-policy=neverโ do not emitstp--param=aarch64-stp-policy=alignedโ emitstponly if the source pointer is aligned to at least double the alignment of the type
aarch64-ldp-alias-check-limitโ the limit on the number of alias checks the AArch64 load/store pair fusion pass performs when it's trying to form anldp/stp๐ง Higher values make the pass more aggressive about re-ordering loads over stores, but at the cost of increased compile time โณaarch64-ldp-writebackโ controls which writeback opportunities get handled in the AArch64 load/store pair fusion pass ๐ฆ- a value of
0disables writeback handling - a value of
1means it tries to form pairs involving one or more existing individual writeback accesses where possible - a value of
2means it also tries to opportunistically form writeback opportunities by folding in trailing destructive updates of the base register used by a pair
- a value of
aarch64-loop-vect-issue-rate-nitersโ some AArch64 CPU tuning tries to weigh both latencies and issue rates when deciding whether a loop gets vectorized with SVE, vectorized with Advanced SIMD, or not vectorized at all ๐ค If this parameter is set ton, GCC will not use this heuristic for loops that are known to execute in fewer thannAdvanced SIMD iterationsaarch64-vect-unroll-limitโ the vectorizer uses available tuning information to figure out whether it would be beneficial to unroll the main vectorized loop, and by how much. This param sets the upper bound on how much the vectorizer will unroll the 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:default,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 an STFL stall penalty can be compensated ๐ซถx86-stv-max-visitsโ the maximum number of use and def visits when discovering an STV chain. If that count gets hit before discovery finishes, the discovery is aborted ๐
โจ Program Instrumentation Options โจ
okay so GCC can add a whole bunch of run-time instrumentation to the code it normally generates ๐ต๏ธโโ๏ธ๐ One reason to do this is to collect profiling stats so you can find program hot spots, do code coverage analysis, or run profile-guided optimizations ๐ Another kind is run-time checking, which catches programming errors like invalid pointer dereferences or out-of-bounds array accesses. It also helps against deliberately hostile attacks like stack smashing or C++ vtable hijacking ๐ก๏ธ And there's a general hook you can use to build other forms of tracing or function-level instrumentation for debugging or program analysis ๐งฉ
-p,-pgโ generates extra code to write profile information suitable for the analysis programprof(for-p) orgprof(for-pg) ๐ You must use this option when compiling the source files you want data about, and you must also use it when linking- you can use the function attribute
no_instrument_functionto suppress profiling of individual functions when compiling with these options ๐
- you can use the function attribute
-fprofile-arcsโ adds code so that program flow arcs are instrumented ๐น- during execution, the program records how many times each branch and call is executed, and how many times it is taken or returns. On targets that support constructors with priority support, profiling properly handles constructors, destructors, and C++ constructors (and destructors) of classes that are used as the type of a global variable ๐งฑ
- when the compiled program exits, it saves this data to a file called
auxname.gcdafor each source file. The data may be used for profile-directed optimizations (-fbranch-probabilities), or for test coverage analysis (-ftest-coverage) ๐ - each object file's
auxnameis generated from the name of the output file, if it's explicitly specified and it is not the final executable. Otherwise it's the basename of the source file. In both cases any suffix is removed. For example,foo.gcdafor input filedir/foo.c, ordir/foo.gcdafor output file specified as-o dir/foo.o๐ - note that if a command line directly links source files, the corresponding
.gcdafiles will be prefixed with the unsuffixed name of the output file. E.g.gcc a.c b.c -o binarywould generatebinary-a.gcdaandbinary-b.gcdafiles ๐
-fcondition-coverageโ adds code so that program conditions are instrumented ๐งช During execution, the program records which terms in a conditional contribute to a decision. You can use this to verify that all terms in a Boolean function are tested and have an independent effect on the outcome of a decision. The result can be read withgcov --conditions๐ฆ--coverageโ the option you use to compile and link code instrumented for coverage analysis ๐ It's a synonym for-fprofile-arcs-ftest-coverage(when compiling) and-lgcov(when linking). See the documentation for those options for more details ๐- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, use the additional-ftest-coverageoption. You don't need to profile every source file in a program ๐ - Compile the source files additionally with
-fprofile-abs-pathto create absolute path names in the.gcnofiles. This lets gcov find the correct sources in projects where compilations happen with different working directories ๐บ๏ธ - Link your object files with
-lgcovor-fprofile-arcs(the latter implies the former) ๐ - Run the program on a representative workload to generate the arc profile information. This may be repeated any number of times. You can run concurrent instances of your program, and provided that the file system supports locking, the data files will be correctly updated. Unless a strict ISO C dialect option is in effect, "fork" calls are detected and correctly handled without double counting ๐ด
- Compile the source files with
Moreover, an object file can be recompiled multiple times, and the corresponding .gcda file merges as long as the source file and the compiler options are unchanged ๐ซถ
- For profile-directed optimizations, compile the source files again with the same optimization and code generation options plus
-fbranch-probabilities๐ - For test coverage analysis, use
gcovto produce human-readable information from the.gcnoand.gcdafiles. Refer to the gcov documentation for further information ๐ง
With -fprofile-arcs, GCC builds a program flow graph for every function in your program and then finds a spanning tree for it โจ Only the arcs that aren't on that tree need instrumenting, so the compiler just adds code to count how many times those arcs get executed ๐ง If an arc is the only exit or only entrance to a block, the counting code can go right into that block. Otherwise GCC has to make a brand new basic block to hold it ๐ซถ
And with -fcondition-coverage, GCC creates a bitset for each conditional in your program and records the exercised boolean values that have an independent effect on the outcome of that expression ๐ฆ
-ftest-coverageโ okay bestie, this one makes a notes file that thegcovcode-coverage utility can use to show your program coverage ๐ Each source file's notes file is calledauxname.gcno. Check the-fprofile-arcsentry above for what auxname means and how to generate test coverage data. Also, coverage data matches your source files way more closely if you don't optimize ๐-fprofile-abs-pathโ this automatically turns relative source file names into absolute path names inside the.gcnofiles ๐บ๏ธ That waygcovcan find the right sources even in projects that compile from different working directories ๐-fprofile-dir=pathโ sets the directory where profile data files get searched for to path ๐ This only affects the profile data made by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-useand-fbranch-probabilitiesplus its related options. Both absolute and relative paths work. By default GCC uses the current directory, so the profile data file lands in the same directory as the object file. To avoid file name clashes, if the object file name isn't an absolute path, GCC mangles the absolute path of the sourcename.gcdafile and uses that as the name of the.gcdafile. Peek-fprofile-arcsfor the full file naming details. There's also a similar option,-fprofile-note. When an executable runs in a massive parallel environment, it's recommended to save profiles to different folders ๐ You can do that with variables in 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 turns on the options you usually want for instrumenting an app so it can produce a profile for later recompilation with profile feedback based optimization ๐ฅ You must use-fprofile-generateboth when compiling and when linking your program ๐จ It enables-fprofile-arcs,-fprofile-values,-finline-functions, and-fipa-bit-cp. If path is specified, GCC looks there for the profile feedback data files (see-fprofile-dir). To optimize the program based on the collected profile information, use-fprofile-useโจ-fprofile-info-section,-fprofile-info-section=nameโ this registers the profile information in a specified section instead of using a constructor/destructor ๐งฉ The section name is name if you give one, otherwise it defaults to.gcov_info. A pointer to the profile information made by-fprofile-arcsgets placed in that section for each translation unit. This option turns off the profile information registration through a constructor, and it also turns off the profile information processing through a destructor. Heads up: this is not meant for hosted environments like GNU/Linux ๐ โโ๏ธ It targets freestanding environments (like embedded systems) with limited resources that don't support constructors/destructors or C library file I/O.
The linker could 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 = .);
}
The program could then dump the profiling information registered in this 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, then merge the profile information into .gcda files on the host filesystem ๐
-fprofile-note=pathโ if path is specified, GCC saves the.gcnofile into that location ๐ Heads up: if you combine this with multiple source files, the.gcnofile will get overwritten ๐ญ-fprofile-prefix-path=pathโ use this withprofile-generate=profile_dirandprofile-use=profile_dirto tell GCC where the base directory of your built source tree is ๐ณ By default, profile_dir will contain files with mangled absolute paths of all object files in the built project. That's not ideal when the directory used to build the instrumented binary is different from the one used to build the binary optimized with profile feedback, because the profile data won't be found during the optimized build ๐ In setups like that,-fprofile-prefix-path=path, with path pointing to the base directory of the build, strips the irrelevant part of the path and keeps all file names relative to the main build directory โจ-fprofile-prefix-map=old=newโ when compiling files living in directory old, GCC records their profiling information (with--coverage) as if they lived in directory new instead ๐บ๏ธ 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 ๐ The method argument should be one ofsingle,atomic, orprefer-atomic. The first one is good for single-threaded apps, and the second one prevents profile corruption by emitting thread-safe code ๐งต
Warning: When an application doesn't properly join all threads (or creates a detached thread), a profile file can still get corrupted ๐ฑ
Using prefer-atomic gets transformed either into atomic (when the target supports it) or into single otherwise. The GCC driver automatically picks prefer-atomic when -pthread is in the command line. Otherwise the default method is single ๐
If atomic is selected, the profile information is updated using atomic operations on a best-effort basis. Ideally, it's updated through atomic operations 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 required hardware atomics nor libatomic, the profile information is not atomically updated and a warning is issued. In that case, the profiling information may be corrupt for multi-threaded applications ๐ฅฒ
For performance reasons, if 64-bit counters are used for the profiling information and the target platform only supports 32-bit atomic operations in hardware, then the performance critical profiling updates are done using two 32-bit atomic operations for each counter update. If a signal interrupts these two operations while updating a counter, the profiling information may end up in an inconsistent state ๐
-fprofile-filter-files=regexโ instruments only the functions from files whose name matches any of the regular expressions (separated by semicolons) ๐ For example,-fprofile-filter-files=main\.c;module.*\.cwill instrument onlymain.cand all C files starting with 'module' ๐ง-fprofile-exclude-files=regexโ instruments only the functions from files whose name does not match any of the regular expressions (separated by semicolons) ๐ซ For example,-fprofile-exclude-files=/usr/.*will prevent instrumentation of all files located in the/usr/folder ๐ โโ๏ธ-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ controls the level of reproducibility of the profile gathered by-fprofile-generate๐ง This 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-generateis 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 theforkfunction is invoked ๐ซถ
Okay so bestie, here's the deal with reproducibility ๐งโจ: execution counts in some parts of a program can depend on stuff like how long temporary file names are, or on memory space randomization (which can shift the hash-table collision rate) ๐. That non-reproducible bit can be marked with the "no_instrument_function" function attribute ๐
. And if you want to check that your gathered data is actually reproducible, gcov-dump with -l can dump it out so you can see for yourself ๐.
With -fprofile-reproducible=parallel-runs, the collected profile stays reproducible no matter what order the data gets streamed into the gcda files ๐. This is the move if you want to run multiple instances of your instrumented program in parallel, like with make -j ๐โโ๏ธ. Just know it's a trade-off: it reduces the quality of the gathered data, especially for indirect call profiling ๐ญ.
-fsanitize=addressโ Turns on AddressSanitizer ๐ฆ, a super fast memory error detector. Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs, and it also enables-fsanitize-address-use-after-scope. More details live athttps://github.com/google/sanitizers/wiki/AddressSanitizer. Run-time behavior can be tweaked with theASAN_OPTIONSenvironment variable, and if you set it to "help=1", the available options get shown when your instrumented program starts. For the full list of supported options, peephttps://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags. This one can't be combined with-fsanitize=threador-fsanitize=hwaddress๐ โโ๏ธ, and the only target-fsanitize=hwaddressis currently supported on is AArch64.
To get more accurate stack traces ๐ฅ, you can use options like -O0, -O1, or -Og (which, for instance, prevent most function inlining), -fno-optimize-sibling-calls (which stops sibling and tail recursive calls from getting optimized; this option is implicit for -O0, -O1, or -Og), or -fno-ipa-icf (which disables Identical Code Folding for functions). Since multiple runs of the program can give you backtraces with different addresses thanks to ASLR (Address Space Layout Randomization), it may be desirable to turn ASLR off ๐. On Linux, you can do that with:
setarch `uname -m` -R ./prog
-fsanitize=kernel-addressโ Enables AddressSanitizer for the Linux kernel ๐ง. Check outhttps://github.com/google/kernel-sanitizersfor more details.-fsanitize=hwaddressโ Hardware-assisted AddressSanitizer ๐ ๏ธ uses a hardware ability to ignore the top byte of a pointer, so it can catch memory errors with a low memory overhead ๐. Memory access instructions get instrumented to detect out-of-bounds and use-after-free bugs. It enables-fsanitize-address-use-after-scope. Seehttps://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.htmlfor more details. Run-time behavior is influenced through theHWASAN_OPTIONSenvironment variable, and when it's set to "help=1", the available options show at startup of the instrumented program. It can't be combined with-fsanitize=threador-fsanitize=address, and it's currently only available on AArch64 ๐.-fsanitize=kernel-hwaddressโ Enables Hardware-assisted AddressSanitizer for compiling the Linux kernel ๐งโจ. It's similar to-fsanitize=kernel-addressbut uses an alternate instrumentation method, and it's similar to-fsanitize=hwaddressbut with the instrumentation differences the kernel needs. 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 to-fsanitize=hwaddress. Instrumenting the stack and alloca calls is not on by default, but it's still possible by specifying 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 ๐. It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it can't be combined with-fsanitize=thread. Note: by default the check is disabled at run time ๐ด. To turn it on, add "detect_invalid_pointer_pairs=2" to theASAN_OPTIONSenvironment variable. Using "detect_invalid_pointer_pairs=1" only detects invalid operation 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 can't be combined with-fsanitize=thread. Note: by default the check is disabled at run time ๐ด. To enable it, add "detect_invalid_pointer_pairs=2" to theASAN_OPTIONSenvironment variable. Using "detect_invalid_pointer_pairs=1" only detects invalid operation when both pointers are non-null.-fsanitize=shadow-call-stackโ Enables 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 the shadow call stack in the function epilogue. Instrumentation only happens in functions that need to save the return address to the stack.
Heads up, this one's picky ๐
: it's currently only supported on 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 feature in user space, you need to provide your own runtime support. It should be noted that this may cause the ABI rules to be broken ๐จ.
On aarch64, the instrumentation makes use of the platform register "x18" ๐ง . That generally means any code that may run on the same thread as code compiled with ShadowCallStack must be compiled with the flag -ffixed-x18. Otherwise, functions compiled without -ffixed-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 off exceptions ๐
โโ๏ธ. See https://clang.llvm.org/docs/ShadowCallStack.html for more details.
-fsanitize=threadโ Enables ThreadSanitizer ๐งต, a fast data race detector. Memory access instructions get instrumented to detect data race bugs. Seehttps://github.com/google/sanitizers/wiki#threadsanitizerfor more details. The run-time behavior can be influenced using theTSAN_OPTIONSenvironment variable; seehttps://github.com/google/sanitizers/wiki/ThreadSanitizerFlagsfor a list of supported options. It can't be combined with-fsanitize=addressor-fsanitize=leak๐ซ.
Note that sanitized atomic builtins cannot throw exceptions when operating on invalid memory addresses with non-call exceptions (-fnon-call-exceptions).
-fsanitize=leakโ Enables LeakSanitizer ๐ง, a memory leak detector. This option only matters for linking executables. The executable gets linked against a library that overrides "malloc" and other allocator functions. Seehttps://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizerfor more details. The run-time behavior can be influenced using theLSAN_OPTIONSenvironment variable. It can't be combined with-fsanitize=thread.-fsanitize=undefinedโ Enables UndefinedBehaviorSanitizer ๐, a fast undefined behavior detector. Various computations get instrumented to catch undefined behavior at runtime. Seehttps://clang.llvm.org/docs/UndefinedBehaviorSanitizer.htmlfor more details. The run-time behavior can be influenced using theUBSAN_OPTIONSenvironment variable. These are the current suboptions:-fsanitize=shiftโ Checks that the result of a shift operation isn't undefined ๐ซถ. What's considered undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc. This option has two suboptions,-fsanitize=shift-baseand-fsanitize=shift-exponent.-fsanitize=shift-exponentโ Checks that the second argument of a shift operation 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, checks that the result of the shift isn't undefined. What's considered 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 you reach the__builtin_unreachablecall, 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 have to be taken into account, which means the following is not an overflow ๐:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ okay so this one turns on array bounds instrumentation ๐ and catches a bunch of out-of-bounds accesses ๐ . 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 that-fstrict-flex-arrays,-fstrict-flex-arrays=, or thestrict_flex_arrayattribute say shouldn't be treated that way do get checked ๐ฆ-fsanitize=bounds-strictโ the stricter, no-excuses version ๐ฅ It catches most out-of-bounds accesses, including flexible-array-member-like arrays. Initializers of variables with static storage still aren't instrumented ๐-fsanitize=alignmentโ checks pointer alignment when a pointer gets dereferenced ๐ธ It also checks when a reference is bound to an insufficiently aligned target, and when a method or constructor gets called on an insufficiently aligned object โจ-fsanitize=object-sizeโ instruments memory references using the__builtin_dynamic_object_sizefunction ๐ง It's how various out-of-bounds pointer accesses get detected ๐-fsanitize=float-divide-by-zeroโ detects floating-point division by zero ๐ Unlike other similar options, this one is not turned on by-fsanitize=undefined, because dividing by zero in floating point can be a legit way to get infinities and NaNs ๐คทโโ๏ธ-fsanitize=float-cast-overflowโ enables checking whenever a floating-point value gets converted to an integer ๐ It makes sure the result of that conversion doesn't overflow โจ Also, this one is not turned on by-fsanitize=undefined, just like the other special ones ๐
Heads up bestie: this option does not work well with FE_INVALID exceptions 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 ๐ซถ-fsanitize=returns-nonnull-attributeโ instruments return statements in functions marked with thereturns_nonnullfunction attribute ๐ฆ It catches those functions returning null values, which is a big no-no ๐-fsanitize=boolโ instruments loads frombool๐ If a value other than 0/1 gets loaded, you get a run-time error ๐จ-fsanitize=enumโ instruments loads from an enum type ๐ If a value outside the enum's range of values 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 the referenced object has the correct dynamic type, so nothing sneaky happens ๐ง-fsanitize=pointer-overflowโ instruments pointer arithmetic ๐ธ If the pointer arithmetic overflows, a run-time error is issued ๐ฅ-fsanitize=builtinโ instruments the arguments to selected builtin functions ๐ If an invalid value gets passed to one of those arguments, a run-time error is issued โญ For example, passing0as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior, and this option diagnoses it ๐
Quick vibe check on sanitizers in general: they tend to bring along extra false positive warnings, especially the ones around -Wmaybe-uninitialized ๐ญ We recommend against combining -Werror and the use of sanitizers, so you don't get stuck on warnings that aren't even real ๐ซถ
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 the sanitizers you turned on before ๐งน Note that-fsanitize=allis not allowed, because some sanitizers can't be used together ๐-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks โจ It's super useful for experimenting with different shadow memory layouts in Kernel AddressSanitizer ๐งช-fsanitize-sections=s1,s2,...โ sanitizes global variables in selected user-defined sections ๐ฆ Eachsimay contain wildcards ๐ธ-fsanitize-recover[=opts]โ okay this one controls the error recovery mode for the sanitizers in the comma-separated list ofopts๐ When recovery is enabled for a sanitizer, the program keeps running like no error happened ๐ซ That means multiple runtime errors can get reported in one run, and the exit code may say success even when errors were reported ๐
The -fno-sanitize-recover= option flips that around: only the first detected error gets reported, and then the program exits with a non-zero exit code ๐ซ
Right now this feature only works for -fsanitize=undefined (and its suboptions, except -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 first enables recovery for all sanitizers that support it, and the second disables recovery for all sanitizers that support it โจ
Even if recovery mode is turned on at 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 this opts list:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ enables sanitization of local variables so you can catch use-after-scope bugs ๐ต๏ธโโ๏ธ This option sets-fstack-reusetonone๐ซถ-fsanitize-trap[=opts]โ this one tells the compiler to report undefined behavior for the sanitizers in the comma-separatedoptslist using__builtin_trapinstead of alibubsanlibrary routine ๐ชค If it's enabled for a sanitizer, it takes precedence over-fsanitizer-recover=for that sanitizer, so__builtin_trapgets emitted and it's fatal whether recovery is on or off ๐- The big perk is that the
libubsanlibrary isn't needed and isn't linked in, so this works even in freestanding environments ๐ง - Right now it works with
-fsanitize=undefined(and its suboptions, except-fsanitize=vptr),-fsanitize=float-cast-overflow,-fsanitize=float-divide-by-zero, and-fsanitize=bounds-strict๐ -fsanitize-trap=allcan also be specified, which enables it for theundefinedsuboptions,-fsanitize=float-cast-overflow,-fsanitize=float-divide-by-zero, and-fsanitize=bounds-strict๐- If
-fsanitize-trap=undefinedor-fsanitize-trap=allis used and-fsanitize=vptris enabled on the command line, the instrumentation is silently ignored ๐ค That's because the instrumentation always needslibubsansupport ๐ -fsanitize-trap=vptris not allowed ๐ซ
- The big perk is that the
-fsanitize-undefined-trap-on-errorโ this one is deprecated, but it's an equivalent of-fsanitize-trap=all๐ฅ-fsanitize-coverage=trace-pcโ enables coverage-guided fuzzing code instrumentation ๐ It inserts a call to__sanitizer_cov_trace_pcinto every basic block ๐งฉ-fsanitize-coverage=trace-cmpโ enables dataflow guided fuzzing code instrumentation ๐ Here's who gets called when:__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4, or__sanitizer_cov_trace_cmp8for integral comparisons where both operands are variables ๐ข__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4, or__sanitizer_cov_trace_const_cmp8for integral comparisons where one operand is a constant ๐ฏ__sanitizer_cov_trace_cmpfor__sanitizer_cov_trace_cmpdfor float or double comparisons ๐ฆ__sanitizer_cov_trace_switchfor switch statements ๐
-fcf-protection=[full|branch|return|none|check]โ enables code instrumentation of control-flow transfers to boost program security ๐ก๏ธ It checks that the target addresses of control-flow transfer instructions (like indirect function calls, function returns, and indirect jumps) are valid, so the flow of control can't get diverted to some unexpected target ๐ This is meant to protect against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP) ๐branchchecks validity of control-flow transfers at indirect branch instructions, i.e. call/jmp instructions ๐ฟreturnchecks validity at the point of returning from a function ๐fullis an alias for specifying bothbranchandreturn๐noneturns off instrumentation ๐ซ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 ๐จ It's ignored at compile time ๐
To override -fcf-protection, you need to add -fcf-protection=none and then add -fcf-protection=xxx after it ๐
The __CET__ macro 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 ๐
โโ๏ธ
Currently, the x86 GNU/Linux target provides an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processors or newer ๐ป
NOTE: NOTE: In Ubuntu 19.10 and later versions, -fcf-protection gets turned on by default for C, C++, ObjC, and ObjC++ ๐, as long as neither -fno-cf-protection nor -fcf-protection=* shows up in your command ๐ซถ.
๐ -fharden-compares
okay so this one goes after every logical test that makes it through gimple optimizations and isn't the condition in a conditional branch ๐. Think conditional moves, or tests stored in boolean variables. GCC adds extra code that computes and verifies the reversed condition, and if the results don't match it calls __builtin_trap ๐. Pair it with -fharden-conditional-branches to cover all the conditionals, bestie โจ.
๐ฆ -fharden-conditional-branches
For every non-vectorized conditional branch that survives gimple optimizations, GCC adds extra code that computes and verifies the reversed condition ๐ฅ. If the result is unexpected, it calls __builtin_trap. Use it with -fharden-compares so nothing slips through ๐
.
๐ธ -fharden-control-flow-redundancy
this one is giving main character energy ๐. GCC emits extra code that sets booleans when it enters basic blocks, then at function exits it verifies them and traps if they don't form an execution path that matches the control flow graph ๐ญ.
The verification happens before returns, and before mandatory tail calls (more on those below). It can also happen, if you ask for it, 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 tuning knobs too: --param hardcfr-max-blocks and --param hardcfr-max-inline-blocks โ๏ธ.
Tail call optimization happens too late to mess with 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. But honestly these cases are merely theoretical, since they can only come up when you're using custom compiler plugins ๐ง.
๐ง -fhardcfr-skip-leaf
Disables -fharden-control-flow-redundancy in leaf functions ๐ฟ.
๐ -fhardcfr-check-exceptions
When -fharden-control-flow-redundancy is active, the recorded execution path gets checked against the control flow graph at exception escape points ๐ฆ. It's like the function body is wrapped in a cleanup handler that does the check and then reraises. This one is enabled by default โจ. If you want it gone, use -fno-hardcfr-check-exceptions.
๐ -fhardcfr-check-returning-calls
When -fharden-control-flow-redundancy is active, the recorded path gets checked before any function call that's immediately followed by a return of its result (if it has one) ๐
. This keeps tail-call optimization working, whether or not the call actually ends up optimized into a tail call.
This option is enabled by default whenever sibling call optimizations are on (see -foptimize-sibling-calls) ๐ซถ. But you can flip it on or off explicitly with its negated form, no matter what the optimizations are doing.
๐ -fhardcfr-check-noreturn-calls=[always|no-xthrow|nothrow|never]
When -fharden-control-flow-redundancy is active, the recorded path gets checked before noreturn calls. You get to pick which ones:
alwaysโ checks before all of them ๐no-xthrowโ checks before those not expected to return control to the caller through an exception. This is the default ๐nothrowโ checks before those that may not return control to the caller through an exception either ๐ธneverโ checks before none of them ๐
Checking before a noreturn function that may return control through an exception can get you checked more than once, if the caller catches that exception with a handler or a cleanup ๐ญ. When -fhardcfr-check-exceptions is also on, the compiler skips associating a noreturn call with the implicit cleanup handler, since it'd be redundant with the check before the call โจ. Other handlers or cleanups in the function, if they're activated, will modify the recorded path and check it again when another checkpoint gets hit. That checkpoint could even be another noreturn call, so the checking may end up happening multiple times ๐.
Okay here's the tea โ. Various optimizers may cause calls to be marked noreturn and/or nothrow even without the matching attributes, and that can shift where checks land before calls, as well as which implicit cleanup handlers get added ๐. That unpredictability, plus the fact that raising and reraising exceptions often amounts to implicitly calling noreturn functions, is why no-xthrow is the default. It excludes from the noreturn treatment only the internal functions used to (re)raise exceptions, which those optimizations don't touch ๐
.
๐ -fhardened
Enables a set of flags for C and C++ that boost the security of the generated code without messing with its ABI ๐ก๏ธ. The exact flags can change between major GCC releases, but right now they are:
-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 yourself with --help=hardened ๐.
If the system glibc is older than 2.35, -D_FORTIFY_SOURCE=2 gets used instead ๐งธ.
This option is meant for production builds, not just debug builds. It's not a debug-only vibe ๐.
Right now -fhardened only works on GNU/Linux targets ๐ง.
Also, -fhardened only turns on a particular option if you haven't already specified it somewhere on the command line ๐
. For example, -fhardened -fstack-protector will only enable -fstack-protector, but 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 call alloca, 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 is printed and the program exits ๐. Only variables that are actually allocated on the stack count. Optimized-away variables or variables living in registers don't ๐ง .
๐ก๏ธ -fstack-protector-all
Like -fstack-protector, except all functions get 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 rule as before, only variables actually allocated on the stack count, and optimized-away or register variables don't.
NOTE: In Ubuntu 14.10 and later versions, -fstack-protector-strong is enabled by default for C, C++, ObjC, ObjC++, if none of -fno-stack-protector, -nostdlib, nor -ffreestanding are found ๐ธ.
๐ก๏ธ -fstack-protector-explicit
Like -fstack-protector, but it only protects functions that have the stack_protect attribute ๐ฏ.
๐งญ -fstack-check
Generates code to verify that you don't go past 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, because stack overflow is automatically detected on nearly all systems if there's only one stack ๐ .
Here's the tea: this switch doesn't actually do the checking ๐ซ . The operating system or the language runtime has to do that. The switch just makes the code that ensures they see the stack being extended ๐.
You can also pass a string parameter ๐:
noโ no checking at all ๐genericโ forces the use of old-style checking ๐ฐ๏ธspecificโ uses 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 some drawbacks ๐ญ:
- Modified allocation strategy for large objects. They're always allocated dynamically if their size goes over a fixed threshold. Note 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= was 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. For that you want -fstack-clash-protection ๐ซถ.
๐ง -fstack-clash-protection
Generates code to prevent stack clash style attacks ๐ง. When this is enabled, the compiler only allocates one page of stack space at a time, and each page gets accessed right after allocation. 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 versions, -fstack-clash-protection is enabled by default for C, C++, ObjC, and ObjC++, unless -fno-stack-clash-protection is found ๐
.
๐ง -fstack-limit-register=reg ยท -fstack-limit-symbol=sym ยท -fno-stack-limit
Generates code to make sure the stack doesn't grow beyond a certain value, either the value of a register or the address of a symbol ๐ง. If a larger stack is needed, a signal gets raised at run time ๐ก. For most targets the signal is raised before the stack overruns the boundary, so you can catch it without taking any special precautions ๐ฆ.
For instance, 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. ๐ฐ Note that this may only work with the GNU linker, so heads up, bestie.
You can locally override stack limit checking by using the no_stack_limit function attribute. ๐
-fsplit-stackโ Okay, this one is giving main character energy ๐ It generates code that automatically splits the stack before it overflows. The result is a discontiguous stack that can only overflow if the program runs out of memory to allocate. It's most useful for threaded programs, because you no longer have to figure out a good stack size for each thread. ๐งต Right now it's only implemented for x86 targets running GNU/Linux, so keep that in mind ๐ซถ
When code compiled with -fsplit-stack calls code compiled without -fsplit-stack, the latter code may not have much stack space to run in. ๐ฌ If compiling all your code, library code included, with -fsplit-stack isn't an option, the linker can fix up those calls so the code compiled without -fsplit-stack always gets a large stack. ๐ฆ This is supported 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 strict rule applies: only functions tied to"strub"-"callable"modes ("at-calls","callable"and"always_inline""internal") can be called by functions with"strub"-enabled modes ("at-calls"and"internal"). ๐-fstrub=relaxedโ Restores the default stack scrub ("strub") setting. That means"strub"only gets enabled when the"strub"attributes on functions and data types ask for it. ๐ธ Relaxed means strub contexts can only be blocked from calling functions that are 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โ Enables"at-calls""strub"mode wherever it's viable. ๐งช The main use is testing: 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โ Enables"internal""strub"mode wherever it's viable. ๐งช The primary use is testing. This option is meant 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โ Enables some"strub"mode wherever it's viable. โจ When both strub modes are viable,"at-calls"is preferred.-fdump-ipa-strubmadds function attributes that tell you which mode was selected for each function. The main use is testing, to thoroughly exercise the"strub"machinery. ๐-fvtable-verify=[std|preinit|none]โ This one's C++ only, so it's for my fellow C++ girlies ๐ 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 used for that call is valid for the object's type and hasn't been corrupted or overwritten. ๐ก๏ธ If an invalid vtable pointer is detected at run time, an error gets reported and the program halts immediately. ๐
This option makes the compiler build 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. With -fvtable-verify=std, they're built after shared libraries have been loaded and initialized. With -fvtable-verify=preinit, they're built 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 debug versions of the vtable verification runtime functions get called. ๐ It also makes the compiler log which vtable pointers it finds for each class. That info gets written to a file namedvtv_set_ptr_data.login the directory named by theVTV_LOGS_DIRenvironment variable if it's defined, or in the current working directory otherwise. ๐
Note: This feature appends data to the log file. If you want a fresh log file, make sure you delete any existing one first, bestie! ๐๏ธ
-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 to certain run-time library functions it inserts, and logs that info for each compilation unit. ๐ Results go 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, delete any existing ones first. ๐๏ธ
-finstrument-functionsโ Generates instrumentation calls for function entry and exit. ๐ Right after a function is entered, and right before it exits, the following profiling functions get called with the address of the current function and its call site. (Heads up: on some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site info may 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 into 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 are expanded inline, this may mean extra code size. ๐ If you use extern inline in your C code, an addressable version of those functions must be provided. (This is normally the case anyway, but if you get lucky and the optimizer always expands the functions inline, you might have gotten away without providing static copies. ๐)
A function can be given the no_instrument_function attribute, which skips this instrumentation for it. This is handy for things like the profiling functions listed above, high-priority interrupt routines, and any functions the profiling functions can't safely be called from (like signal handlers, if the profiling routines generate output or allocate memory). ๐ซ
-finstrument-functions-onceโ This is similar to-finstrument-functions, but the profiling functions only get called once per instrumented function. 1๏ธโฃ Specifically, the first profiling function is called after the first entry into the instrumented function, and the second 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 get called at least once per process and at most once per thread. The calls are always paired, though: if a thread calls the first function, it will call the second one too, unless it never reaches the exit of the instrumented function. ๐ซถ
-finstrument-functions-exclude-file-list=file,file,...โ Sets the list of functions that get excluded from instrumentation (see-finstrument-functionsabove). ๐ท If the file containing a function definition matches one of thefileentries, that function doesn't get instrumented. The match is done on substrings: if thefilevalue is a substring of the file name, it counts as a match. ๐ค
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
That 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 values, write ,,. For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quote surrounding the option). ๐ง
-finstrument-functions-exclude-function-list=sym,sym,...โ This is like-finstrument-functions-exclude-file-list, but this one sets the list of function names to exclude from instrumentation. ๐ท๏ธ The name that gets matched is its user-visible name, like"vector<int> blah(const vector<int> &)", not the internal mangled name (for example,"_Z4blahRSt6vectorIiSaIiEE"). The match is done on substrings: if thesymvalue is a substring of the function name, it counts as a match. For C99 and C++ extended identifiers, the function name has to be given in UTF-8, not using universal character names. ๐-fpatchable-function-entry=N[,M]โ okay so this one drops N NOPs right at the very start of every function, with the function's entry point sitting before the Mth NOP. If you skip M, it quietly defaults to 0, so the entry point lands right on the first NOP. ๐ง Those NOPs are basically reserved empty space you can patch instrumentation into at run time, but only if the code segment is writable ๐- The amount of space is controlled indirectly, through how many NOPs you ask for. The NOP instruction used matches what the internal GCC back-end interface
gen_nopemits. - This is target-specific and may also depend on the architecture variant and/or other compilation options, so it's not one-size-fits-all ๐ธ
- The amount of space is controlled indirectly, through how many NOPs you ask for. The NOP instruction used matches what the internal GCC back-end interface
For run-time identification, the starting addresses of these areas (their function entries minus M) also get collected in the __patchable_function_entries section of the final binary ๐ฆ
Heads up, bestie:__attribute__ ((patchable_function_entry (N,M)))takes priority over the-fpatchable-function-entry=N,Mcommand-line option. You can use it to make the area bigger or to remove it completely on one specific function. IfN=0, no pad location gets recorded ๐
The NOPs go in at the function entry address, which might be before the prologue depending on M. On PowerPC with the ELFv2 ABI, for a function with dual entry points, the local entry point is this same function entry address โจ
The max value of N and M is 65535. Also on PowerPC with the ELFv2 ABI, if you've got a function with dual entry points, the supported values for M are 0, 2, 6 and 14 ๐ฅ
๐ง Options Controlling the Preprocessor ๐ง
These options control the C preprocessor, which runs on every C source file before the actual compilation happens ๐
If you use -E, nothing happens except preprocessing. Some of these options only make sense together with -E, because they make the preprocessor output unsuitable for actual compilation ๐
Also, there are a bunch of options for search paths for include files, which are documented in Directory Options. Options for preprocessor diagnostics live in Warning Options ๐
-D nameโ predefinesnameas a macro, with the definition1๐-D name=definitionโ thedefinitiongets tokenized and processed as if it showed up during translation phase three in a#definedirective. A newline character inside it will truncate the definition ๐- If you're calling the preprocessor from a shell, you might need the shell's quoting syntax to protect characters like spaces that mean something to the shell ๐ซถ
- Want a function-like macro on the command line? Put its argument list in parentheses before the equals sign. Parentheses mean stuff to most shells, so quote the option. With
shandcsh,-D'name(args...)=definition'works โจ -Dand-Uoptions are processed in the order you type them. All-imacrosand-includeoptions get processed after every-Dand-U๐
-U nameโ cancels any previous definition ofname, whether it was built in or set with a-Doption ๐ฆ-include fileโ processesfileas if#include "file"showed up as the 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, it gets searched for in the rest of the#include "..."search chain, like normal ๐- Multiple
-includeoptions get included in the order they appear on the command line ๐
- Multiple
-imacros fileโ works exactly like-include, except any output made by scanningfilegets thrown away. The macros it defines stay defined. This lets you grab all the macros from a header without processing its declarations ๐ง- Every
-imacrosfile gets processed before every-includefile ๐
- Every
-undefโ don't predefine any system-specific or GCC-specific macros. The standard predefined macros stay defined ๐ธ-pthreadโ defines the extra macros you need for the POSIX threads library. Use this option consistently for both compiling and linking, bestie ๐ฅ- It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets โญ
-Mโ instead of spitting out the preprocessed result, this outputs a rule thatmakecan use to describe the dependencies of the main source file ๐ญ- The preprocessor outputs one make rule. It has the object file name for that source file, a colon, and the names of all the included files, including the ones from
-includeor-imacroscommand-line options ๐ - Unless you set it explicitly with
-MTor-MQ, the object file name is the source file name with its suffix swapped for the object file suffix, and any leading directory parts removed ๐ฆ - If there are a lot of included files, the rule gets split across several lines using
\-newline. The rule has no commands ๐ - This doesn't suppress the preprocessor's debug output, like
-dM. To keep that debug output from mixing with your dependency rules, specify the dependency output file with-MF, or use an environment variable likeDEPENDENCIES_OUTPUT. Debug output still goes to the regular output stream as usual ๐ - Passing
-Mto the driver implies-E, and it suppresses warnings with an implicit-w๐
- The preprocessor outputs one make rule. It has the object file name for that source file, a colon, and the names of all the included files, including the ones from
-MMโ like-M, but it doesn't mention header files found in system header directories, or header files included (directly or indirectly) from those system headers ๐- This means the choice of angle brackets or double quotes in an
#includedirective doesn't, by itself, decide whether that header shows up in-MMdependency output ๐
- This means the choice of angle brackets or double quotes in an
-MF fileโ when used with-Mor-MM, this says which 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 ๐- With the driver options
-MDor-MMD,-MFoverrides the default dependency output file ๐ซถ - If
fileis-, the dependencies get written to stdout โจ
- With the driver options
-MGโ used alongside an option like-Mthat asks for dependency generation,-MGassumes missing header files are generated files. It adds them to the dependency list without raising an error. The dependency filename is taken 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 each one depends on nothing. These dummy rules work around errorsmakethrows if you delete 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 that dependency generation emits ๐ฆ- By default, CPP takes the main input file name, deletes any directory components and the file suffix (like
.c), and adds the platform's usual object suffix. That result is the target ๐ - An
-MToption makes the target exactly the string you specify. If you want multiple targets, you can put them in one argument to-MT, or use multiple-MToptions ๐ - For example,
-MT '$(objpfx)foo.o'might give:
- By default, CPP takes the main input file name, deletes any directory components and the file suffix (like
$(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 you'd given it with
-MQ๐
-MDโ this is equivalent to-M -MF file, except-Eisn't implied ๐ธ- The driver figures out
filebased on whether an-ooption is given. If it is, the driver uses that argument with a.dsuffix. Otherwise, it takes the input file name, removes any directory components and suffix, and applies a.dsuffix โจ - If
-MDis used with-E, any-oswitch is understood to specify the dependency output file. But if it's used without-E, each-ois understood to specify a target object file ๐ - Since
-Eisn't implied,-MDcan generate a dependency output file as a side effect of the compilation process ๐
- The driver figures out
-MMDโ like-MD, except it only mentions user header files, not system header files ๐-fpreprocessedโ tells the preprocessor the input file has already been preprocessed. This suppresses things like macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives ๐ง- The preprocessor still recognizes and removes comments, so you can pass a file preprocessed with
-Cto the compiler without any problems. In this mode, the integrated preprocessor is basically just a tokenizer for the front ends ๐ฆ -fpreprocessedis implicit if the input file has one of the extensions.i,.iior.mi. Those are the extensions GCC uses for preprocessed files created by-save-temps๐
- The preprocessor still recognizes and removes comments, so you can pass a file preprocessed with
-fdirectives-onlyโ when preprocessing, this handles directives but does not expand macros ๐ซถ- What it does 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, don't happen. Also, the-dDoption is implicitly enabled ๐ญ - With
-fpreprocessed, predefinition of command-line macros and most builtin macros is disabled. Macros like__LINE__, which depend on context, are handled normally. This lets you compile files that were previously preprocessed with-E -fdirectives-only๐ - With both
-Eand-fpreprocessed, the-fpreprocessedrules take precedence. This enables full preprocessing of files that were previously preprocessed with-E -fdirectives-only๐
- With
- What it does depends on
-fdollars-in-identifiersโ accepts$in identifiers ๐-fextended-identifiersโ ๐ Lets identifiers use universal character names and extended characters, which is pure main character energy โจ. It's on by default for C99 (and later C standard versions) and C++, so you're already winning ๐ .-fno-canonical-system-headersโ ๐ง When preprocessing, GCC won't shorten system header paths with canonicalization โจ.-fmax-include-depth=depthโ ๐ธ Sets how deep nested#includes can go. The default is200, which is honestly a lot of nesting bestie ๐.-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 when a compile error happens inside a macro, GCC can show the current macro expansion stack. Heads up, though: this makes the preprocessor and compiler eat more memory ๐.
The level parameter lets you pick how precise the token tracking is, so you can dial down the memory use if you need to ๐:
0โ turns this option off.1โ degraded mode for minimal memory overhead. All tokens from expanding an argument of a function-like macro end up with the same location.2โ tracks token locations completely. This is the most memory-hungry one ๐ญ.
If you don't give it a value, the default level is 2.
Note that -ftrack-macro-expansion=2 is activated by default.
-fmacro-prefix-map=old=newโ ๐บ๏ธ When preprocessing files that live in directoryold, GCC expands__FILE__and__BASE_FILE__as if those files lived in directorynewinstead. Use.fornewto turn an absolute path into a relative one, which can lead to more reproducible, location-independent builds ๐ซถ. This also affects__builtin_FILE()during compilation. See also-ffile-prefix-mapand-fcanon-prefix-map.-fexec-charset=charsetโ ๐ Sets the execution character set, used for string and character constants. The default isUTF-8.charsetcan be any encoding your system'siconvlibrary routine supports ๐ธ.-fwide-exec-charset=charsetโ ๐ Sets the wide execution character set, used for wide string and character constants. The default is one ofUTF-32BE,UTF-32LE,UTF-16BE, orUTF-16LE, whichever matches the width ofwchar_tand the big-endian or little-endian byte order used for code generation ๐. Just like-fexec-charset,charsetcan be any encodingiconvsupports.
Heads up: you'll run into problems with encodings that don't fit exactly in wchar_t ๐ญ.
-finput-charset=charsetโ ๐ฆ Sets the input character set, which is used to translate the input file's characters 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 right now the command-line option wins if there's a conflict ๐ .charsetcan be any encodingiconvsupports.-fpch-depsโ ๐งธ When you're using precompiled headers, this makes the dependency-output flags also list the files from the precompiled header's dependencies. Without it, only the precompiled header gets listed, not the files used to create it, because those files aren't consulted when a PCH is used ๐.-fpch-preprocessโ ๐ฎ Lets you use a precompiled header together with-E. It inserts a special#pragma, namely#pragma GCC pch_preprocess "filename", into the output to mark the place where the precompiled header was found and its filename. When-fpreprocessedis in use, GCC recognizes that#pragmaand loads the PCH.
This option is off by default, because the resulting preprocessed output is only really suitable as input to GCC ๐. It gets switched on by -save-temps.
You should not write this #pragma in your own code ๐
, but it's safe to edit the filename if the PCH file is available in a different location. The filename may be absolute, or relative to GCC's current directory.
-fworking-directoryโ ๐ท Enables generation of linemarkers in the preprocessor output that let the compiler know the current working directory at the time of preprocessing. When this is enabled, the preprocessor emits, after the initial linemarker, a second linemarker with the current working directory followed by two slashes. GCC uses this directory, when it's present in the preprocessed input, as the directory emitted as the current working directory in some debugging information formats. This option is implicitly enabled if debugging information is enabled, but you can inhibit it with the negated form-fno-working-directory. If the-Pflag is present on the command line, this option has no effect, since no#linedirectives are emitted whatsoever ๐ฅฒ.-A predicate=answerโ โจ Makes an assertion with the predicatepredicateand the answeranswer. This form is preferred over the older-A predicate(answer), which is still supported, because it doesn't use shell special characters ๐.-A -predicate=answerโ ๐ซ Cancels an assertion with the predicatepredicateand the answeranswer.-Cโ ๐ฌ Don't throw comments away! All comments are passed through to the output file, except for comments in processed directives, which get deleted along with the directive.
Be prepared for side effects when using-C, because it makes the preprocessor treat comments as tokens in their own right. For example, comments appearing at the start of what would be a directive line turn that line into an ordinary source line, since the first token on the line is no longer a#.
-CCโ ๐ Don't discard comments, even during macro expansion. It's like-C, except comments contained within macros also get passed through to the output file where the macro is expanded.
In addition to the side effects of the -C option, -CC converts all C++-style comments inside a macro into C-style comments. That stops a later use of the macro from accidentally commenting out the rest of the source line ๐.
The -CC option is generally used to support lint comments ๐งน.
-Pโ ๐ Inhibits generation of linemarkers in the preprocessor output. This might be useful when you're running the preprocessor on something that isn't C code and will be sent to a program that might get confused by the linemarkers.-traditional,-traditional-cppโ ๐ฆ Tries to imitate the behavior of pre-standard C preprocessors, instead of ISO C preprocessors. Check the GNU CPP manual for details.
Note that GCC doesn't otherwise try to emulate a pre-standard C compiler, and these options are only supported with the -E switch, or when invoking 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:
??(becomes[??)becomes]??<becomes{??>becomes}??=becomes#??/becomes\??'becomes^??!becomes|??-becomes~
By default, GCC ignores trigraphs, but in standard-conforming modes it converts them. See the -std and -ansi options ๐.
-remapโ ๐๏ธ Enables special code to work around file systems that only permit very short file names, such as MS-DOS ๐พ.-Hโ ๐ณ Prints the name of each header file used, in addition to the other normal activities. Each name is indented to show how deep it is in the#includestack. Precompiled header files are also printed, even if they turn out to be invalid. An invalid precompiled header file 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're silently ignored. If you specify letters whose behavior conflicts, the result is undefined ๐.-dMโ Instead of the normal output, generates a list of#definedirectives for all the macros defined during the execution of the preprocessor, including predefined macros. This gives you a way of finding out what's predefined in your version of the preprocessor ๐. Assuming you have no filefoo.h, the command below shows all the predefined macros โจ:
touch foo.h; cpp -dM foo.h
If you use -dM without the -E option, -dM is interpreted as a synonym for -fdump-rtl-mach.
-dDโ 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 emits only the macro names, not their expansions.-dIโ Outputs#includedirectives in addition to the result of preprocessing.-dUโ Like-dD, except only macros that are expanded, or whose definedness is tested in preprocessor directives, are output. The output is delayed until the use or test of the macro, and#undefdirectives are also output for macros that were tested but undefined at the time ๐ฆ.
-fdebug-cppโ ๐ This option is only useful for debugging GCC. When used fromCPPor with-E, it dumps debugging information about location maps. Every token in the output is preceded by the dump of the map its location belongs to.
When used from GCC without -E, this option has no effect.
-Wp,option
-Wp,optionโ Hot tip from bestie: this lets you skip the compiler driver entirely and sendoptionstraight to the preprocessor. ๐ง Ifoptionhas commas, it gets split up at each comma. BUT, ngl, a lot of options get modified, translated, or interpreted by the driver first, and-Wptotally bypasses that step. The preprocessor's direct interface is undocumented and can change at any time, so whenever possible just let the driver handle your options instead. ๐
-Xpreprocessor option
-Xpreprocessor optionโ Passesoptionto the preprocessor as an option. This is clutch for system-specific preprocessor options that GCC doesn't recognize. ๐
If you want to pass an option that takes an argument, you have to use -Xpreprocessor twice: once for the option and once for the argument. ๐ซถ
-no-integrated-cpp
-no-integrated-cppโ Okay so, by default GCC does preprocessing as part of input tokenization and parsing, all integrated and smooth. โจ With this option, preprocessing happens as a separate pass before compilation instead. The language front end (cc1for C,cc1plusfor C++, andcc1objfor Objective-C) gets invoked twice: once for preprocessing only, and once for the actual compilation of the preprocessed input. This can be super useful together with the-Bor-wrapperoptions if you want an alternate preprocessor or extra processing of your source between normal preprocessing and compilation. ๐ฆ
-flarge-source-files
-flarge-source-filesโ Okay this one is for the big leagues ๐. It tells GCC to expect large source files, but it costs you slower compilation and higher memory usage. ๐
Here's the tea: GCC normally tracks both column numbers and line numbers in source files, and it prints both in diagnostics. Once it has processed a certain number of source lines, though, it stops tracking column numbers and only tracks line numbers. So diagnostics for later lines won't include column numbers. ngl that also means options like -Wmisleading-indentation stop working at that point, although the compiler prints a note if this happens. ๐ญ Passing -flarge-source-files seriously boosts how many source lines GCC can process before it stops tracking columns. ๐
๐ Passing Options to the Assembler ๐
You can pass options to the assembler. ๐ฆ
-Wa,option
-Wa,optionโ Passesoptionto the assembler. Ifoptionhas commas, it gets split into multiple options at the commas. ๐ธ
-Xassembler option
-Xassembler optionโ Passesoptionto the assembler as an option. 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: once for the option and once 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. ๐
object-file-name
object-file-nameโ A file name that doesn't end in a special recognized suffix is considered to name an object file or library. (The linker tells object files apart from libraries by checking the file contents, not the name.) If linking happens, these object files get fed into the linker as input. โจ
-c -S -E
-c,-S,-Eโ If any of these is used, the linker doesn't run, so object file names shouldn't be used as arguments. ๐
-flinker-output=type
-flinker-output=typeโ Controls code generation of the link-time optimizer. โจ By default, the linker output is figured out automatically by the linker plugin. For debugging the compiler, or if you want incremental linking with a non-LTO object file, it can be handy to set the type manually. ๐ง
If type is exec, code generation produces a static binary. In this case -fpic and -fpie are both disabled. ๐ง
If type is dyn, code generation produces a shared library. In this case -fpic or -fPIC is preserved, but not enabled automatically. This lets you build shared libraries without position-independent code on architectures where that's possible, i.e. on x86. ๐
If type is pie, code generation produces an -fpie executable. This gives similar optimizations to exec, except -fpie is not disabled if it was specified at compilation time. ๐
If type is rel, the compiler assumes incremental linking is happening. The sections containing intermediate code for link-time optimization are merged, pre-optimized, and output to the resulting object file. Also, if -ffat-lto-objects is specified, binary code is produced for future non-LTO linking. The object file from incremental linking is smaller than a static library made from the same object files. At link time, the result of incremental linking also loads faster than a static library, assuming most objects in the library are used. ๐ซ
Finally, nolto-rel configures 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 resulting code is better optimized than with link-time optimizations disabled (for example, cross-module inlining happens), but most of the benefits of whole program optimizations are lost. ๐ค
During the incremental link (by-r), the linker plugin defaults torel. With current interfaces to GNU Binutils, it is however 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 issues a warning and usesnolto-rel. To maintain whole program optimization, it's recommended to link such objects into a static library instead. Alternatively, it's possible to use H.J. Lu's binutils with support for mixed objects. ๐จ
-fuse-ld=bfd
-fuse-ld=bfdโ Uses the bfd linker instead of the default linker. ๐ธ
-fuse-ld=gold
-fuse-ld=goldโ Uses the gold linker instead of the default linker. ๐ฅ
-fuse-ld=lld
-fuse-ld=lldโ Uses the LLVM lld linker instead of the default linker. ๐ฆ
-fuse-ld=mold
-fuse-ld=moldโ Uses the Modern Linker (mold) instead of the default linker. โก
-llibrary -l library
-llibrary,-l libraryโ Searches the library named library when linking. (The second form, with the library as a separate argument, is only there for POSIX compliance and isn't recommended. ๐)
The -l option is passed straight through to the linker by GCC, so check your linker's documentation for exact details. The general description below applies to the GNU linker. ๐ง
The linker searches a standard list of directories for the library. The directories searched include several standard system directories, plus any you specify with -L. ๐๏ธ
Static libraries are archives of object files and have file names like liblibrary.a. Some targets also support shared libraries, which typically have names like liblibrary.so. If both static and shared libraries are found, the linker prefers the shared library unless the -static option is used. ๐ซง
Where you write this option in the command really matters. The linker searches and processes libraries and object files in the order they're specified. So foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not get loaded. ๐ฌ
-lobjc
-lobjcโ You need this special case of the-loption to link an Objective-C or Objective-C++ program. ๐
-nostartfiles
-nostartfilesโ Doesn't use the standard system startup files when linking. The standard system libraries are still used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used. ๐ซ
-nodefaultlibs
-nodefaultlibsโ Doesn't use the standard system libraries when linking. Only the libraries you specify get passed to the linker, and options that set linkage for system libraries, like-static-libgccor-shared-libgcc, are ignored. The standard startup files are still used normally, unless-nostartfilesis used. ๐ โโ๏ธ
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These are usually resolved by entries in libc. When this option is specified, these entry points need to be supplied through some other mechanism. ๐งฉ
-nolibc
-nolibcโ Doesn't use the C library or the system libraries tightly coupled with it when linking. It still links with the startup files, libgcc, or toolchain-provided language support libraries likelibgnat,libgfortran, orlibstdc++, unless options preventing their inclusion are used too. This typically removes-lcfrom the link command line, along with system libraries that normally go with it and become meaningless when a C library is assumed absent, for example-lpthreador-lmin some configurations. This is meant for bare-board targets where there's really no C library available. ๐ค
-nostdlib
-nostdlibโ Doesn't use the standard system startup files or libraries when linking. No startup files are used, and only the libraries you specify get passed to the linker. Options that set linkage for system libraries, like-static-libgccor-shared-libgcc, are ignored. ๐งฑ
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These are usually resolved by entries in libc. When this option is specified, these entry points need to be supplied through some other mechanism. ๐งฉ
One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines that GCC uses to work around shortcomings of particular machines, or special needs for some languages. ๐
In most cases, you still need libgcc.a even when you want to avoid other standard libraries. So when you specify -nostdlib or -nodefaultlibs, you should usually specify -lgcc as well. This makes sure you don't have unresolved references to internal GCC library subroutines. (An example of such an internal subroutine is "__main", which is used to make sure C++ constructors get called.) ๐
-nostdlib++
-nostdlib++โ Doesn't implicitly link with standard C++ libraries. ๐ซ
-e entry --entry=entry
-e entry,--entry=entryโ Specifies that the program entry point is entry. The linker interprets the argument: the GNU linker accepts either a symbol name or an address. ๐ช-pieโ okay so this one tells the linker to make a dynamically linked position independent executable ๐ on targets that actually support it โจ. For predictable results, bestie, you have to use the same compile options too (-fpie,-fPIE, or model suboptions) when you use this linker option ๐ .-no-pieโ the opposite energy ๐ โโ๏ธ. It does not make a dynamically linked position independent executable.-static-pieโ makes a static position independent executable on targets that support it ๐ฆ. It's giving static executable vibes, but it can get loaded at any address with no dynamic linker needed ๐ง. Same rule as before: match the compile options (-fpie,-fPIE, or model suboptions) for predictable results ๐.-pthreadโ links with the POSIX threads library ๐งต. It works on GNU/Linux, most other Unix derivatives, and also on x86 Cygwin and MinGW targets ๐. Heads up: on some targets this 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 ๐ฅ. It tells the linker to add all symbols, not just the used ones, to the dynamic symbol table ๐. You need this for some uses ofdlopen, or to get backtraces from inside a program ๐.-sโ removes all symbol table and relocation information from the executable ๐.-staticโ on systems that support dynamic linking, this overrides-pieand stops linking with the shared libraries ๐ซ. On other systems it does absolutely 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, match the compile options (-fpic,-fPIC, or model suboptions) when you use this linker option [1].-shared-libgcc,-static-libgccโ on systems that provide libgcc as a shared library, these force the use of the shared or static version, respectively ๐. If no shared version of libgcc got built when the compiler was configured, these options have no effect ๐ญ.
There are several situations where an application should use the shared libgcc instead of the static version ๐ง . The most common one is when the application wants to throw and catch exceptions across different shared libraries. In that case, each of the libraries and the application itself should use the shared libgcc ๐ซถ.
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable, because C++ programs typically use exceptions. That's the right move, periodt ๐
.
If, instead, you use the GCC driver to create shared libraries, they might not always get linked with the shared libgcc ๐. If GCC finds at its 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 optimizes away the linking with the shared version of libgcc, linking with the static version by default. This lets exceptions propagate through those shared libraries without incurring relocation costs at library load time โจ.
However, if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ driver, or using the option -shared-libgcc, so that it's linked with the shared libgcc ๐จ.
-static-libasanโ when the-fsanitize=addressoption is used to link a program, the GCC driver automatically links against libasan ๐ต๏ธโโ๏ธ. If libasan is available as a shared library, and the-staticoption is not used, it links against the shared version. This option directs the GCC driver to link libasan statically, without necessarily linking other libraries statically ๐.-static-libtsanโ when the-fsanitize=threadoption is used to link a program, the GCC driver automatically links against libtsan ๐งต. If libtsan is available as a shared library, and the-staticoption is not used, it links against the shared version. This option directs the GCC driver to link libtsan statically, without necessarily linking other libraries statically ๐ฆ.-static-liblsanโ when the-fsanitize=leakoption is used to link a program, the GCC driver automatically links against liblsan ๐งน. If liblsan is available as a shared library, and the-staticoption is not used, it links against the shared version. This option directs the GCC driver to link liblsan statically, without necessarily linking other libraries statically ๐ธ.-static-libubsanโ when the-fsanitize=undefinedoption is used to link a program, the GCC driver automatically links against libubsan ๐ซง. If libubsan is available as a shared library, and the-staticoption is not used, it links against the shared version. This option directs the GCC driver to link libubsan statically, without necessarily linking other libraries statically ๐.-static-libstdc++โ when theg++program links a C++ program, it normally links against libstdc++ automatically ๐ . If libstdc++ is available as a shared library, and the-staticoption is not used, it links against the shared version, and that's normally fine โจ. Sometimes though, you want to freeze the version of libstdc++ your program uses without going all the way to a fully static link ๐ง. This option directs 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 option, so it's a bit of a rare flex ๐.-T scriptโ uses script as the linker script ๐. This option is supported by most systems using the GNU linker. On some targets, like bare-board targets without an operating system,-Tmay be required when linking to avoid references to undefined symbols ๐ค.-Xlinker optionโ passes option along to the linker as an option ๐. Use this to supply system-specific linker options that GCC doesn't recognize.
If you want to pass an option that takes a separate argument, you have to use -Xlinker twice, once for the option and once for the argument ๐. For example, to pass -assert definitions, you must write -Xlinker -assert -Xlinker definitions. It does not work to write -Xlinker "-assert definitions", because that passes the entire string as one single argument, which is not what the linker expects ๐.
When you're using the GNU linker, it's usually way more convenient to pass arguments to linker options with the option=value syntax instead of as separate arguments ๐ง. For example, you can write -Xlinker -Map=output.map instead of -Xlinker -Map -Xlinker output.map. Just know that other linkers might not support this syntax for command-line options ๐คทโโ๏ธ.
-Wl,optionโ passes option as an option to the linker ๐. If option contains commas, it gets split into multiple options at those commas. This syntax lets you pass an argument to the option too: for example,-Wl,-Map,output.mappasses-Map output.mapto the linker โจ. When using the GNU linker, you can get the same effect with-Wl,-Map=output.map๐ฆ.
NOTE: In Ubuntu 8.10 and later versions, for LDFLAGS, the option-Wl,-z,relrois used. To disable it, use-Wl,-z,norelro๐จ.
-u symbolโ pretends the symbol symbol is undefined, to force linking of library modules that define it ๐ง. You can use-umultiple times with different symbols to force loading of additional library modules ๐.-z keywordโ-zis passed straight on to the linker along with the keyword keyword ๐ซถ. Check the section in your linker's documentation for the permitted values and what they mean ๐.
๐งญ Options for Directory Search ๐งญ
These options specify the directories to search for header files, for libraries and for 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 begins with=or$SYSROOT, then the=or$SYSROOTis replaced by the sysroot prefix. See--sysrootand-isysrootfor more on that ๐.
Directories specified with -iquote only apply to the quote form of the directive, #include "file" ๐ฌ. Directories specified with -I, -isystem, or -idirafter apply to lookup for both #include "file" and #include <file> ๐
.
You can specify any number or combination of these options on the command line to search for header files in several directories ๐. The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first ๐.
- For the quote form of the include directive, the directories specified by
-iquoteoptions are searched in left-to-right order, as they appear on the command line โก๏ธ. - Directories specified with
-Ioptions are scanned in left-to-right order ๐. - Directories specified with
-isystemoptions are scanned in left-to-right order ๐๏ธ. - Standard system directories are scanned ๐งฑ.
- Directories specified with
-idirafteroptions are scanned in left-to-right order ๐.
You can use -I to override a system header file and substitute your own version, since these directories get searched before the standard system header file directories ๐. However, you should not use this option to add directories that contain vendor-supplied system header files. Use -isystem for that ๐
โโ๏ธ.
The -isystem and -idirafter options also mark the directory as a system directory, so it gets the same special treatment that's applied to the standard system directories ๐โจ.
okay so bestie, if a standard system include directory (or one you pass with -isystem) is also given with -I, the -I gets ignored ๐
โโ๏ธ The directory still gets searched, just as a system directory in its normal spot in the system include chain. This keeps GCC's little fix-up routine for buggy system headers and the ordering for #include_next from getting accidentally messed up ๐
If you really need to change the search order for system directories, reach for -nostdinc and/or -isystem.
-I-โ splits the include path ๐ฆ This one is deprecated, so please use-iquotefor the-Idirectories that come before the-I-, and then remove the-I-option ๐ซถ
Any directories given with -I before -I- only get searched for headers requested with #include "file". They are NOT searched for #include <file>. If you add more -I directories after the -I-, those get searched for all #include directives.
-I- also blocks the current file's directory from being the first search directory for #include "file". There is no way to override this effect of -I- ๐ญ
-iprefix prefixโ picksprefixas the prefix for any later-iwithprefixoptions ๐ธ If your prefix is a directory, make sure you include the final/.-iwithprefix dir,-iwithprefixbefore dirโ tacksdironto the prefix you set earlier with-iprefix, then adds the result to the include search path โจ-iwithprefixbeforeputs it in the same place-Iwould, and-iwithprefixputs it where-idirafterwould.-isysroot dirโ basically the--sysrootoption, but it only applies to header files ๐ง (Except on Darwin targets, where it applies to both header files and libraries.) See the--sysrootoption for more information.-imultilib dirโ usesdiras a subdirectory of the directory that holds target-specific C++ headers ๐-nostdincโ don't search the standard system directories for header files ๐ Only the directories you explicitly give with-I,-iquote,-isystem, and/or-idirafter(plus the directory of the current file, if appropriate) get searched.-nostdinc++โ skips the C++-specific standard directories, but still searches the other standard directories ๐ค (This one is used when building the C++ library.)-iplugindir=dirโ sets the directory to search for plugins that get passed by-fplugin=nameinstead of-fplugin=path/name.so. This one isn't meant for you to use, it's only passed along by the driver ๐ โโ๏ธ-Ldirโ addsdirto the list of directories searched for-l๐-Bprefixโ this is where you tell the compiler where to find its own executables, libraries, include files, and data files ๐
The compiler driver program runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for each program it tries to run, both with and without machine/version/ for the corresponding target machine and compiler version.
For each subprogram, the driver first tries the -B prefix, if there is one. If that name isn't found, or if -B isn't specified, the driver tries two standard prefixes, /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those turns up a file, the unmodified program name gets searched for using the directories in your PATH environment variable.
The compiler checks whether the path given by -B refers to a directory, and if necessary it adds a directory separator character at the end of the path ๐ฆ
-B prefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into -L options for the linker. They also apply to include files in the preprocessor, because the compiler translates these options into -isystem options for the preprocessor. In this case, the compiler appends include to the prefix.
The runtime support file libgcc.a can also be searched for using the -B prefix, if needed. If it isn't found there, the two standard prefixes above are tried, and that is all. The file gets left out of the link if it isn't found by those means ๐ญ
Another way to specify a prefix that's pretty much like the -B prefix is to use the environment variable GCC_EXEC_PREFIX ๐
As a special kludge, if the path given by -B is [dir/]stageN/, where N is a number in the range 0 to 9, then it gets replaced by [dir/]include. This is to help with boot-strapping 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โ usesdiras the logical root directory for headers and libraries ๐ For example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it instead searchesdir/usr/includeanddir/usr/lib.
If you use both this option and the -isysroot option, then --sysroot applies to libraries, but -isysroot applies to header files.
The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker doesn't support it, the header file side of --sysroot still works, but the library side does not ๐
--no-sysroot-suffixโ for some targets, a suffix gets added to the root directory given with--sysroot, depending on the other options you used, so headers might be found indir/suffix/usr/includeinstead ofdir/usr/include๐ This option turns off the addition of that suffix.
โจ Options for Code Generation Conventions โจ
These machine-independent options control the interface conventions used in code generation ๐
Most of them have both positive and negative forms, and the negative form of -ffoo is -fno-foo. Below, only one of the forms is listed (the one that is not the default). You can figure out the other form by either removing no- or adding it ๐ซถ
-fstack-reuse=reuse-levelโ controls stack space reuse for user-declared local/auto variables and compiler-generated temporaries ๐reuse_levelcan beall,named_vars, ornone.allturns on stack reuse for every local variable and temporary,named_varsonly reuses space for user-defined local variables that have names, andnoneturns stack reuse off completely. The default value isall.
This option is needed when a program extends the lifetime of a scoped local variable or a compiler-generated temporary beyond the end point defined by the language. When a variable's lifetime ends and it lives in memory, the optimizing compiler is free to reuse its stack space with other temporaries or scoped local variables whose live range doesn't overlap with it.
Legacy code that extends local lifetime is likely to break with the stack reuse optimization ๐ญ
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example:
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 lifetime of a compiler-generated temporary is well defined by the C++ standard. When a temporary's lifetime ends and it lives in memory, the optimizing compiler is free to reuse its stack space with other temporaries or scoped local variables whose live range doesn't overlap with it. However, some legacy code relies on the behavior of older compilers, where temporaries' stack space wasn't reused, so aggressive stack reuse can lead to runtime errors ๐ This option controls that temporary stack reuse optimization.
-ftrapvโ generates traps for signed overflow on addition, subtraction, and multiplication operations ๐ฅ-ftrapvand-fwrapvoverride each other, so using-ftrapv -fwrapvon the command line results in-fwrapvbeing effective. Only active options override, though, so using-ftrapv -fwrapv -fno-wrapvon the command line results in-ftrapvbeing effective.-fwrapvโ tells the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation ๐ฆ This flag enables some optimizations and disables others.-ftrapvand-fwrapvoverride each other, so using-ftrapv -fwrapvon the command line results in-fwrapvbeing effective. Only active options override, so using-ftrapv -fwrapv -fno-wrapvon the command line results in-ftrapvbeing effective.-fwrapv-pointerโ tells the compiler to assume that pointer arithmetic overflow on addition and subtraction wraps around using twos-complement representation ๐ธ This flag disables some optimizations that assume pointer overflow is invalid.-fstrict-overflowโ implies-fno-wrapv -fno-wrapv-pointer, and when negated, implies-fwrapv -fwrapv-pointer๐-fexceptionsโ okay bestie, this one switches on exception handling ๐ It generates the extra code needed to propagate exceptions. On some targets it also means GCC builds frame unwind info for every function, which can add serious data size overhead, but it doesn't mess with execution ๐ If you don't say anything, GCC turns it on by default for languages like C++ that normally need exception handling, and turns it off for languages like C that don't. You might need to enable it manually when your C code has to play nicely with exception handlers written in C++ โจ You might also want to disable it if you're compiling older C++ programs that don't use exception handling.-fnon-call-exceptionsโ lets trapping instructions throw exceptions ๐ฆ ngl this needs platform-specific runtime support, and that support doesn't exist everywhere. It only lets trapping instructions, meaning memory references or floating-point instructions, throw. It does not let exceptions come out of arbitrary signal handlers like"SIGALRM". This one also turns on-fexceptions.-fdelete-dead-exceptionsโ instructions that might throw but don't otherwise contribute to the program can be optimized away ๐งน This doesn't touch calls to functions unless they have the"pure"or"const"attributes. It's on by default for the Ada and C++ compilers, since the language specs allow it. The optimization passes that remove dead exceptions turn on independently at different optimization levels.-funwind-tablesโ basically the vibe of-fexceptions, except it only generates the needed static data and leaves the generated code alone ๐ธ You usually don't have to turn this on yourself, because any language processor that needs this handling enables it for you.-fasynchronous-unwind-tablesโ generates an unwind table in DWARF format, if the target machine supports it ๐ฅ The table is exact at every instruction boundary, so it can be used for stack unwinding from asynchronous events, like a debugger or a garbage collector.-fno-gnu-uniqueโ okay, this one's a little dramatic ๐ถ๏ธ On systems with a recent GNU assembler and C library, the C++ compiler uses the"STB_GNU_UNIQUE"binding so definitions of template static data members and static local variables in inline functions stay unique, even with"RTLD_LOCAL". That matters so a library used by two different"RTLD_LOCAL"plugins doesn't end up depending on a definition in one of them while disagreeing with the other about the binding of the symbol. BUT, this makesdlcloseget ignored for affected DSOs. So if your program relies on reinitializing a DSO throughdlcloseanddlopen, you can use-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 GCC-compiled files play nicely with files built by other compilers, especially the Portable C Compiler (pcc).
The precise convention for returning structures in memory depends on the target configuration macros. Short structures and unions are those whose size and alignment match that of some integer type.
Warning: code compiled with-fpcc-struct-returnis not binary compatible with code compiled with-freg-struct-return. Use it to conform to a non-default application binary interface.
-freg-struct-returnโ returnsstructandunionvalues in registers when possible ๐ This is more efficient than-fpcc-struct-returnfor small structures.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever 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 choose the standard, and it picks the more efficient register return alternative.
Warning: code compiled with-freg-struct-returnis not binary compatible with code compiled with-fpcc-struct-return. Use it to conform to a non-default application binary interface.
-fshort-enumsโ gives anenumtype only as many bytes as it needs for its declared range of possible values ๐ Specifically, theenumtype becomes the smallest integer type with enough room. This option has no effect on an enumeration type with a fixed underlying type.
Warning: -fshort-enums makes GCC generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface.
-fshort-wcharโ overrides the underlying type for"wchar_t"to be"short unsigned int"instead of the target's default โจ It's super useful 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. Use it to conform to a non-default application binary interface.
-fcommonโ in C code, this controls where global variables defined without an initializer get placed ๐ These are called tentative definitions in the C standard. They're different from declarations with theexternkeyword, which don't allocate any storage.
The default is -fno-common, which places uninitialized global variables in the BSS section of the object file. This stops the linker from merging tentative definitions, so you get a multiple-definition error if the same variable is accidentally defined in more than one compilation unit ๐ญ
-fcommon places 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 one object, or to a non-tentative definition. This behaviour is inconsistent with C++, and on many targets it implies a speed and code size penalty on global variable references. It's mainly useful for getting legacy code to link without errors.
-fno-identโ ignores 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 and the two halves end up far apart in memory ๐ This is used when compilingcrtstuff.c, so you shouldn't need it for anything else.-fverbose-asmโ adds extra commentary to the generated assembly so it's way easier to read ๐ This one's really for people who actually need to read generated assembly, like when they're debugging the compiler itself.
-fno-verbose-asm, the default, leaves the extra info out, which is clutch 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.
For example, given 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 to (x86_64) assembly via -S and emitting the result direct to stdout via -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 of the comments is subject to change ๐ฆ
-frecord-gcc-switchesโ this makes the command line used to invoke the compiler get recorded into the object file being created ๐ It's only implemented on some targets, and the exact format of the recording depends on the target and binary file format. Usually it takes the form of a section containing ASCII text. This switch is related to-fverbose-asm, but that one only records information as comments in the assembler output file, so it never reaches the object file. See also-grecord-gcc-switchesfor another way of storing compiler options in the object file.-fpicโ โจ okay bestie, this one makes position-independent code (PIC) that's ready to live inside a shared library ๐, if your target machine supports it. The code reaches every constant address through a global offset table (GOT), and the dynamic loader fills in those GOT entries when the program starts ๐ง (fun fact: the dynamic loader is NOT part of GCC, it's part of the operating system ๐). If the GOT for the linked executable goes over a machine-specific maximum, the linker yells that-fpicdoesn't work ๐, and then you just recompile with-fPICinstead. (Those maxes 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 to1โจ.
-fPICโ ๐ฅ if your target supports it, this emits position-independent code that's suitable for dynamic linking and has no limit on the size of the global offset table ๐. This option makes a difference on AArch64, m68k, PowerPC and SPARC.- Same deal as above: PIC needs special support, so it only works on certain machines ๐ .
- When this flag is set, the macros
"__pic__"and"__PIC__"are defined to2๐.
-fpie,-fPIEโ these are basically the cousins of-fpicand-fPIC๐ฆ, but the position-independent code can only be linked into executables (not shared libraries) ๐. Usually you use these when you're compiling code that gets linked with the-pieGCC option.- Both
-fpieand-fPIEdefine the macros"__pie__"and"__PIE__". The value is1for-fpieand2for-fPIE๐.
- Both
-fno-pltโ โจ this tells GCC to not use the PLT for external function calls in position-independent code ๐ธ. Instead, it loads the callee address at call sites from the GOT and branches to it. It's giving more efficient code, since it gets rid of PLT stubs and lets GOT loads be optimized ๐. On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in a specific register, this gives the compiler more register allocation freedom ๐ซถ. Heads up though: lazy binding needs the PLT, so with-fno-pltall external symbols get resolved at load time โฐ.- Want this for just some functions instead? Use the function attribute
"noplt"to avoid calls through the PLT for specific external functions ๐ง. - In position-dependent code, a few targets also convert calls to functions marked to not use the PLT so they use the GOT instead ๐.
- Want this for just some functions instead? Use the function attribute
-fno-jump-tablesโ ๐ โโ๏ธ no 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 this option isn't needed there ๐.-fno-bit-testsโ no bit tests forswitchstatements, even when they'd be more efficient than other code generation strategies ๐ซง.-ffixed-regโ ๐ treat the register named reg as a fixed register, so the generated code should never touch it (except maybe as a stack pointer, frame pointer, or in some other fixed role) ๐.- reg has to be the name of a register. The accepted names depend on the machine and are defined in the
REGISTER_NAMESmacro in the machine description macro file ๐. - This flag doesn't have a negative form, because it's a three-way choice ๐คทโโ๏ธ.
- reg has to be the name of a register. The accepted names depend on the machine and are defined in the
-fcall-used-regโ ๐ treat the register named reg as an allocable register that gets clobbered by function calls. It can be used for temporaries or variables that don't live across a call. Functions compiled this way do not save and restore reg ๐ซ.- It's an error to use this flag with the frame pointer or stack pointer ๐ซ.
- Using this on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results ๐.
- No negative form here either, since it's a three-way choice ๐ .
-fcall-saved-regโ ๐ก๏ธ treat the register named reg as 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 restore reg if they use it ๐ซถ.- Same rule: it's an error to use this with the frame pointer or stack pointer ๐ซ.
- Using it on other registers with fixed pervasive roles produces disastrous results ๐ญ.
- A different kind of disaster happens if you use this flag on a register that function values may be returned in ๐ช๏ธ.
- No negative form, three-way choice ๐ฆ.
-fpack-struct[=n]โ ๐ฆ without a value, this packs all structure members together with no holes. With a value (which has to be a small power of two), it packs structure members according to that value, which is the maximum alignment. So objects with default alignment requirements bigger than that get output potentially unaligned at the next fitting location ๐งฉ.
โ ๏ธ Warning, bestie: -fpack-struct makes GCC generate code that is not binary compatible with code generated without it. 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-underscoreforcibly change how C symbols are represented in the object file. One use is to help link with legacy assembly code ๐ง.
โ ๏ธ Warning: -fleading-underscore makes GCC generate code that is not binary compatible with code generated without it ๐. Use it only to conform to a non-default application binary interface. And not every target fully supports this switch, so check before you count on it ๐.
-ftls-model=modelโ ๐งต alter the thread-local storage model. The model argument should be one ofglobal-dynamic,local-dynamic,initial-execorlocal-exec๐ท. The choice is subject to optimization though, so the compiler might use a more efficient model for symbols that aren't visible outside the translation unit, or if-fpicisn't given on the command line ๐ง .- The default without
-fpicisinitial-exec. With-fpic, the default isglobal-dynamicโจ.
- The default without
-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 piece of code that gets created at run time on the stack when the address of a nested function is taken. It's used to call the nested function indirectly ๐ฆ. That means the stack has to be made executable for the program to work properly ๐ณ.
-fno-trampolinesis enabled by default on a language-by-language basis, so the compiler can skip generating trampolines when it figures that's safe and swap in 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-trampolinesis enabled by default only for Ada ๐.- Code compiled with
-ftrampolinesand code compiled with-fno-trampolinesare not binary compatible if nested functions are present. So this option has to be used program-wide, and it needs extreme care ๐ค. - For languages other than Ada,
-ftrampolinesand-fno-trampolinescurrently have no effect. Trampolines are always generated on platforms that need them for nested functions ๐ธ.
-ftrampoline-impl=[stack|heap]โ ๐ by default, trampolines get generated on the stack. But some platforms (like the Apple M1) don't allow an executable stack ๐ โโ๏ธ. Compiling with-ftrampoline-impl=heapgenerates calls to__gcc_nested_func_ptr_createdand__gcc_nested_func_ptr_deleted, which allocate and deallocate trampoline space on the executable heap ๐งบ. These functions are implemented in libgcc and only get 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. Be careful, bestie ๐.
-fvisibility=[default|internal|hidden|protected]โ ๐ this sets the default ELF image symbol visibility to the option you pick. Every symbol gets marked with it unless the code overrides it ๐. Using this can massively improve linking and load times of shared object libraries, produce more optimized code, give you near-perfect API export, and prevent symbol clashes ๐ฅ. It's strongly recommended that you use this in any shared objects you distribute ๐ซถ.- Despite the name,
defaultalways means public, meaning it's available to be linked against from outside the shared object ๐.protectedandinternalare pretty useless in real-world usage, so the only other one people commonly use ishidden๐. - If you don't specify
-fvisibility, the default isdefault, which makes every symbol public ๐ง. - A great explanation of why correct ELF symbol visibility matters is "How To Write Shared Libraries" by Ulrich Drepper, which you can find at
https://www.akkadia.org/drepper/๐. But here's the superior move ๐: instead of marking thingshiddenwhen the default is public, make the defaulthiddenand mark the things you want public. That's the norm with DLLs on Windows. With-fvisibility=hiddenand__attribute__ ((visibility("default")))instead of__declspec(dllexport), you get almost identical semantics with identical syntax ๐ฆ. It's a total boon for anyone working on cross-platform projects ๐ โจ.
- Despite the name,
Okay so, if you're adding visibility support to existing code, #pragma GCC visibility is literally your new bestie ๐ซถ. You wrap the declarations you want to control with #pragma GCC visibility push(hidden) and close it off with #pragma GCC visibility pop. โจ
Real talk though: symbol visibility is part of the API interface contract ๐, so all new code should always specify visibility whenever it isn't the default. Declarations that are only for use within the local DSO should ALWAYS be explicitly marked as hidden ๐, so you dodge PLT indirection overheads. Being super clear about it also helps readability and makes the code self-documenting. Iconic behavior ๐
. Heads up though: due to ISO C++ specification requirements, operator new and operator delete must always be of default visibility. Nonnegotiable ๐ญ.
Watch out for headers from outside your project ๐, especially system headers and headers from any other library you use. They might not be expecting to be compiled with any visibility other than the default. If that's the case, you may need to explicitly say #pragma GCC visibility push(default) before including them. ๐ธ
extern declarations are NOT affected by -fvisibility ๐ง, which means a lot of code can be recompiled with -fvisibility=hidden with zero modifications. Lowkey amazing. But here's the catch: calls to extern functions with no explicit visibility use 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 ๐. So, for instance, 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. Don't skip this one bestie ๐.
If you want the full tea on all these techniques, their benefits, and how to use them, check out the overview at https://gcc.gnu.org/wiki/Visibility. ๐ฆ
-fstrict-volatile-bitfields ๐
This one is for when accesses to volatile bit-fields (or other structure fields, although the compiler usually honors those types anyway) should use a single access of the width of the field's type, aligned to a natural alignment if possible. For example, targets with memory-mapped peripheral registers might require all such accesses to be 16 bits wide. With this flag you can declare all peripheral bit-fields as unsigned short (assuming short is 16 bits on these targets) to force GCC to use 16-bit accesses instead of, perhaps, a more efficient 32-bit access. ๐
If this option is disabled, the compiler uses the most efficient instruction. In the previous example, that might be a 32-bit load instruction, even though that accesses bytes that don't contain any part of the bit-field, or memory-mapped registers unrelated to the one being updated. Yikes ๐ฌ.
In some cases, such as when the packed attribute is applied to a structure field, it may not be possible to access the field with a single read or write that is correctly aligned for the target machine. In this case GCC falls back to generating multiple accesses rather than code that will fault or truncate the result at run time. Safe and sound ๐.
Note: Due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members. It is therefore recommended to define all bits of the field's type as bit-field members. ๐
The default value of this option is determined by the application binary interface for the target processor. โจ
-fsync-libcalls ๐ฅ
This option controls whether any out-of-line instance of the __sync family of functions may be used to implement the C++11 __atomic family of functions.
The default value of this option is enabled, so the only useful form of the option is -fno-sync-libcalls. This option is used in the implementation of the libatomic runtime library. ๐
๐ฆ GCC Developer Options ๐ฆ
This section covers command-line options that are mainly of interest to GCC developers, including options for compiler testing and for investigating compiler bugs and compile-time performance problems. That includes options that produce debug dumps at various points in the compilation, options that print statistics like memory use and execution time, and options that print info about GCC's configuration, like where it searches for libraries. You should rarely need any of these for ordinary compilation and linking tasks. ๐ค
Lots of developer options that make GCC dump output to a file take an optional =filename suffix. You can specify stdout or - to dump to standard output, and stderr for standard error. ๐
If =filename is omitted, a default dump file name is built 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 produced by the compiler if it was explicitly specified and isn't an executable; otherwise it's the source file name. The pass number is determined by the order passes are registered with the compiler's pass manager. This is generally the same as the order of execution, but passes registered by plugins, target-specific passes, or passes that are otherwise registered late are numbered higher than the pass named final, even if they're executed earlier. The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree). The files are created in the directory of the output file. ๐
-fcallgraph-info, -fcallgraph-info=MARKERS ๐ธ๏ธ
Makes the compiler output callgraph information for the program, on a per-object-file basis. The information is generated in the common VCG format. It can be decorated with additional, per-node and/or per-edge information, if a list of comma-separated markers is also specified. When the su marker is specified, the callgraph is decorated with stack usage information; it's equivalent to -fstack-usage. When the da marker is specified, the callgraph is decorated with information about dynamically allocated objects. ๐
When compiling with -flto, no callgraph information is output along with the object file. At LTO link time, -fcallgraph-info may generate multiple callgraph information files next to the intermediate LTO output files. ๐
-dletters, -fdump-rtl-pass, -fdump-rtl-pass=filename ๐งโโ๏ธ
Says to make debugging dumps during compilation at the times specified by letters. This is used for debugging the RTL-based passes of the compiler. ๐
Some -dletters switches have a different meaning when -E is used for preprocessing. ๐
Debug dumps can be enabled with a -fdump-rtl switch or some -d option letters. Here's the lineup of possible letters for use in pass and letters, and what each one means ๐
-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 is only run 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โ 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โ 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โ Enable dumping after the two common subexpression elimination passes. ๐ธ-fdump-rtl-dceโ Dumps after the standalone dead code elimination passes. ๐๏ธ-fdump-rtl-dbrโ Dumps after delayed branch scheduling. โณ-fdump-rtl-dce1,-fdump-rtl-dce2โ Enable dumping after the two dead store elimination passes. ๐-fdump-rtl-ehโ Dumps after finalization of EH handling code. ๐จ-fdump-rtl-eh_rangesโ Dumps after conversion of EH handling range regions. ๐บ๏ธ-fdump-rtl-expandโ Dumps after RTL generation. ๐ฑ-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ Enable dumping after the two forward propagation passes. โก๏ธ-fdump-rtl-gcse1,-fdump-rtl-gcse2โ Enable dumping after global common subexpression elimination. ๐-fdump-rtl-init-regsโ Dumps after the initialization of the registers. ๐-fdump-rtl-initvalsโ Dumps after the computation of the initial value sets. ๐ฑ-fdump-rtl-into_cfglayoutโ Dumps after converting to cfglayout mode. ๐งญ-fdump-rtl-iraโ Dumps after iterated register allocation. ๐๏ธ-fdump-rtl-jumpโ Dumps after the second jump optimization. ๐ฆ-fdump-rtl-loop2โ Enables dumping after the RTL loop optimization passes. ๐-fdump-rtl-machโ Dumps after performing the machine dependent reorganization pass, if that pass exists. ๐ค-fdump-rtl-mode_swโ Dumps after removing redundant mode switches. ๐๏ธ-fdump-rtl-rnregโ Dumps after register renumbering. ๐ข-fdump-rtl-outof_cfglayoutโ Dumps after converting from cfglayout mode. ๐งญ-fdump-rtl-peephole2โ Dumps after the peephole pass. ๐-fdump-rtl-postreloadโ Dumps after post-reload optimizations. ๐ง-fdump-rtl-pro_and_epilogueโ Dumps after generating the function prologues and epilogues. ๐ฌ-fdump-rtl-sched1,-fdump-rtl-sched2โ Enable dumping after the basic block scheduling passes. ๐๏ธ
-fdump-rtl-ree Dump after sign/zero extension elimination.
Hm bestie, I'm not even sure I need to show you a -fdump-rtl-ree example. Okay wait, no, let's get into it ๐
Okay, -fdump-rtl-ree is the one that dumps right after the sign/zero extension elimination pass. Lowkey iconic.
-fdump-rtl-seqabstr Dump after common sequence discovery.
Okay so -fdump-rtl-seqabstr gives you a dump after common sequence discovery. It's giving pattern-finding energy ๐โจ
-fdump-rtl-shorten Dump after shortening branches.
-fdump-rtl-shorten dumps after the branch-shortening pass. Main character energy for branches ๐ฆ
-fdump-rtl-sibling Dump after sibling call optimizations.
-fdump-rtl-sibling is the one for after sibling call optimizations. Slay ๐
-fdump-rtl-split1 -fdump-rtl-split2 -fdump-rtl-split3 -fdump-rtl-split4 -fdump-rtl-split5 These options enable dumping after five rounds of instruction splitting.
Okay bestie, these five are the splits. -fdump-rtl-split1 through -fdump-rtl-split5 each give you a dump after one of the five rounds of instruction splitting. Five rounds, no cap ๐
-fdump-rtl-sms Dump after modulo scheduling. This pass is only run on some architectures.
-fdump-rtl-sms dumps after modulo scheduling. Heads up, this one only runs on some architectures, so if it's not showing up, that's why ๐
-fdump-rtl-stack Dump after conversion from GCC's "flat register file" registers to the x87's stack-like registers. This pass is only run on x86 variants.
-fdump-rtl-stack is the dump after GCC turns its "flat register file" registers into the x87's stack-like registers. This pass only runs on x86 variants, so don't be surprised if it's missing elsewhere ๐
-fdump-rtl-subreg1 -fdump-rtl-subreg2 -fdump-rtl-subreg1 and -fdump-rtl-subreg2 enable dumping after the two subreg expansion passes.
Okay so -fdump-rtl-subreg1 and -fdump-rtl-subreg2 both give you dumps after the two subreg expansion passes. Two passes, two dumps, we love a matching set ๐ง
-fdump-rtl-unshare Dump after all rtl has been unshared.
-fdump-rtl-unshare dumps after all the RTL has been unshared. Unshared and iconic ๐
-fdump-rtl-vartrack Dump after variable tracking.
-fdump-rtl-vartrack is the one for after variable tracking ๐ซถ
-fdump-rtl-vregs Dump after converting virtual registers to hard registers.
-fdump-rtl-vregs dumps after virtual registers have been converted to hard registers. Virtual to hard, the ultimate glow-up โจ
-fdump-rtl-web Dump after live range splitting.
-fdump-rtl-web dumps after live range splitting. It's giving web-weaving vibes ๐ธ๏ธ๐
-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 always produce empty files.
Bestie, I have to warn you about these five: -fdump-rtl-regclass, -fdump-rtl-subregs_of_mode_init, -fdump-rtl-subregs_of_mode_finish, -fdump-rtl-dfinit, and -fdump-rtl-dfinish are defined but always produce empty files. Don't waste your time staring at them ๐
-da -fdump-rtl-all Produce all the dumps listed above.
-da and -fdump-rtl-all both produce all the dumps listed above. The whole buffet ๐
-dA Annotate the assembler output with miscellaneous debugging information.
-dA adds miscellaneous debugging information to the assembler output. Extra annotations, extra cute ๐
-dD Dump all macro definitions, at the end of preprocessing, in addition to normal output.
-dD dumps all macro definitions at the end of preprocessing, on top of the normal output. Every macro, served ๐
-dH Produce a core dump whenever an error occurs.
-dH makes GCC produce a core dump whenever an error occurs. Errors, hit different now ๐ญ
-dp Annotate the assembler output with a comment indicating which pattern and alternative is used. The length and cost of each instruction are also printed.
-dp annotates the assembler output with a comment saying which pattern and alternative got used. It also prints the length and cost of each instruction. Receipts for every instruction ๐งพ๐ธ
-dP Dump the RTL in the assembler output as a comment before each instruction. Also turns on -dp annotation.
-dP puts the RTL in the assembler output as a comment before each instruction. It also turns on the -dp annotation, so you get both ๐ฆ
-dx Just generate RTL for a function instead of compiling it. Usually used with -fdump-rtl-expand.
-dx just generates RTL for a function instead of compiling it all the way. It's usually paired with -fdump-rtl-expand ๐งโจ
-fdump-debug Dump debugging information generated during the debug generation phase.
-fdump-debug dumps the debugging information generated during the debug generation phase. Debug tea, spilled โ
-fdump-earlydebug Dump debugging information generated during the early debug generation phase.
-fdump-earlydebug does the same thing but for the early debug generation phase. Early bird debug gets the worm ๐
-fdump-noaddr When doing debugging dumps, suppress address output. This makes it more feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations.
Okay this one is so useful, bestie. -fdump-noaddr hides address output in debugging dumps, which makes it way easier to diff dumps when your compiler invocations use different compiler binaries, or different text, bss, data, heap, stack, or dso start locations. Less noise, more vibes ๐ซถ๐
-freport-bug Collect and dump debug information into a temporary file if an internal compiler error (ICE) occurs.
-freport-bug collects and dumps debug information into a temporary file if an internal compiler error (ICE) happens. Ate that ICE, and left no crumbs ๐ฅน
-fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. This makes it more feasible to use diff on debugging dumps for compiler invocations with different options, in particular with and without -g.
-fdump-unnumbered suppresses instruction numbers and address output in debugging dumps. That makes diff way more feasible when your invocations use different options, especially with and without -g ๐
-fdump-unnumbered-links When doing debugging dumps (see -d option above), suppress instruction numbers for the links to the previous and next instructions in a sequence.
-fdump-unnumbered-links is for when you're doing debugging dumps (see the -d option above). It suppresses instruction numbers for the links to the previous and next instructions in a sequence. Links with no numbers, no drama ๐๐
-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 is created in the same directory as the output file. The following dumps are possible:
Okay so -fdump-ipa-switch and -fdump-ipa-switch-options control dumping at various stages of inter-procedural analysis language tree to a file. The file name comes from 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 pick from:
all Enables all inter-procedural analysis dumps.
cgraph Dumps information about call-graph optimization, unused function removal, and inlining decisions.
inline Dump after function inlining.
strubm Dump after selecting "strub" modes, and recording the selections as function attributes.
strub Dump "strub" transformations: interface changes, function wrapping, and insertion of builtin calls for stack scrubbing and watermarking.
Additionally, the options -optimized, -missed, -note, and -all can be provided, with the same meaning as for -fopt-info, defaulting to -optimized.
For example, -fdump-ipa-inline-optimized-missed will emit information on callsites that were inlined, along with callsites that were not inlined.
By default, the dump will contain messages about successful optimizations (equivalent to -optimized) together with low-level details about the analysis.
-fdump-lang Dump language-specific information. The file name is made by appending .lang to the source file name.
-fdump-lang dumps language-specific information. The file name is made by appending .lang to 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 information. The options and filename portions behave as described in the -fdump-tree option. The following switch values are accepted:
-fdump-lang-all, -fdump-lang-switch, -fdump-lang-switch-options, and -fdump-lang-switch-options=filename control the dumping of language-specific information. The options and filename parts work the same way as described under -fdump-tree. These switch values are accepted:
all Enable all language-specific dumps.
class Dump class hierarchy information. Virtual table information is emitted unless 'slim' is specified. This option is applicable to C++ only.
module Dump module information. Options lineno (locations), graph (reachability), blocks (clusters), uid (serialization), alias (mergeable), asmname (Elrond), eh (mapper) & vops (macros) may provide additional information. This option is applicable to C++ only.
raw Dump the raw internal tree data. This option is applicable to C++ only.
-fdump-passes Print on stderr the list of optimization passes that are turned on and off by the current command-line options.
-fdump-passes prints to stderr the list of optimization passes that are turned on and off by your current command-line options ๐โจ
-fdump-statistics-option Enable and control dumping of pass statistics in a separate file. The file name is generated by appending a suffix ending in .statistics to the source file name, and the file is created in the same directory as the output file. If the -option form is used, -stats causes counters to be summed over the whole compilation unit while -details dumps every event as the passes generate them. The default with no option is to sum counters for each function compiled.
-fdump-statistics-option turns on and controls pass statistics dumping into a separate file. The file name comes from appending a suffix ending in .statistics to the source file name, and it gets created in the same directory as the output file. With the -option form, -stats sums counters over the whole compilation unit, while -details dumps every event as the passes generate them. With no option, the default is to sum counters for each function compiled ๐๐
-fdump-tree-all -fdump-tree-switch -fdump-tree-switch-options -fdump-tree-switch-options=filename Control the dumping at various stages of processing the intermediate language tree to a file. If the -options form is used, options is a list of - separated options which control the details of the dump. Not all options are applicable to all dumps; those that are not meaningful are ignored. The following options are available
Okay, -fdump-tree-all, -fdump-tree-switch, -fdump-tree-switch-options, and -fdump-tree-switch-options=filename control dumping at various stages of processing the intermediate language tree to a file. If you use the -options form, options is a list of - separated options that control the details of the dump. Not every option works with every dump, and the ones that don't apply just get ignored. These are the options available:
address Print the address of each node. Usually this is not meaningful as it changes according to the environment and source file. Its primary use is for tying up a dump file with a debug environment.
asmname If "DECL_ASSEMBLER_NAME" has been set for a given decl, use that in the dump instead of "DECL_NAME". Its primary use is ease of use working backward from mangled names in the assembly file.
slim When dumping front-end intermediate representations, inhibit dumping of members of a scope or body of a function merely because that scope has been reached. Only dump such items when they are directly reachable by some other path.
When dumping pretty-printed trees, this option inhibits dumping the bodies of control structures.
When dumping RTL, print the RTL in slim (condensed) form instead of the default LISP-like representation.
raw Print a raw representation of the tree. By default, trees are pretty-printed into a C-like representation.
details Enable more detailed dumps (not honored by every dump option). Also include information from the optimization passes.
stats Enable dumping various statistics about the pass (not honored by every dump option).
blocks Enable showing basic block boundaries (disabled in raw dumps).
graph For each of the other indicated dump files (-fdump-rtl-pass), dump a representation of the control flow graph suitable for viewing with GraphViz to file.passid.pass.dot. Each function in the file is pretty-printed as a subgraph, so that GraphViz can render them all in a single plot.
This option currently only works for RTL dumps, and the RTL is always dumped in slim form.
vops Enable showing virtual operands for every statement.
lineno Enable showing line numbers for statements.
uid Enable showing the unique ID ("DECL_UID") for each variable.
verbose Enable showing the tree dump for each statement.
eh Enable showing the EH region number holding each statement.
scev Enable showing scalar evolution analysis details.
optimized Enable showing optimization information (only available in certain passes).
missed Enable showing missed optimization information (only available in certain passes).
note Enable other detailed optimization information (only available in certain passes).
all Turn on all options, except raw, slim, verbose and lineno.
optall Turn on all optimization options, i.e., optimized, missed, and note.
To determine what tree dumps are available or find the dump for a pass of interest follow the steps below.
- Invoke GCC with -fdump-passes and in the stderr output look for a code that corresponds to the pass you are interested in. For example, the codes "tree-evrp", "tree-vrp1", and "tree-vrp2" correspond to the three Value Range Propagation passes. The number at the end distinguishes distinct invocations of the same pass.
- To enable the creation of the dump file, append the pass code to the -fdump- option prefix and invoke GCC with it. For example, to enable the dump from the Early Value Range Propagation pass, invoke GCC with the -fdump-tree-evrp option. Optionally, you may specify the name of the dump file. If you don't specify one, GCC creates as described below.
- Hunt down the pass dump in a file whose name has three parts joined by periods: the name of the source file GCC was invoked to compile, a numeric suffix for the pass number followed by
tfor tree passes (orrfor 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. ngl, the numeric codes are not stable, so they can change from one version of GCC to another ๐
-fopt-info, -fopt-info-options, -fopt-info-options=filename
Okay so this one controls the optimization dumps coming out of the various optimization passes ๐
. If you use the -options form, options is a list of --separated keywords that pick the dump details and the optimizations you want. Think of it as building a little playlist ๐
The options come in three groups ๐:
- options describing what kinds of messages should be emitted,
- options describing the verbosity of the dump, and
- options describing which optimizations should be included.
You can mix options from each group freely because they don't overlap ๐ซถ. If there's ever a conflict, the later option on the command line wins.
These options control which kinds of messages get emitted:
optimizedโ Prints information when an optimization is successfully applied. Each pass gets to decide what's relevant. For example, the vectorizer passes print the source location of loops that were 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 one controls the dump verbosity:
internalsโ By default, only "high-level" messages are emitted. This turns on extra, more detailed messages that are mostly of interest to GCC developers ๐ค.
One or more of these option keywords can be used to describe a group of optimizations:
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 while skipping anything marked as "internals" โจ.
If you give a filename, the dumps from all the applicable optimizations get concatenated into it. Otherwise, the dump goes to stderr. You can use several -fopt-info options, but only one of them can include a filename. If other filenames are provided, all but the first such option get ignored.
Heads up: the output filename gets overwritten when there are multiple translation units. If you want combined output from several of them, use stderr instead.
Here's the example where the optimization info goes 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. Fun fact: -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
As another example, this outputs info about missed optimizations as well as 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 are in conflict, since only one output file is allowed. In this case, only the first option takes effect and the subsequent options are ignored. So only vec.miss gets produced, and it contains dumps from the vectorizer about missed opportunities ๐
.
-fsave-optimization-record
This writes a SRCFILE.opt-record.json.gz file detailing what optimizations were performed, for the ones that support -fopt-info ๐.
โ ๏ธ This option is experimental, and the format of the data inside the compressed JSON file is subject to change.
It's roughly 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 this 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 you 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), you can tell the copies apart,
- objects identifying those parts of the message that refer to expressions, statements or symbol-table nodes, which of these categories they are, and, when available, their source code location,
- the GCC pass that emitted the message, and
- the location in GCC's own code from which the message was emitted
Additionally, some messages are logically nested within other messages, reflecting implementation details of the optimization passes ๐งฉ.
-fsched-verbose=n
On targets that use instruction scheduling, this controls how much debugging output the scheduler prints to the dump files ๐ง . The levels stack up like this:
- For
ngreater than zero,-fsched-verboseoutputs the same information as-fdump-rtl-sched1and-fdump-rtl-sched2. - For
ngreater than one, it also outputs basic block probabilities, detailed ready list information, and unit/insn info. - For
ngreater than two, it includes RTL at the abort point, control-flow, and regions info. - For
nover four,-fsched-verbosealso includes dependence info.
-fenable-kind-pass, -fdisable-kind-pass=range-list
This is a whole set of options for explicitly disabling and enabling optimization passes ๐ง. They're meant for debugging GCC itself, so regular compiler users should use the regular options for enabling and disabling passes instead ๐.
-fdisable-ipa-passโ Disables the IPA pass pass, where pass is the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from 1.-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ Disables the RTL pass pass, where pass is the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from 1. range-list is a comma-separated list of function ranges or assembler names. Each range is a number pair separated by a colon, and the range is inclusive at both ends. If the range is trivial, the number pair can be simplified to a single number. If the function's call graph node's uid falls within one of the specified ranges, the pass is disabled for that function. The uid is shown in the function header of a dump file, and the pass names can be dumped by using option-fdump-passes.-fdisable-tree-pass,-fdisable-tree-pass=range-listโ Disables the tree pass pass. See-fdisable-rtlfor the description of option arguments.-fenable-ipa-passโ Enables the IPA pass pass, where pass is the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from 1.-fenable-rtl-pass,-fenable-rtl-pass=range-listโ Enables the RTL pass pass. See-fdisable-rtlfor option argument description and examples.-fenable-tree-pass,-fenable-tree-pass=range-listโ Enables the tree pass pass. See-fdisable-rtlfor the description of option arguments.
Here are some examples showing how these options get used ๐:
# 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
This turns on internal consistency checking ๐ง. The default depends on the compiler configuration. -fchecking=2 turns on further internal consistency checking, which might affect code generation.
-frandom-seed=string
This option gives GCC a seed to use in place of random numbers when it generates certain symbol names that have to be different in every compiled file ๐ฒ. The seed is also used to place unique stamps in coverage data files and in the object files that produce them. You can use the -frandom-seed option to produce reproducibly identical object files ๐ธ.
The string can be a number (decimal, octal or hex) or an arbitrary string. An arbitrary string gets converted to a number by computing CRC32 ๐.
The string has to be different for every single file you compile, no repeats ๐ซถ
-save-tempsโ okay so this one keeps all the usual "temporary" intermediate files permanently ๐พ instead of tossing them. They get named as auxiliary output files, the same way as described under-dumpbaseand-dumpdir.
When you pair it with -x, -save-temps is smart enough to avoid overwriting an input source file that shares an extension with an intermediate file ๐ง If you want that intermediate file, you can rename the source file before using -save-temps.
-save-temps=cwdโ the same as-save-temps -dumpdir ./.๐-save-temps=objโ the same as-save-temps -dumpdir outdir/, whereoutdir/is the directory of the output file given after-o, including any directory separators ๐๏ธ If you don't use-o, then-save-temps=objacts 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, 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 executing the program itself. The second is the "system time," which is the time spent in operating system routines on behalf of the program. Both numbers are in seconds โ
With an output file, the output gets appended to the named file and 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 always tell later what file got compiled and with which options ๐
-fdump-final-insns[=file]โ dumps the final internal representation (RTL) to file ๐ If you leave out the optional argument (or file is.), the dump file name is made by appending.gkdto the dump base name. See-dumpbase.-fcompare-debug[=opts]โ if no error happens during compilation, the compiler runs a second time with opts and-fcompare-debug-secondadded to its arguments ๐ It dumps the final internal representation in both compilations and prints an error if they differ. If you leave off the equal sign, the default-gtoggleis 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 gets 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 -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any actual compilation (rather than preprocessing, assembly or linking) ๐ If you just want a warning, setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do the job.
-fcompare-debug-secondโ this one gets implicitly passed to the compiler for the second compilation requested by-fcompare-debug, along with options to silence warnings ๐ It skips 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 extra ".gk" extension during the 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 much only useful for 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 in the command line doesn't matter. It takes effect after all other options are processed, and it only does this 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-assignmentsthe same way-gtoggletoggles-g๐-Qโ makes the compiler print out each function name as it's compiled, and print some statistics about each pass when it finishes ๐จ๏ธ-ftime-reportโ makes the compiler print some statistics to stderr about the time consumed by each pass when it finishes โฐ
If SARIF output of diagnostics was requested via -fdiagnostics-format=sarif-file or -fdiagnostics-format=sarif-stderr, then the -ftime-report info gets emitted as JSON inside the SARIF output instead ๐งพ The exact format of that JSON is subject to change. The values might not match exactly what goes to stderr, since they're written out at a slightly different spot inside the compiler.
-ftime-report-detailsโ records the time consumed by infrastructure parts separately for each pass ๐ฌ-fira-verbose=nโ controls how verbose the dump file for the integrated register allocator is ๐งฉ The default value is 5. If n is 10 or greater, the dump output goes to stderr in the same format as n minus 10.-flto-reportโ prints a report with internal details on how the link-time optimizer works ๐ง What's in the report changes from version to version. It's meant to be helpful to GCC developers when they're processing object files in LTO mode (via-flto). It's disabled by default.-flto-report-wpaโ like-flto-report, but only prints for the WPA phase of link-time optimization ๐ฏ-fmem-reportโ makes the compiler print some statistics about permanent memory allocation when it finishes ๐ง-fmem-report-wpaโ makes the compiler print some statistics about permanent memory allocation for the WPA phase only ๐ฏ-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ makes the compiler print some statistics about permanent memory allocation before or after interprocedural optimization ๐
-fmultiflagsโ this option enables multilib-aware "TFLAGS" to be used to build 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," this lets target libraries be built for portable baseline environments, while the compiler defaults to more demanding ones ๐ That's useful because users can easily override the compiler's defaults to build their own programs when those defaults aren't ideal for their target environment. Rebuilding the runtime libraries is usually not as easy or desirable, though.
Unlike "TFLAGS," using specs lets different flags be selected for different multilibs โจ The way to do that is to build with make TFLAGS=-fmultiflags, after configuring --with-specs=%{fmultiflags:...}.
This option is discarded by the driver once it's done processing driver self spec.
It's also handy for checking that "TFLAGS" are being used to build all target libraries ๐ Just configure a non-bootstrap compiler with --with-specs='%{!fmultiflags:%emissing TFLAGS}', then build the compiler and target libraries.
-fprofile-reportโ makes the compiler print some statistics about the consistency of the (estimated) profile and the effect of individual passes ๐-fstack-usageโ makes the compiler output stack usage information for the program, on a per-function basis ๐ฅ The filename for the dump is made by appending.suto the auxname. The auxname comes from the name of the output file if it's explicitly specified and 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 qualifier "static" means the function manages 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 qualifier "dynamic" means the function manages the stack dynamically. On top of the static allocation, stack adjustments get made in the body of the function, like pushing and popping arguments around function calls ๐ If "bounded" is also present, the amount of those adjustments is bounded at compile time, and the second field is an upper bound on the total stack used by the function. If "bounded" isn't present, the amount of adjustments isn't bounded at compile time, and the second field only represents the bounded part.
-fstatsโ emits statistics about front-end processing at the end of the compilation ๐ Only the C++ front end supports this, and the info is generally only useful to the G++ development team ๐ค-fdbg-cnt-listโ prints the name and the counter upper bound for all debug counters ๐ข-fdbg-cnt=counter-value-listโ sets the internal debug counter lower and upper bounds ๐๏ธ counter-value-list is a comma-separated list ofname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]tuples. These set the name of the counter and a list of closed intervals. Thelower_boundis optional and is zero initialized if it isn't set.
For example, with -fdbg-cnt=dce:2-4:10-11,tail_call:10, dbg_cnt(dce) returns true only for the second, third, fourth, tenth and eleventh invocation ๐ฏ For dbg_cnt(tail_call), true is returned for the first 10 invocations.
-print-file-name=libraryโ prints the full absolute name of the library file library that would be used when linking, and then that's it ๐บ๏ธ With this option, GCC doesn't compile or link anything. It just prints the file name ๐-print-multi-directory: Prints the directory name for whichever multilib gets picked by any other switches on your command line ๐ It's supposed to exist insideGCC_EXEC_PREFIXโจ-print-multi-lib: Prints the map from multilib directory names to the switches that turn them on ๐บ๏ธ The directory name is separated from the switches by;, and each switch starts with@instead of-, with no spaces between multiple switches. This is supposed to make shell processing way easier ๐-print-multi-os-directory: Prints the path to OS libraries for the selected multilib, relative to somelibsubdirectory ๐ธ If OS libraries sit in thelibsubdirectory and no multilibs are used, it's usually just.. If they're inlibsuffixsibling directories, you'll see things like../lib64,../libor../lib32. If they're inlib/subdirsubdirectories, you'll get stuff likeamd64,sparcv9orev6๐ฆ-print-multiarch: Prints the path to OS libraries for the selected multiarch, relative to somelibsubdirectory ๐ง-print-prog-name=program: Basically-print-file-name, but it searches for a program likecppinstead ๐-print-libgcc-file-name: Same as-print-file-name=libgcc.a๐
This one is lowkey clutch when you use -nostdlib or -nodefaultlibs but still 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 directoriesgccsearches. It doesn't do anything else, so don't expect a compile ๐
This is the one you want when gcc yells installation problem, cannot exec cpp0: No such file or directory. To fix that, 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 used during compilation ๐ฐ That's the one set at configure time or with--sysroot, possibly with an extra suffix that depends on your compilation options. If no target sysroot is specified, this prints nothing at all ๐คทโโ๏ธ-print-sysroot-headers-suffix: Prints the suffix added to the target sysroot when searching for headers. If the compiler wasn't configured with one, you'll get an error instead, and it won't do anything else ๐-dumpmachine: Prints the compiler's target machine, likei686-pc-linux-gnu. Then it stops, no other business ๐-dumpversion: Prints the compiler version, like3.0,6.3.0or7, and then it's done โจ This is the version used in filesystem paths and specs. Depending on how the compiler was configured, it can be one number (the major version), two numbers separated by a dot (major and minor), or three numbers separated by dots (major, minor and patchlevel) ๐ฅ-dumpfullversion: Prints the full compiler version, then stops. The output is always three numbers separated by dots: major, minor and patchlevel ๐-dumpspecs: Prints the compiler's built-in specs and then stops ๐ง (This is used when GCC itself is being built, so it's mostly for the compiler devs, bestie ๐ซถ)
๐ฆ Machine-Dependent Options ๐ฆ
Each target machine GCC supports can have its own options. For example, you might use them to compile for a particular processor variant or ABI, or to 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 additional target-specific options, usually so it plays nicely 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 permissible 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. Also, 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 ๐
-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 won'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 ๐ This makes no assumptions about addresses and sizes of sections. Programs can be statically linked only.
The-mcmodel=largeoption is incompatible with-mabi=ilp32,-fpicand-fPIC. Don't mix them up, bestie ๐ซ
-mtp=name: Specifies the system register to use as a thread pointer ๐งต The valid values aretpidr_el0,tpidrro_el0,tpidr_el1,tpidr_el2andtpidr_el3. For backwards compatibility, the aliasesel0,el1,el2andel3are also accepted. The default setting istpidr_el0.
It's recommended to compile all code that's meant to interoperate with the same value of this option, so you don't accidentally access a different thread pointer from the wrong exception level ๐ญ
-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 ๐-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointer: Omits or keeps the frame pointer in leaf functions ๐ The former behavior is the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset: Generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register ๐ก๏ธ
With the sysreg choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset specify which system register to use as the base register for reading the canary, and what offset from that base register to use. There is no default register or offset, because this is entirely for use within the Linux kernel ๐ง
-mtls-dialect=desc: Uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables. This is the default ๐-mtls-dialect=traditional: Uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐ฐ๏ธ-mtls-size=size: Specifies the bit size of immediate TLS offsets. The valid values are12,24,32and48. This option requires binutils 2.26 or newer ๐ง-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769: Enables or disables the workaround for ARM Cortex-A53 erratum number 835769 ๐ฉน This involves inserting a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions.-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419: Enables or disables the workaround for ARM Cortex-A53 erratum number 843419 ๐ฉน This erratum workaround is made at link time, so this option only passes the corresponding flag to the linker.-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrt: Enables or disables the reciprocal square root approximation โก This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of reciprocal square root results to about 16 bits for single precision and about 32 bits for double precision.-mlow-precision-sqrt,-mno-low-precision-sqrt: Enables or disables the square root approximation ๐ This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of square root results to about 16 bits for single precision and about 32 bits for double precision. If enabled, it implies-mlow-precision-recip-sqrt.-mlow-precision-div,-mno-low-precision-div: Enables or disables the division approximation โ This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of division results to about 16 bits for single precision and about 32 bits for double precision.-mtrack-speculation,-mno-track-speculation: Enables or disables generation of additional code to track speculative execution through conditional branches ๐ The tracking state can then be used by the compiler when expanding calls to"__builtin_speculation_safe_copy", so it can generate a more efficient code sequence.-moutline-atomics,-mno-outline-atomics: Enables or disables calls to out-of-line helpers that implement atomic operations ๐งฉ At runtime, these helpers figure out whether the LSE instructions from ARMv8.1-A can be used. If not, they fall back to the load/store-exclusive instructions that are present in the base ARMv8.0 ISA.
This option is only applicable when compiling for the base ARMv8.0 instruction set. If you're using a later revision, like -march=armv8.1-a or -march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for -mcpu= when the selected CPU supports the lse feature. This option is on by default ๐ฅ
-march=name: Specifies the name of the target architecture and, optionally, one or more feature modifiers ๐๏ธ This option has the form-march=arch{+[no]feature}*.
The table just below sums up the permissible values for arch and the features that each one enables by default ๐
okay so here's the whole architecture lineup, bestie ๐ each row reads arch value : Architecture : Includes by default, so you can see what every value is and what extra bits come along with it โจ
arch value : Architecture : Includes by default
armv8-a : Armv8-A : +fp, +simd
armv8.1-a : Armv8.1-A : armv8-a, +crc, +lse, +rdma
armv8.2-a : Armv8.2-A : armv8.1-a
armv8.3-a : Armv8.3-A : armv8.2-a, +pauth
armv8.4-a : Armv8.4-A : armv8.3-a, +flagm, +fp16fml, +dotprod
armv8.5-a : Armv8.5-A : armv8.4-a, +sb, +ssbs, +predres
armv8.6-a : Armv8.6-A : armv8.5-a, +bf16, +i8mm
armv8.7-a : Armv8.7-A : armv8.6-a, +ls64
armv8.8-a : Armv8.8-a : armv8.7-a, +mops
armv8.9-a : Armv8.9-a : armv8.8-a
armv9-a : Armv9-A : armv8.5-a, +sve, +sve2
armv9.1-a : Armv9.1-A : armv9-a, +bf16, +i8mm
armv9.2-a : Armv9.2-A : armv9.1-a, +ls64
armv9.3-a : Armv9.3-A : armv9.2-a, +mops
armv9.4-a : Armv9.4-A : armv9.3-a
armv8-r : Armv8-R : armv8-r
The value native is available on native AArch64 GNU/Linux and makes the compiler pick the architecture of the host system ๐ If the compiler can't recognize the host system's architecture, this option just does nothing, so no drama ๐ซถ
The permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one wins ๐
GCC looks at name to decide what kind of instructions it's allowed to emit when generating assembly code ๐
If you use -march without also using -mtune or -mcpu, the code gets tuned to perform well across a whole range of target processors that implement the target architecture โจ
๐ -mtune=name
Here you tell GCC the name of the target processor it should tune the performance of your 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, neoverse-512tvb, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-v1, neoverse-v2, qdf24xx, saphira, phecda, xgene1, vulcan, octeontx, octeontx81, octeontx83, octeontx2, octeontx2t98, octeontx2t96, octeontx2t93, octeontx2f95, octeontx2f95n, octeontx2f95mm, a64fx, 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-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, cortex-a510, cortex-a520, cortex-a710, cortex-a715, cortex-a720, ampere1, ampere1a, ampere1b, cobalt-100 and native.
The values cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55 and cortex-a76.cortex-a55 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 ๐ฅ Basically, the option 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). It's 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 recognize the processor of the host system, this option has no effect ๐ธ
If none of -mtune=, -mcpu= or -march= are specified, the code is tuned to perform well across a range of target processors ๐
This option cannot be suffixed by feature modifiers ๐
๐ท -mcpu=name
Here you name the target processor, and you can optionally suffix it with one or more feature modifiers โจ The form is -mcpu=cpu{+[no]feature}*, where the permissible values for cpu are the same as the ones for -mtune ๐ The permissible values for feature are documented in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. Again, if feature modifiers conflict, the right-most feature is used ๐
GCC uses name to figure out what kind of instructions it can emit when generating assembly code (just like -march does) and to figure out which target processor to tune for performance (just like -mtune does) ๐
If you use this option together with -march or -mtune, those options take precedence over the matching part of this option ๐ซถ
-mcpu=neoverse-512tvb is special, because it doesn't refer to one specific core. Instead it refers to all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle ๐ญ Unless you override it with -march, -mcpu=neoverse-512tvb generates code that can run on a Neoverse V1 core, since Neoverse V1 is the first Neoverse core with these properties ๐ฆ Unless you override it with -mtune, -mcpu=neoverse-512tvb tunes code in the same way as for -mtune=neoverse-512tvb ๐
๐ซง -moverride=string
This lets you override the tuning decisions the back-end makes in response to a -mtune= switch ๐
โ ๏ธ The syntax, semantics, and accepted values for string in this option are not guaranteed to be consistent across releases. It's only intended to be useful when developing GCC, so maybe don't go wild with it ๐
๐ -mverbose-cost-dump
This turns on verbose cost model dumping in the debug dump files ๐ง It's provided for debugging the compiler, so it's more of a GCC-dev thing ๐
๐ -mpc-relative-literal-loads / -mno-pc-relative-literal-loads
These enable or disable PC-relative literal loads ๐ธ With this option on, literal pools get accessed using a single instruction and are emitted after each function. The catch is that this limits the maximum size of functions to 1MB โจ It's enabled by default for -mcmodel=tiny ๐ฆ
๐ชฝ -msign-return-address=scope
This picks the function scope that return address signing gets applied to ๐
The permissible values are none, which disables return address signing; non-leaf, which enables pointer signing for functions that aren't leaf functions; and all, which enables pointer signing for all functions ๐ซถ The default value is none.
โ ๏ธ This option has been deprecated by -mbranch-protection, so switch over when you can ๐ญ
๐ก๏ธ -mbranch-protection=none|standard|pac-ret[+leaf+b-key]|bti
This selects which branch protection features to use ๐ none is the default and turns off all types of branch protection. standard turns on all types of branch protection features, and if a feature has additional tuning options, standard sets it to its standard level ๐
pac-ret[+leaf] turns on return address signing to its standard level, which means signing functions that save the return address to memory (non-leaf functions will practically always do this) using the a-key ๐ The optional argument leaf can be used to extend the signing to include leaf functions. The optional argument b-key can be used to sign the functions with the B-key instead of the A-key ๐
bti turns on the branch target identification mechanism ๐
๐งฑ -mharden-sls=opts
This enables compiler hardening against straight line speculation (SLS) ๐ opts is a comma-separated list of the following options:
retbrblr
On top of that, -mharden-sls=all enables all SLS hardening, while -mharden-sls=none disables all SLS hardening ๐ซง
๐ฐ๏ธ -mearly-ra=scope
This determines when to enable an early register allocation pass โจ The pass runs before instruction scheduling and tries to find a spill-free allocation of floating-point and vector code. It also tries to make use of strided multi-register instructions, such as SME2's strided LD1 and ST1 ๐
The possible values of scope are:
allโ runs the pass on all functionsstridedโ runs the pass on functions that have access to strided multi-register instructionsnoneโ disables the pass
-mearly-ra=all is the default for -O2 and above, and for -Os. -mearly-ra=none is the default otherwise ๐ธ
โก -mearly-ldp-fusion
This enables the copy of the AArch64 load/store pair fusion pass that runs before register allocation ๐ฅ It's enabled by default at -O and above ๐
โก -mlate-ldp-fusion
This enables the copy of the AArch64 load/store pair fusion pass that runs after register allocation ๐ฅ It's also enabled by default at -O and above ๐
๐ -msve-vector-bits=bits
This specifies the number of bits in an SVE vector register ๐ฆ It only has an effect when SVE is enabled, so no SVE, no vibes ๐
GCC supports two forms of SVE code generation. "Vector-length agnostic" output works with any size of vector register, and "vector-length specific" output lets GCC make assumptions about the vector length when that's useful for optimization reasons ๐ง The possible values of bits are scalable, 128, 256, 512, 1024 and 2048. Specifying scalable selects vector-length agnostic output. At present, -msve-vector-bits=128 also generates vector-length agnostic output for big-endian targets. All other values generate vector-length specific code ๐
โ ๏ธ The behaviour of these values may change in future releases, and no value except scalable should be relied on for producing code that's portable across different hardware SVE vector lengths. Be careful out there, bestie ๐ญ
The default is -msve-vector-bits=scalable, which produces vector-length agnostic code ๐ซถ
โจ -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, nofeature ๐ท
crcโ enables the CRC extension. This is on by default for-march=armv8.1-a๐ฅcryptoโ enables the Crypto extension. This also enables Advanced SIMD and floating-point instructions ๐fpโ enables floating-point instructions. This is on by default for all possible values for options-marchand-mcpu๐simdโ enables Advanced SIMD instructions. This also enables floating-point instructions. This is on by default for all possible values for options-marchand-mcpu๐ฆsveโ enables Scalable Vector Extension instructions. This also enables Advanced SIMD and floating-point instructions ๐งlseโ enables Large System Extension instructions. This is on by default for-march=armv8.1-a๐ธrdmaโ enables Round Double Multiply Accumulate instructions. This is on by default for-march=armv8.1-aโจ
Okay bestie, the AArch64 feature list is giving main character energy ๐
Every +feature you can flip on, plus which ones come bundled ๐
fp16โ Turns on the FP16 extension โจ and brings the floating-point instructions along for the ride ๐ฅfp16fmlโ Turns on the FP16fmlaextension ๐. It also switches on the FP16 extensions and floating-point instructions. It's on by default for-march=armv8.4-a. Using it with anything older than Armv8.2-A is not supported ๐rcpcโ Turns on the RCpc extension ๐ฆ. That means theLDAPRinstructions get used for load-acquire atomic semantics, and it's passed along to the assembler so inline asm statements can use RCpc instructions toodotprodโ Turns on the Dot Product extension ๐. It also enables Advanced SIMD instructionsaesโ Turns on the Armv8-aaesandpmullcrypto extension ๐. Advanced SIMD instructions come with itsha2โ Turns on the Armv8-asha2crypto extension ๐ธ. Advanced SIMD instructions come with it toosha3โ Turns on thesha512andsha3crypto extension ๐. Advanced SIMD instructions come along. Using it with architectures prior to Armv8.2-A is not supported ๐sm4โ Turns on thesm3andsm4crypto extension ๐ง. Advanced SIMD instructions come along. Using it with architectures prior to Armv8.2-A is not supported ๐profileโ Turns on the Statistical Profiling extension ๐. This only enables it at the assembler level, so code generation stays the samerngโ Turns on the Armv8.5-a Random Number instructions ๐ฒ. Assembler level only, so code generation isn't affectedmemtagโ Turns on the Armv8.5-a Memory Tagging Extensions ๐ท๏ธ. Using it with architectures prior to Armv8.5-A is not supported ๐sbโ Turns on the Armv8-a Speculation Barrier instruction ๐ง. This only enables it at the assembler level and doesn't change code generation. It's on by default for-march=armv8.5-assbsโ Turns on the Armv8-a Speculative Store Bypass Safe instruction ๐ก๏ธ. Assembler level only, no change to code generation. It's on by default for-march=armv8.5-apredresโ Turns on the Armv8-a Execution and Data Prediction Restriction instructions ๐. Assembler level only, no change to code generation. It's on by default for-march=armv8.5-asve2โ Turns on the Armv8-a Scalable Vector Extension 2 ๐. It also enables SVE instructionssve2-bitpermโ Turns on SVE2 bitperm instructions ๐ช. It also enables SVE2 instructionssve2-sm4โ Turns on SVE2 sm4 instructions ๐. It also enables SVE2 instructionssve2-aesโ Turns on SVE2 aes instructions ๐. It also enables SVE2 instructionssve2-sha3โ Turns on SVE2 sha3 instructions ๐. It also enables SVE2 instructionstmeโ Turns on the Transactional Memory Extension ๐งi8mmโ Turns on 8-bit Integer Matrix Multiply instructions ๐งฎ. It also enables Advanced SIMD and floating-point instructions. It's on by default for-march=armv8.6-a. Using it with architectures prior to Armv8.2-A is not supported ๐f32mmโ Turns on 32-bit Floating point Matrix Multiply instructions ๐. It also enables SVE instructions. Using it with architectures prior to Armv8.2-A is not supported ๐f64mmโ Turns on 64-bit Floating point Matrix Multiply instructions ๐. It also enables SVE instructions. Using it with architectures prior to Armv8.2-A is not supported ๐bf16โ Turns on brain half-precision floating-point instructions ๐ง โจ. It also enables Advanced SIMD and floating-point instructions. It's on by default for-march=armv8.6-a. Using it with architectures prior to Armv8.2-A is not supported ๐ls64โ Turns on the 64-byte atomic load and store instructions for accelerators ๐. It's on by default for-march=armv8.7-amopsโ Turns on the instructions that speed up memory operations like"memcpy","memmove", and"memset"๐งน. It's on by default for-march=armv8.8-aflagmโ Turns on the Flag Manipulation instructions Extension ๐ณ๏ธpauthโ Turns on the Pointer Authentication Extension ๐csscโ Turns on the Common Short Sequence Compression instructions ๐๏ธsmeโ Turns on the Scalable Matrix Extension ๐งsme-i16i64โ Turns on the FEAT_SME_I16I64 extension to SME ๐ขsme-f64f64โ Turns on the FEAT_SME_F64F64 extension to SME ๐ฃ
Quick heads up: the source has a stray+@itemglitch stuck onto thesme-f64f64entry, sosme2gets its own bullet below ๐
sme2โ Turns on the Scalable Matrix Extension 2 ๐. It also enables SME instructionslse128โ Turns on the LSE128 128-bit atomic instructions extension โ๏ธ. It also enables LSE instructionsd128โ Turns on support for 128-bit system register read/write instructions ๐ฟ. It also enables the LSE128 extensiongcsโ Turns on support for the Armv9.4-a Guarded Control Stack extension ๐ฐtheโ Turns on support for the Armv8.9-a/9.4-a translation hardening extension ๐ ๏ธrcpc3โ Turns on the RCpc3 (Release Consistency) extension ๐บ
Feature bundles are linked, so crypto implies aes, sha2, and simd, which implies fp. Going the other way, nofp implies nosimd, which implies nocrypto, noaes and nosha2 ๐
๐ง Adapteva Epiphany Options ๐ง
These -m options are defined for Adapteva Epiphany ๐ฆ
-mhalf-reg-fileโ Don't hand out any register in the range"r32"..."r63"๐ซถ. That lets your code run on hardware variants that don't have those registers-mprefer-short-insn-regsโ Gives priority to registers that allow short instruction generation โก. This can bump up the instruction count, so overall code size could go either way-mbranch-cost=numโ Sets the cost of branches to roughlynum"simple" instructions ๐ฟ. It's only a heuristic, so it isn't guaranteed to give consistent results across releases-mcmoveโ Turns on the generation of conditional moves ๐-mnops=numโ EmitsnumNOPs before every other generated instruction ๐ด-mno-soft-cmpsfโ For single-precision floating-point comparisons, this emits anfsubinstruction and tests the flags ๐๏ธ. It's faster than a software comparison, but it can give incorrect results in the presence of 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 range"sp+0...sp+7"can be used by leaf functions without stack allocation. Values other than8or16are untested and unlikely to work ๐
Heads up: this option changes the ABI! Compiling a program with a different stack offset than the libraries were built with generally does not work. It can help you check whether a different stack offset would give you better code, but if you want to actually build working programs with a different stack offset, it's recommended 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โ Unless an attribute says otherwise, this assumes all calls might be beyond the offset range of the"b"/"bl"instructions ๐. So the function address gets loaded into a register before the (otherwise direct) call. This is the default-mshort-callsโ Unless an attribute says otherwise, this assumes all direct calls are in the range of the"b"/"bl"instructions ๐ฒ, 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 doesn't apply to function addresses where-mlong-callssemantics are in effect-mfp-mode=modeโ Sets the prevailing mode of the floating-point unit ๐งญ. This decides which floating-point mode gets 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 might want to link into programs with different prevailing FPU modes. The convenience of one single object file outweighs the size and speed overhead of any extra mode switching, compared with a more specific choice of prevailing FPU modetruncateโ The mode used for floating-point calculations with truncating (i.e. round towards zero) rounding ๐ชต. That includes conversion from floating point to integerround-nearestโ The mode used for floating-point calculations with round-to-nearest-or-even rounding ๐ฏ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
Heads up: this is an ABI change! Many library function interfaces are unaffected, as long as 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 generally the case ๐
โจ AMD GCN Options โจ
okay so these ones are made specifically for the AMD GCN port ๐ ๐ฅ๏ธ
-m1reg-regโ okay bestie, this one lets you pick a register to hold the constant-1๐ which makes loading small negative constants and certain bitmasks faster โจ The allowed values forregare:r43andr63โ use that register as a fixed register ๐noneโ no register gets used for this purpose ๐ซถ- The default is
-m1reg-none๐ธ
-march=gpu,-mtune=gpuโ set the architecture type or tuning forgpu๐ Supported values forgpuare:fijiโ compile for GCN3 Fiji devices (gfx803) ๐ฆ
Support is deprecated ๐ญ Whether it's available depends on how GCC was configured, so check--with-archand--with-multilib-list.
gfx900โ compile for GCN5 Vega 10 devices (gfx900) โจgfx906โ compile for GCN5 Vega 20 devices (gfx906) ๐ฅgfx908โ compile for CDNA1 Instinct MI100 series devices (gfx908) ๐gfx90aโ compile for CDNA2 Instinct MI200 series devices (gfx90a) ๐gfx1030โ compile for RDNA2gfx1030devices (GFX10 series) ๐งgfx1036โ compile for RDNA2gfx1036devices (GFX10 series) ๐gfx1100โ compile for RDNA3gfx1100devices (GFX11 series) โญgfx1103โ compile for RDNA3gfx1103devices (GFX11 series) ๐ฆ
-msram-ecc=on,-msram-ecc=off,-msram-ecc=anyโ compile binaries for devices with SRAM-ECC enabled, disabled, or either mode ๐ก๏ธ This feature can be turned on per-process on some devices, and the compiled code must match the device mode ๐ The default isany, for devices that support it.-mstack-size=bytesโ specify how many bytes of stack space get requested for each GPU thread (wave-front) ๐งต
Heads up, there can be a lot of threads and not much memory, so be careful ๐ญ The stack size can also affect run-time performance. The default is 32KB when using OpenACC or OpenMP, and 1MB otherwise.
-mxnack=on,-mxnack=off,-mxnack=anyโ compile binaries for devices with the XNACK feature enabled, disabled, or either mode ๐ธ Some devices always need XNACK, and some let the user configure it. The compiled code must match the device mode. The default is-mxnack=anyon devices that support Unified Shared Memory, and-mxnack=nootherwise.
๐ ARC Options ๐
these options are all about controlling which architecture variant your ARC code gets compiled for ๐ the following are the vibes:
-mbarrel-shifterโ generate instructions supported by the barrel shifter โ๏ธ This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ force a function call to use thejli_sinstruction ๐ฆ This option is only valid for the ARCv2 architecture.-mcpu=cpuโ set the architecture type, register usage, and instruction scheduling parameters forcpu๐ There are also shortcut alias options for backward compatibility and convenience. Supported values forcpuare:arc600โ compile for ARC600. Aliases:-mA6,-mARC600๐งarc601โ compile for ARC601. Alias:-mARC601๐arc700โ compile for ARC700. Aliases:-mA7,-mARC700โญ This is the default when configured with--with-cpu=arc700.arcemโ compile for ARC EM ๐archsโ compile for ARC HS ๐ฅemโ compile for ARC EM CPU with no hardware extensions ๐ธem4โ compile for ARC EM4 CPU โจem4_dmipsโ compile for ARC EM4 DMIPS CPU ๐ฆem4_fpusโ compile for ARC EM4 DMIPS CPU with the single-precision floating-point extension ๐ซถem4_fpudaโ compile for ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions ๐hsโ compile for ARC HS CPU with no hardware extensions except the atomic instructions ๐hs34โ compile for ARC HS34 CPU ๐hs38โ compile for ARC HS38 CPU ๐hs38_linuxโ compile for ARC HS38 CPU with all hardware extensions on ๐ฅhs4xโ compile for ARC HS4x CPU ๐hs4xdโ compile for ARC HS4xD CPU ๐งhs4x_rel31โ compile for ARC HS4x CPU release 3.10a โญarc600_normโ compile for ARC 600 CPU with"norm"instructions enabled ๐arc600_mul32x16โ compile for ARC 600 CPU with"norm"and 32x16-bit multiply instructions enabled ๐arc600_mul64โ compile for ARC 600 CPU with"norm"and"mul64"-family instructions enabled ๐ฆarc601_normโ compile for ARC 601 CPU with"norm"instructions enabled ๐ธarc601_mul32x16โ compile for ARC 601 CPU with"norm"and 32x16-bit multiply instructions enabled โจarc601_mul64โ compile for ARC 601 CPU with"norm"and"mul64"-family instructions enabled ๐nps400โ compile for ARC 700 on the NPS400 chip ๐em_miniโ compile for ARC EM minimalist configuration featuring a reduced register set ๐ง
-mdpfp,-mdpfp-compactโ generate double-precision FPX instructions, tuned for the compact implementation ๐-mdpfp-fastโ generate double-precision FPX instructions, tuned for the fast implementation โก-mno-dpfp-lrsrโ disable"lr"and"sr"instructions from using FPX extension aux registers ๐ โโ๏ธ-meaโ generate extended arithmetic instructions ๐งฎ Currently only"divaw","adds","subs", and"sat16"are supported. This is only valid for-mcpu=ARC700.-mno-mpyโ do not generate"mpy"-family instructions for ARC700 ๐
This option is deprecated, so maybe don't build your whole life around it ๐ญ
-mmul32x16โ generate 32x16-bit multiply and multiply-accumulate instructions โ๏ธ-mmul64โ generate"mul64"and"mulu64"instructions ๐ข This is only valid for-mcpu=ARC600.-mnormโ generate"norm"instructions ๐ฏ This is the default if-mcpu=ARC700is in effect.-mspfp,-mspfp-compactโ generate single-precision FPX instructions, tuned for the compact implementation ๐ธ-mspfp-fastโ generate single-precision FPX instructions, tuned for the fast implementation ๐ฅ-msimdโ enable generation of ARC SIMD instructions via target-specific builtins ๐ This is only valid for-mcpu=ARC700.-msoft-floatโ this option gets ignored ๐ 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โ generate"swap"instructions ๐-matomicโ enables the use of the locked load/store conditional extension to implement atomic memory built-in functions ๐ Not available for ARC 6xx or ARC EM cores.-mdiv-remโ enable"div"and"rem"instructions for ARCv2 cores โ-mcode-densityโ enable code density instructions for ARC EM โจ This option is on by default for ARC HS.-mll64โ enable double load/store operations for ARC HS cores ๐ฆ-mtp-regno=regnoโ specify the thread pointer register number ๐งต-mmpy-option=multoโ compile ARCv2 code with a multiplier design option ๐งฎ You can specify the option using either a string or a numeric value formulto.wlh1is the default. The recognized values are:0ornoneโ no multiplier available ๐ โโ๏ธ1orwโ 16x16 multiplier, fully pipelined. The following instructions are enabled:"mpyw"and"mpyuw"๐ธ2orwlh1โ 32x32 multiplier, fully pipelined (1 stage). The following instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s"๐3orwlh2โ 32x32 multiplier, fully pipelined (2 stages). The following instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s"๐ฆ4orwlh3โ two 16x16 multipliers, blocking, sequential. The following instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s"๐ง5orwlh4โ one 16x16 multiplier, blocking, sequential. The following instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s"๐6orwlh5โ one 32x4 multiplier, blocking, sequential. The following instructions are additionally enabled:"mpy","mpyu","mpym","mpymu", and"mpy_s"โญ7orplus_dmpyโ ARC HS SIMD support ๐8orplus_macdโ ARC HS SIMD support ๐ฅ9orplus_qmacwโ ARC HS SIMD support ๐
This option is only available for ARCv2 cores ๐ซถ
-mfpu=fpuโ enables support for specific floating-point hardware extensions for ARCv2 cores ๐งฎ Supported values forfpuare:fpusโ enables support for single-precision floating-point hardware extensions โจfpudโ enables support for double-precision floating-point hardware extensions. The single-precision floating-point extension is also enabled. Not available for ARC EM ๐fpudaโ enables support for double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point extension is also enabled. This option is only available for ARC EM ๐ฆfpuda_divโ enables support for double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point, square-root, and divide extensions are also enabled. This option is only available for ARC EM ๐ธfpuda_fmaโ enables support for double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point and fused multiply and add hardware extensions are also enabled. This option is only available for ARC EM ๐งfpuda_allโ enables support for double-precision floating-point hardware extensions using double-precision assist instructions. All single-precision floating-point hardware extensions are also enabled. This option is only available for ARC EM ๐ฅfpus_divโ enables support for single-precision floating-point, square-root, and divide hardware extensions ๐
fpud_div๐ is the double-precision bundle: double-precision floating-point plus the square-root and divide hardware extensions. It also includesfpus_div. Not available for ARC EM ๐fpus_fmaโจ gives you single-precision floating-point and the fused multiply and add hardware extensions. Lowkey the cutest combo ๐ฆfpud_fma๐ฅ gives you double-precision floating-point and the fused multiply and add hardware extensions. This one includesfpus_fma. Not available for ARC EM.fpus_all๐ธ turns on all the single-precision floating-point hardware extensions. Every single one, no skipping.fpud_all๐ is the whole buffet: all the single- and double-precision floating-point hardware extensions. Not available for ARC EM ๐ญ-mirq-ctrl-saved=register-range, blink, lp_count๐ง tells the compiler which general-purpose registers the processor automatically saves and restores on interrupt entry and exit. The register-range is 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 replicated into the second register bank when a fast interrupt fires. Fast interrupts are the highest-priority P0 ones, and they only save thePCandSTATUS32registers so they can skip memory transactions during entry and exit. Use this when you're running fast interrupts on an ARC V2 family processor. Permitted values are4,8,16, and32.-mlpc-width=width๐ sets the width of thelp_countregister. Valid widths are8,16,20,24,28, and32bits. The default is fixed at 32 bits. If the width is less than 32, the compiler won't transform your loops into the zero-delay loop mechanism unless it knowslp_countcan actually hold the loop-counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for various needs. This option defines the__ARC_LPC_WIDTH__macro with the value of width.-mrf16๐ tells the compiler to generate code for a 16-entry register file. It defines the__ARC_RF16__preprocessor macro.-mbranch-index๐ enables use ofbiorbihinstructions to implement jump tables.
Next up, these ones get passed along to the assembler and set preprocessor macro symbols ๐ซถ
-mdsp-packa๐ gets passed down to the assembler to enable the DSP Pack A extensions. It also sets the__Xdsp_packapreprocessor symbol. Deprecated. ๐-mdvbfgets passed down to the assembler to enable the dual Viterbi butterfly extension. It also sets__Xdvbf. Deprecated.-mlockgets passed down to the assembler to enable the locked load/store conditional extension. It also sets__Xlock.-mmac-d16gets passed down to the assembler and sets__Xxmac_d16. Deprecated.-mmac-24gets passed down to the assembler and sets__Xxmac_24. Deprecated.-mrtscgets passed down to the assembler to enable the 64-bit time-stamp counter extension instruction. It also sets__Xrtsc. Deprecated.-mswapegets passed down to the assembler to enable the swap byte ordering extension instruction. It also sets__Xswape.-mtelephonygets passed down to the assembler to enable dual- and single-operand instructions for telephony. It also sets__Xtelephony. Deprecated.-mxygets passed down to the assembler to enable the XY memory extension. It also sets__Xxy.
These next ones control how the assembly code gets annotated ๐
-misizeannotates assembler instructions with estimated addresses.-mannotate-aligndoes nothing. It's only hanging around for backward compatibility ๐
These ones get passed through to the linker ๐
-marclinuxgets passed through to the linker to specify use of thearclinuxemulation. It's enabled by default in toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets when profiling is not requested.-marclinux_profgets passed through to the linker to specify use of thearclinux_profemulation. It's enabled by default in those same toolchains when profiling is requested.
Now the options that control the semantics of the generated code ๐ง
-mlong-callsgenerates calls as register indirect calls, which gives you access to the full 32-bit address range.-mmedium-callsmeans don't use less than a 25-bit addressing range for calls, which is the offset available for an unconditional branch-and-link instruction. Conditional execution of function calls gets suppressed so you can use that 25-bit range instead of the 21-bit range you'd get with conditional branch-and-link. This is the default for toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets.-G numputs definitions of externally-visible data in a small data section if that data is no bigger thannumbytes. The default value ofnumis 4 for any ARC configuration, or 8 when there are double load/store operations.-mno-sdatameans no sdata references. This is the default for toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets.-mvolatile-cacheuses ordinarily cached memory accesses for volatile references. This is the default ๐-mno-volatile-cacheenables cache bypass for volatile references.
These fine-tune code generation ๐
-malign-calldoes nothing. Preserved for backward compatibility.-mauto-modify-regenables the use of pre/post modify with register displacement.-mbbit-peepholedoes nothing. Preserved for backward compatibility.-mno-brccdisables 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-pcreluses PC-relative switch case tables to enable case table shortening. This is the default for-Os.-mcompact-casesienables the compactcasesipattern. This is the default for-Os, and it's only available for ARCv1 cores. Deprecated.-mno-cond-execdisables the ARCompact-specific pass that generates conditional execution instructions.
Okay, the tea โ is that delay slot scheduling and the interactions between operand numbers, literal sizes, instruction lengths, and conditional execution support mean the target-independent pass for conditional execution is often lacking. So the ARC port keeps a special pass around that tries to find more conditional execution opportunities after register allocation, branch shortening, and delay slot scheduling have been 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 have a problem with call instructions exceeding their allowable offset range because they've been conditionalized, you should consider using -mmedium-calls instead ๐ซ
-mearly-cbranchsienables pre-reload use of thecbranchsipattern.-mexpand-adddiexpandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. Deprecated.-mindexed-loadsenables the use of indexed loads. This can be problematic because some optimizers then assume that indexed stores exist, which is not the case โ-mlraenables Local Register Allocation. It's still experimental for ARC, so by default the compiler uses standard reload (i.e.-mno-lra) ๐งช-mlra-priority-nonedoesn't indicate any priority for target registers.-mlra-priority-compactindicates target register priority forr0..r3/r12..r15.-mlra-priority-noncompactreduces target register priority forr0..r3/r12..r15.-mmillicode๐ when you're optimizing for size (using-Os), prologues and epilogues that have to save or restore a large number of registers are often shortened by calling a special function in libgcc. This is called a millicode call. Since these calls can pose performance issues, and/or cause linking issues when linking in a nonstandard way, this option lets you turn millicode call generation on or off.-mcode-density-frameenables the compiler to emitenterandleaveinstructions. These are only valid for CPUs with the code-density feature.-mmixed-codedoes nothing. Preserved for backward compatibility.-mq-classis deprecated. It enables q instruction alternatives. This is the default for-Os.-mRcqdoes nothing. Preserved for backward compatibility.-mRcwdoes nothing. Preserved for backward compatibility.-msize-level=levelfine-tunes size optimization with regards to instruction lengths and alignment. The recognized values forlevelare:0means no size optimization. This level is deprecated and treated like1.1means short instructions are used opportunistically.2means that, in addition, alignment of loops and of code after barriers is dropped.3means that, in addition, optional data alignment is dropped, and the optionOsis enabled.
This defaults to 3 when -Os is in effect. Otherwise, the behavior when this is not set is equivalent to level 1 โจ
-mtune=cpusets instruction scheduling parameters for cpu, overriding any that are implied by-mcpu=.
Supported values for cpu are:
ARC600tunes for the ARC600 CPU.ARC601tunes for the ARC601 CPU.ARC700tunes for the ARC700 CPU with the standard multiplier block.ARC700-xmactunes for the ARC700 CPU with the XMAC block.ARC725Dtunes for the ARC725D CPU ๐
ARC750Dโ ok this one's for the ARC750D CPU ๐ tuning just for it, no cap โจcore3โ tunes for the ARCv2 core3 type CPU ๐ฆ and this one unlocks thedbnzinstruction, so it's giving main character energy ๐release31aโ tunes for ARC4x release 3.10a ๐ธ-mmultcost=numโ sets the cost GCC assumes for a multiply instruction ๐งฎ where4means it's the same cost as a normal instruction ๐-munalign-prob-threshold=probabilityโ literally does nothing ๐ it's just kept around so older code doesn't cry ๐ญ
The following options are still around for backward compatibility, but they're deprecated now, so bestie don't build new stuff with them ๐
These options will be removed in a future release, so start switching now before they vanish! ๐ซถ
-margonautโ obsolete FPX, retired and gone ๐ง-mbig-endian,-EBโ compiles code for big-endian targets ๐ but using these is deprecated now. Big-endian is supported by configuring GCC to build thearceb-elf32andarceb-linux-uclibctargets instead, and big endian is the default for those ๐-mlittle-endian,-ELโ compiles code for little-endian targets ๐ also deprecated. Little-endian is supported by configuring GCC to build thearc-elf32andarc-linux-uclibctargets, where little endian is the default โจ-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-xmacgot 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, these are your lowkey best friends ๐
-mabi=nameโ generates code for the ABI you pick ๐. The permissible values areapcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt๐-mapcs-frameโ makes a stack frame that follows the ARM Procedure Call Standard for all functions ๐ซถ, even when it's not strictly needed for the code to run right. If you pair this with-fomit-frame-pointer, stack frames won't get generated for leaf functions ๐ธ. The default is-mno-apcs-frame, and this option is deprecated ๐-mapcsโ just a synonym for-mapcs-frame๐ง and it's deprecated too ๐ญ-mthumb-interworkโ generates code that can call between the ARM and Thumb instruction sets ๐. Without it, on pre-v5 architectures, the two sets can't be reliably used inside one program ๐. The default is-mno-thumb-interwork, because-mthumb-interworkmakes slightly larger code ๐. In AAPCS configurations this option is meaningless ๐-mno-sched-prologโ stops GCC from reordering instructions in the function prologue, or merging them with the instructions in the function's body ๐ฅ. So every function starts with a recognizable set of instructions (or one from a small set of prologues), and you can use that to find where functions start inside an executable ๐. The default is-msched-prologโจ-mfloat-abi=nameโ picks which floating-point ABI to use ๐. The values aresoft,softfpandhard๐ฆ.softmakes GCC emit library calls for floating-point operations ๐งฎsoftfplets you use hardware floating-point instructions but still uses the soft-float calling conventions ๐ธhardgives you floating-point instructions and FPU-specific calling conventions ๐ฅ
The default depends on the specific target configuration ๐ . Heads up: the hard-float and soft-float ABIs are not link-compatible, so you have to compile your entire program with the same ABI and link with a compatible set of libraries ๐
-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers ๐. This stops the compiler from using floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler ๐ซถ-mlittle-endianโ generates code for a processor running in little-endian mode ๐. This is the default for all standard configurations ๐-mbig-endianโ generates code for a processor running in big-endian mode ๐. The default is to compile for a little-endian processor ๐-mbe8,-mbe32โ when linking a big-endian image, these pick between the BE8 and BE32 formats ๐ง. They have no effect on little-endian images and get ignored there ๐. The default depends on the target architecture: ARMv6 and later default to BE8, and older architectures default to BE32 โญ. BE32 has been deprecated by ARM ๐-march=name[+extension...]โ specifies the name of the target ARM architecture ๐. GCC uses this name to figure out what kinds of instructions it can emit when generating assembly code โจ. You can use it 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, armv9-a, iwmmxt and iwmmxt2 ๐
Also, armv4 is recognized but its support is deprecated ๐. It's one of the architectures that doesn't support the Thumb execution state ๐.
Lots of these architectures support extensions ๐. You add one by appending +extension to the architecture name ๐. Extension options get processed in order and their capabilities stack up ๐งฎ. An extension also turns on any base extensions it needs ๐ซถ. For example, +crypto will always enable +simd ๐ฅ. The exception to all that stacking is the extensions prefixed with +no...: those turn off the option and any other extensions that depend on it ๐ญ.
For example, -march=armv7-a+simd+nofp+vfpv4 is the same as writing -march=armv7-a+vfpv4, because the +simd option gets totally disabled by the +nofp that comes after it ๐.
Most extension names are generic, but what they do depends on the architecture they're applied 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 ๐.
The table below lists the supported extensions for each architecture ๐ง. Architectures that aren't 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 ๐ฅ
This is 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's 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 (it doesn't disable floating point) ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐ญ
โจ armv7ve ๐
This is 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โ okay so this one gets you the VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations ๐โจ+vfpv4-d16โ the VFPv4 floating-point instructions, but with 16 double-precision registers ๐+vfpv4โ the VFPv4 floating-point instructions with 32 double-precision registers, so it's the full-fat version ๐ฆ+neonโ the Advanced SIMD (Neon) v1 along with the VFPv3 floating-point instructions. You can also write+neon-vfpv3and it's the same thing, an alias ๐+neon-fp16โ the Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions, plus the half-precision floating-point conversion operations ๐ฅ+nosimdโ disables the Advanced SIMD instructions. Floating point is still on though, so don't panic ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐
๐ธ armv8-a
+crcโ the Cyclic Redundancy Check (CRC) instructions ๐ง+simdโ the ARMv8-A Advanced SIMD and floating-point instructions ๐+cryptoโ the cryptographic instructions ๐+nocryptoโ disables the cryptographic instructions ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions. Big yikes energy ๐ญ+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 ๐+fp16fmlโ the half-precision floating-pointfmlaextension. This also enables the half-precision floating-point extension and the Advanced SIMD and floating-point instructions, so it's a whole vibe ๐+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, plus the Dot Product extension and the half-precision floating-pointfmlaextension. Triple threat ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ญ+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ซถ+i8mmโ the 8-bit Integer Matrix Multiply instructions. This also 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, plus the Dot Product extension and the half-precision floating-pointfmlaextension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ญ+i8mmโ the 8-bit Integer Matrix Multiply instructions. This also 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, plus the Dot Product extension and the half-precision floating-pointfmlaextension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ญ+i8mmโ the 8-bit Integer Matrix Multiply instructions. This also 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 and the half-precision floating-point conversion operations ๐+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers and 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 bestie, -march=native is giving auto-detect ๐. It tells the compiler to figure out the architecture of the build computer all by itself. ngl, this only works on GNU/Linux right now, and not every architecture gets recognized ๐. If the auto-detect doesn't work out, the option just has no effect ๐ซถ.
๐ -mtune=name
This is how you tell GCC which target ARM processor to tune your code's performance for โจ For some ARM implementations you can get better performance with this option ๐ฆ. The permissible names are arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi, arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, ares, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-r52plus, cortex-m0, cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m52, cortex-m55, cortex-m85, cortex-x1, cortex-x1c, cortex-m1.small-multiply, cortex-m0.small-multiply, cortex-m0plus.small-multiply, exynos-m1, marvell-pj4, neoverse-n1, neoverse-n2, neoverse-v1, xscale, iwmmxt, iwmmxt2, ep9312, fa526, fa626, fa606te, fa626te, fmp626, fa726te, star-mc1, xgene1.
Okay, and this option can also say "tune this for a big.LITTLE system" ๐ง The permissible names for that are cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a72.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55.
-mtune=generic-arch is the move if you want code that runs well on the current most popular processors ๐
It's a blend across the processors within arch, balancing optimizations that help some CPUs in the range while avoiding performance pitfalls on others. Just know the effects may change in future GCC versions as CPU models come and go ๐ธ
-mtune takes the same extension options as -mcpu, but those extensions don't change the tuning of the generated code ๐
-mtune=native auto-detects the CPU of the build computer ๐ Same deal as before: GNU/Linux only, not all architectures are recognized, and if the auto-detect fails, the option has no effect ๐
๐ธ -mcpu=name[+extension...]
This one specifies the target ARM processor. GCC uses that name to work out the target ARM architecture (as if you'd passed -march) and the ARM processor type to tune for (as if you'd passed -mtune). If you use this alongside -march or -mtune, those two win for their part of the job ๐
Lots of the supported CPUs have optional architectural extensions, and those are normally enabled by default ๐ง If implementations that lack the extension exist, you can use the extension syntax to switch off the ones that got left out. For floating-point and Advanced SIMD (Neon) instructions, keep -mfloat-abi and -mfpu in mind too: floating-point and Advanced SIMD instructions are only used if -mfloat-abi isn't set to soft, and any -mfpu setting other than auto overrides the available floating-point and SIMD extension instructions ๐ฅ
For example, cortex-a9 comes in three major configs: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD. The default is to enable all of the instructions, but +nosimd and +nofp can disable just the SIMD, or both the SIMD and floating-point instructions, respectively ๐
Permissible names for this option are the same as for -mtune.
The following extension options are common to the listed CPUs:
+nodspโ Disables the DSP instructions oncortex-m33,cortex-m35p,cortex-m52,cortex-m55andcortex-m85. It also disables the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85๐+nopacbtiโ Disables the Pointer Authentication and Branch Target Identification Extension oncortex-m52andcortex-m85๐ฆ+nomveโ Disables the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions oncortex-m52,cortex-m55andcortex-m85๐+nomve.fpโ Disables 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, picked by the numbers in the options from 0 to 7, oncortex-m52andcortex-m55๐ง+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 instead ๐+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, neon-vfpv4. The meanings are the same as for the extensions to -march=armv7-a.
-mcpu=generic-arch is also allowed, and it's equivalent to -march=arch -mtune=generic-arch. Check out -mtune for more info โจ
-mcpu=native auto-detects the CPU of the build computer ๐ Again, GNU/Linux only, not every architecture is recognized, and if the auto-detect is unsuccessful the option has no effect ๐
๐ฅ -mfpu=name
This specifies what floating-point hardware (or hardware emulation) is available on the target. The permissible names are auto, vfpv2, vfpv3, vfpv3-fp16, vfpv3-d16, vfpv3-d16-fp16, vfpv3xd, vfpv3xd-fp16, neon-vfpv3, neon-fp16, vfpv4, vfpv4-d16, fpv4-sp-d16, neon-vfpv4, fpv5-d16, fpv5-sp-d16, fp-armv8, neon-fp-armv8 and crypto-neon-fp-armv8. Heads up: neon is an alias for neon-vfpv3, and vfp is an alias for vfpv2 ๐
auto is the default and it's a special one ๐ง It makes the compiler pick the floating-point and Advanced SIMD instructions based on the settings of -mcpu and -march.
โ ๏ธ If the selected floating-point hardware includes the NEON extension (e.g.-mfpu=neon), GCC's auto-vectorization pass won't generate floating-point operations unless-funsafe-math-optimizationsis also specified. That's because NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic (denormal values get 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
This specifies the format of the "__fp16" half-precision floating-point type โจ The permissible names are none, ieee and alternative. The default is none, which means the "__fp16" type is not defined at all ๐
๐ง -mstructure-size-boundary=n
The sizes of all structures and unions get rounded up to a multiple of the number of bits set by this option ๐ The permissible values are 8, 32 and 64. The default varies between toolchains. For the COFF targeted toolchain, the default is 8. A value of 64 is only allowed if the underlying ABI supports it.
Going bigger can produce faster, more efficient code, but it can also increase the size of the program ๐ Different values are potentially incompatible, too. Code compiled with one value can't necessarily work with code or libraries compiled with another value, if they swap information using structures or unions ๐ญ
๐ This option is deprecated, so maybe don't build new stuff around it.
๐ -mabort-on-noreturn
This generates a call to the function "abort" at the end of a "noreturn" function ๐ฅ It gets executed if the function tries to return.
๐ -mlong-calls and -mno-long-calls
These tell the compiler to make function calls by first loading the address of the function into a register, and then performing a subroutine call on that register ๐ซถ You need this switch if the target function lies outside of the 64-megabyte addressing range of the offset-based version of the subroutine call instruction.
Okay so even if this switch is on, bestie, not every function call gets turned into a long call ๐
The heuristic (aka the vibe check the compiler runs) says that static functions, functions with the short_call attribute, functions inside the scope of a #pragma no_long_calls directive, and functions whose definitions have already been compiled within the current compilation unit are not turned into long calls ๐
โโ๏ธ. The exceptions are the main character moments: weak function definitions, functions with the long_call attribute or the section attribute, and functions inside the scope of a #pragma long_calls directive are always turned into long calls ๐.
This feature is not enabled by default โจ Specifying -mno-long-calls restores the default behavior, and so does putting the function calls inside the scope of a #pragma long_calls_off directive. Also, these switches have zero effect on how the compiler handles function calls made through function pointers, so don't expect them to reach that part ๐
-msingle-pic-baseโ Treats the register used for PIC addressing as read-only, instead of loading it in the prologue for each function ๐ The runtime system has to set this register to a proper value before execution starts, so that's on it ๐ซถ-mpic-register=regโ Picks 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, otherwise it'sR10๐-mpic-data-is-text-relativeโ Assumes the displacement between the text and data segments is fixed at static link time ๐ฆ This lets PC-relative addressing operations access data known to be in the data segment. For non-VxWorks RTP targets, this option is on by default. When it's disabled on those targets,-msingle-pic-basegets enabled by default instead โจ-mpoke-function-nameโ 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, code can check the value of pc stored at fp + 0. If the trace function then looks at location pc - 12 and the top 8 bits are set, we know there's a function name embedded right before that location, and its length is ((pc[-3]) & 0xff000000) ๐
-mthumb,-marmโ Pick between generating code that runs in ARM state or Thumb state ๐ธ Most configurations default to ARM state, but you can change that default by configuring GCC with the--with-mode=stateconfigure option. You can also override ARM or Thumb mode for each function using thetarget("thumb")andtarget("arm")function attributes or pragmas ๐-mflip-thumbโ Switches ARM and Thumb modes on alternating functions ๐ This one exists for regression testing of mixed Thumb/ARM code generation, so it's not meant for ordinary code compiling ๐ โโ๏ธ-mtpcs-frameโ Generates a stack frame that follows the Thumb Procedure Call Standard for all non-leaf functions. (A leaf function is one that does not call any other functions.) The default is-mno-tpcs-frame๐-mtpcs-leaf-frameโ Generates a stack frame that follows the Thumb Procedure Call Standard for all leaf functions. (A leaf function is one that does not call any other functions.) The default is-mno-apcs-leaf-frame๐-mcallee-super-interworkingโ Gives all externally visible functions in the file being compiled an ARM instruction set header that switches to Thumb mode before the rest of the function runs โจ That means 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 ๐ซง There's a small overhead when running a function pointer if you turn this on. Same deal as above: this option is not valid in AAPCS configurations because interworking is enabled by default ๐-mtp=nameโ Picks the access model for the thread local storage pointer ๐งต Thesoftmodel generates calls to__aeabi_read_tp. The other accepted models aretpidrurw,tpidruroandtpidrprw, which grab the thread pointer straight from the matching system register (supported from the arm6k architecture and later). Those system registers are accessed through the CP15 co-processor interface, andcp15is also accepted as a convenient alias oftpidruro๐ Theautoargument uses the best available method for the processor you've selected, andautois 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 gives better performance 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 on by default on targets (uClinux, SymbianOS) where the runtime loader imposes that restriction, and whenever-fpicor-fPICis specified. This option conflicts with-mslow-flash-dataโ-mfix-cortex-m3-ldrdโ Some Cortex-M3 cores can corrupt data whenldrdinstructions with overlapping destination and base registers are 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โ Enables (or disables) the mitigation for an erratum on Cortex-A57 and Cortex-A72 that affects the AES cryptographic instructions ๐ This option is enabled by default when either-mcpu=cortex-a57or-mcpu=cortex-a72is specified ๐-munaligned-access,-mno-unaligned-accessโ Enables (or disables) reading and writing of 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 for ARMv8-M Baseline architectures, and enabled for all other architectures. If unaligned access isn't enabled, words in packed data structures get accessed one byte at a time ๐ข
The ARM attribute Tag_CPU_unaligned_access gets set in the generated object file to either true or false, depending on how this option is set ๐ท๏ธ If unaligned access is enabled, the preprocessor symbol __ARM_FEATURE_UNALIGNED is also defined โจ
-mneon-for-64bitsโ This option is deprecated and has no effect ๐ฅ-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 uses unified asm syntax ๐งฉ The default is currently off, which implies divided syntax. This option has no impact on Thumb2, but that might change in future GCC releases. Divided syntax should be considered deprecated ๐-mrestrict-itโ Restricts generation of IT blocks so they follow 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 one is only for regression testing of the compiler and isn't intended for ordinary code compiling. It's disabled by default ๐ โโ๏ธ-mverbose-cost-dumpโ Enables verbose cost model dumping in the debug dump files ๐ต๏ธโโ๏ธ It's provided for debugging the compiler, so that's its whole job ๐ซถ-mpure-codeโ Doesn't allow constant data to be placed in code sections ๐ง When compiling for ELF object format, it also gives all text sections the ELF processor-specific section attributeSHF_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 athttps://developer.arm.com/documentation/ecm0359818/latest/๐-mfix-cmse-cve-2021-35465โ Mitigates a potential security issue with theVLLDMinstruction on some M-profile devices when using CMSE (CVE-2021-365465) ๐ก๏ธ This option is enabled by default when-mcpu=is used withcortex-m33,cortex-m35p,cortex-m52,cortex-m55,cortex-m85orstar-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=tlsand is not for use in user-land code ๐-mfdpic,-mno-fdpicโ okay bestie, this one picks the FDPIC ABI ๐ which uses 64-bit function descriptors to represent pointers to functions โจ. When the compiler is configured for"arm-*-uclinuxfdpiceabi"targets, it's on by default and implies-fPIEif none of the PIC/PIE-related options is provided ๐ฅ. On other targets it only turns on the FDPIC-specific code generation features, so you have to explicitly pass the PIC/PIE-related options yourself ๐ซถ.
Heads up ๐ static linking is not supported, because it would still involve the dynamic linker when the program self-relocates. If that's acceptable to you, use -static and -Wl,-dynamic-linker options instead.
The opposite -mno-fdpic option is useful (and required) for building the Linux kernel with the same "arm-*-uclinuxfdpiceabi" toolchain you used for your userland programs ๐ง.
-mbranch-protection=none|standard|pac-ret[+leaf][+bti]|bti[+pac-ret[+leaf]]โ branch protection features ๐ฆ (armv8.1-m.main only). Here's the vibe check on each value:noneโ generate code without branch protection or return address signing ๐ โโ๏ธ.standard[+leaf]โ generate code with all branch protection features enabled at their standard level โจ.pac-ret[+leaf]โ generate code with return address signing set to its standard level, which means signing all functions that save the return address to memory ๐.leafโ when return address signing is enabled, also sign leaf functions, even if they don't write the return address to memory ๐.+btiโ add landing-pad instructions at the permitted targets of indirect branch instructions ๐ธ.
If the +pacbti architecture extension is not enabled, then all branch protection and return address signing operations are constrained to use only the instructions defined in the architectural-NOP space. The generated code stays backwards-compatible with earlier versions of the architecture, but the extra security can be turned on at run time on processors that support the PACBTI extension ๐.
Branch target enforcement using BTI can only be enabled at runtime if all code in the application has been compiled with at least -mbranch-protection=bti ๐.
Any setting other than none is supported only on armv8-m.main or later ๐.
The default is to generate code without branch protection or return address signing ๐.
โจ AVR Options โจ
These options are defined for AVR implementations ๐.
-mmcu=mcuโ pick your AVR instruction set architecture (ISA) or device type ๐. The default for this option is"avr2".
The following AVR devices and ISAs are supported. Note ๐: a complete device support setup consists of startup code crtmcu.o, a device header avr/io*.h, a device library libmcu.a, and a device-specs file specs-mcu (https://gcc.gnu.org/wiki/avr-gcc#spec-files). Only that last one, the device-specs file, is provided by the compiler, according to the supported mcus listed below. The rest comes from AVR-LibC (https://www.nongnu.org/avr-libc/) or from atpack files (https://gcc.gnu.org/wiki/avr-gcc#atpack) supplied by the hardware manufacturer ๐ซถ.
avr2โ "Classic" devices with up to 8 KiB of program memory ๐. mcu ="attiny22", "attiny26", "at90s2313", "at90s2323", "at90s2333", "at90s2343", "at90s4414", "at90s4433", "at90s4434", "at90c8534", "at90s8515", "at90s8535".avr25โ "Classic" devices with up to 8 KiB of program memory and with the "MOVW" instruction ๐ฆ. mcu ="attiny13", "attiny13a", "attiny24", "attiny24a", "attiny25", "attiny261", "attiny261a", "attiny2313", "attiny2313a", "attiny43u", "attiny44", "attiny44a", "attiny45", "attiny48", "attiny441", "attiny461", "attiny461a", "attiny4313", "attiny84", "attiny84a", "attiny85", "attiny87", "attiny88", "attiny828", "attiny841", "attiny861", "attiny861a", "ata5272", "ata6616c", "at86rf401".avr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory ๐ท. mcu ="at76c711", "at43usb355".avr31โ "Classic" devices with 128 KiB of program memory ๐ฅ. mcu ="atmega103", "at43usb320".avr35โ "Classic" devices with 16 KiB up to 64 KiB of program memory and with the "MOVW" instruction ๐. mcu ="attiny167", "attiny1634", "atmega8u2", "atmega16u2", "atmega32u2", "ata5505", "ata6617c", "ata664251", "at90usb82", "at90usb162".avr4โ "Enhanced" devices with up to 8 KiB of program memory โญ. mcu ="atmega48", "atmega48a", "atmega48p", "atmega48pa", "atmega48pb", "atmega8", "atmega8a", "atmega8hva", "atmega88", "atmega88a", "atmega88p", "atmega88pa", "atmega88pb", "atmega8515", "atmega8535", "ata5795", "ata6285", "ata6286", "ata6289", "ata6612c", "at90pwm1", "at90pwm2", "at90pwm2b", "at90pwm3", "at90pwm3b", "at90pwm81".avr5โ "Enhanced" devices with 16 KiB up to 64 KiB of program memory ๐. mcu ="atmega16", "atmega16a", "atmega16hva", "atmega16hva2", "atmega16hvb", "atmega16hvbrevb", "atmega16m1", "atmega16u4", "atmega161", "atmega162", "atmega163", "atmega164a", "atmega164p", "atmega164pa", "atmega165", "atmega165a", "atmega165p", "atmega165pa", "atmega168", "atmega168a", "atmega168p", "atmega168pa", "atmega168pb", "atmega169", "atmega169a", "atmega169p", "atmega169pa", "atmega32", "atmega32a", "atmega32c1", "atmega32hvb", "atmega32hvbrevb", "atmega32m1", "atmega32u4", "atmega32u6", "atmega323", "atmega324a", "atmega324p", "atmega324pa", "atmega324pb", "atmega325", "atmega325a", "atmega325p", "atmega325pa", "atmega328", "atmega328p", "atmega328pb", "atmega329", "atmega329a", "atmega329p", "atmega329pa", "atmega3250", "atmega3250a", "atmega3250p", "atmega3250pa", "atmega3290", "atmega3290a", "atmega3290p", "atmega3290pa", "atmega406", "atmega64", "atmega64a", "atmega64c1", "atmega64hve", "atmega64hve2", "atmega64m1", "atmega64rfr2", "atmega640", "atmega644", "atmega644a", "atmega644p", "atmega644pa", "atmega644rfr2", "atmega645", "atmega645a", "atmega645p", "atmega649", "atmega649a", "atmega649p", "atmega6450", "atmega6450a", "atmega6450p", "atmega6490", "atmega6490a", "atmega6490p", "ata5790", "ata5790n", "ata5791", "ata6613c", "ata6614q", "ata5782", "ata5831", "ata8210", "ata8510", "ata5787", "ata5835", "ata5700m322", "ata5702m322", "at90pwm161", "at90pwm216", "at90pwm316", "at90can32", "at90can64", "at90scr100", "at90usb646", "at90usb647", "at94k", "m3000".avr51โ "Enhanced" devices with 128 KiB of program memory ๐ . mcu ="atmega128", "atmega128a", "atmega128rfa1", "atmega128rfr2", "atmega1280", "atmega1281", "atmega1284", "atmega1284p", "atmega1284rfr2", "at90can128", "at90usb1286", "at90usb1287".avr6โ "Enhanced" devices with 3-byte PC, i.e. with 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", "avr64da32", "avr64da48", "avr64da64", "avr64db28", "avr64db32", "avr64db48", "avr64db64", "avr64dd14", "avr64dd20", "avr64dd28", "avr64dd32", "avr64du28", "avr64du32", "avr64ea28", "avr64ea32", "avr64ea48".avrxmega3โ "XMEGA" devices with up to 64 KiB of combined program memory and RAM, and with program memory 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", "avr16ea28", "avr16ea32", "avr16ea48", "avr16eb14", "avr16eb20", "avr16eb28", "avr16eb32", "avr32da28", "avr32da32", "avr32da48", "avr32db28", "avr32db32", "avr32db48", "avr32dd14", "avr32dd20", "avr32dd28", "avr32dd32", "avr32ea28", "avr32ea32", "avr32ea48".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", "avr128da32", "avr128da48", "avr128da64", "avr128db28", "avr128db32", "avr128db48", "avr128db64".avrxmega5โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory and 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".avrtinyโ "Reduced Tiny" Tiny core devices with only 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 implemented by the minimal AVR core and is supported for assembler only ๐. mcu ="attiny11", "attiny12", "attiny15", "attiny28", "at90s1200".
-mabsdataโ okay so this one tells the compiler to assume all data in static storage can be reached withLDS/STSinstructions ๐. It only has an effect on reduced Tiny devices, like ATtiny40 ๐ง. See also the "absdata" AVR Variable Attributes, which is a variable attribute โจ.-maccumulate-argsโ this one collects outgoing function arguments and grabs the stack space for them once, in the function prologue, then releases it in the epilogue ๐. Without it, outgoing arguments get pushed before each call and popped right after, which is the default vibe.
Popping arguments after a function call can be expensive on AVR, so accumulating the stack space can lead to smaller executables. The arguments don't need to be removed from the stack after each call. It can shrink code for functions that make several calls to functions taking 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 is0.-mcall-prologuesโ function prologues and epilogues get expanded as calls to the appropriate subroutines, so the code size comes out smaller ๐ธ.-mfuse-add,-mno-fuse-add,-mfuse-add=levelโ optimizes indirect memory accesses on reduced Tiny devices ๐ฅ. The default useslevel=1for-Ogand-O1, andlevel=2for higher optimizations. Valid values forlevelare0,1and2.-mdouble=bits,-mlong-double=bitsโ sets the size in bits of thedoubleorlong doubletype, respectively ๐ฆ. Possible values forbitsare32and64. Whether a specific value is allowed depends on the--with-double=and--with-long-double=configure options (https://gcc.gnu.org/install/configure.html#avr), and the same goes for the default values of the options ๐.-mgas-isr-prologuesโ interrupt service routines (ISRs) are allowed to use the__gcc_isrpseudo instruction, which 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. The feature is turned on by default if optimization is on (but not with-Og, see@pxref{Optimize Options}), and only if GNU Binutils supports PR21683 (https://sourceware.org/PR21683) โญ.-mint8โ tells the compiler to assumeintis an 8-bit integer ๐. This changes the sizes of all types: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes.
Heads up, bestie: this option does not conform to the C standards. It does result in smaller code size, though ๐.
-mmain-is-OS_taskโ do not save registers inmain๐. The effect is the same as attaching the AVR Function Attributes"OS_task"attribute tomain. It is turned on by default if optimization is on.-mno-interruptsโ generated code is not compatible with hardware interrupts ๐ . The upside is that code size comes out smaller.
Careful: generated code with this option will not work alongside hardware interrupts, so only use it when you're sure your code doesn't need them ๐ญ.
-mrelaxโ tries to swap aCALLorJMPfor the shorterRCALLorRJMPinstruction, where that's allowed ๐ฆ. Setting-mrelaxjust adds--mlink-relaxto the assembler's command line and--relaxto the linker's command line.
Jump relaxing is done by the linker, because jump offsets aren't known until the code is located. So the assembler code the compiler generates stays the same, but the instructions in the executable may differ from the ones in the assembler code ๐ง .
Relaxing must be turned on if linker stubs are needed. See the section on "EIND" and linker stubs below ๐.
-mrodata-in-ram,-mno-rodata-in-ramโ puts the.rodatasections for read-only data in RAM or in program memory, respectively ๐ท. For most devices there's no real choice here, so this option acts more 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 available. In that case, -mrodata-in-ram can be used to go back to the old layout with .rodata in RAM ๐.
-mstrict-Xโ uses the address registerXin the 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 is done like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-mtiny-stackโ only changes the lower 8 bits of the stack pointer ๐.-mfract-convert-truncateโ lets fractional fixed-point types use truncation instead of rounding towards zero ๐.-nodevicelibโ don't link against AVR-LibC's device specific librarylib<mcu>.a๐.-nodevicespecsโ don't add-specs=device-specs/specs-mcuto the compiler driver's command line. You're taking full responsibility for giving the subprocesses (compiler proper, assembler and linker) the right command line options ๐ซถ. That means you have to supply your own private device specs file with-specs=path-to-specs-file. There's no more need for-mmcu=mcu.
This option can also replace the older way of making custom device-specs files. That method needed -B some-path to point to a directory containing a folder named "device-specs", which in turn contained a specs file named "specs-mcu", where mcu was specified by -mmcu=mcu ๐๏ธ.
-Waddr-space-convertโ warns about conversions between address spaces when the resulting address space is not contained in the incoming address space ๐.-Wmisspelled-isrโ warns if the ISR is misspelled, i.e. without the__vectorprefix. This is enabled by default ๐ .
โจ "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.
To make indirect jumps work on devices with more than 128 Ki bytes of flash, there's a special function register called EIND ๐. It acts as the most significant part of the target address whenever EICALL or EIJMP instructions are used.
Indirect jumps and calls on these devices are handled as follows by the compiler, and they come with some limitations ๐ซ :
- The compiler never sets
EIND. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or might readEINDdirectly in order to emulate an indirect call/jump by means of aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved/restored in function or interrupt service routine prologue/epilogue. - For indirect calls to functions and computed goto, the linker generates stubs ๐งธ. Stubs are jump pads, sometimes also called trampolines. So the indirect call/jump lands on such a stub, and the stub contains a direct jump to the desired address.
- Linker relaxation must be turned on so that the linker generates the stubs correctly in all situations. See the compiler option
-mrelaxand the linker option--relax. Watch out: there are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message ๐ฑ. - The default linker script is arranged for code with
EIND = 0. If code is supposed to work for a setup withEIND != 0, a custom linker script has to be used to place the sections whose name starts with.trampolinesinto the segment whereEINDpoints to ๐บ๏ธ. - The startup code from libgcc never sets
EIND. Notice that startup code is a blend of code from libgcc and AVR-LibC. For the impact of AVR-LibC onEIND, see the AVR-LibC user manual (https://www.nongnu.org/avr-libc/user-manual/) ๐. - It is legitimate for user-specific startup code to set up
EINDearly, for example by means of initialization code located in section.init3. That code runs prior to the general startup code that initializes RAM and calls constructors, but after the bit of AVR-LibC startup code that setsEINDto the segment where the vector table is located ๐ง.
#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 are generated automatically by the linker if the following two conditions are met ๐ช:
- The address of a label is taken by means of the
gsmodifier (short for generate stubs), like so:
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The final location of that label is in a code segment outside the segment where the stubs are located.
- The compiler emits such
gsmodifiers for code labels in the following situations:- Taking the address of a function or code label.
- Computed goto.
- If the prologue-save function is used, see the
-mcall-prologuescommand-line option. - Switch/case dispatch tables. If you do not want such dispatch tables, you can specify the
-fno-jump-tablescommand-line option. - C and C++ constructors/destructors called during startup/shutdown.
- If the tools hit a
gs()modifier explained above.
- Jumping to non-symbolic addresses like so is not supported ๐ :
int main (void)
{
/* Call function at word address 0x2 */
return ((int(*)(void)) 0x2)();
}
Instead, a stub has to be set up, i.e. the function has to be called through a symbol (func_4 in the example) ๐:
int main (void)
{
extern int func_4 (void);
/* Call function at byte address 0x4 */
return func_4();
}
...and the application be linked with -Wl,--defsym,func_4=0x4. Alternatively, func_4 can be defined in the linker script. ๐ง
๐ Handling of the "RAMPD", "RAMPX", "RAMPY" and "RAMPZ" Special Function Registers ๐
okay so some AVR devices have more memory than a 16-bit pointer can reach, which is anything past the 64 KiB range ๐ญ. To get to those higher spots, the content of a RAMP register is used as the high part of the address. The X, Y, and Z address registers get paired with RAMPX, RAMPY, and RAMPZ respectively to make a wide address. RAMPD does the same job for direct addressing. โจ
- The startup code sets the
RAMPspecial function registers to zero. ๐ธ - If a named address space other than generic or
__flashis used (see AVR Named Address Spaces), thenRAMPZgets set as needed before the operation. ๐ - If the device supports RAM larger than 64 KiB and the compiler needs to change
RAMPZto pull off an operation,RAMPZgets reset to zero afterwards. ๐ - If the device has a specific
RAMPregister, the ISR prologue and epilogue save and restore that SFR, and initialize it with zero in case the ISR code might (implicitly) use it. ๐ก๏ธ - RAM larger than 64 KiB is not supported by GCC for AVR targets.
๐ Big warning, bestie: if you use inline assembler to read from locations outside the 16-bit address range and change one of the RAMP registers, you MUST reset it to zero after the access, or things get messy.
๐ง AVR Built-in Macros ๐ง
GCC defines a bunch of built-in macros so your code can check whether a feature is there or not. Almost all of the following built-in macros are deduced 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 built-in macro resolves to a decimal number that identifies the architecture, and it depends on the-mmcu=mcuoption. The possible values are2, 25, 3, 31, 35, 4, 5, 51, 6, which map to these mcus in order:"avr2"=2,"avr25"=25,"avr3"=3,"avr31"=31,"avr35"=35,"avr4"=4,"avr5"=5,"avr51"=51,"avr6"=6- And
100, 102, 103, 104, 105, 106, 107for the xmega and tiny ones, in order:"avrtiny"=100,"avrxmega2"=102,"avrxmega3"=103,"avrxmega4"=104,"avrxmega5"=105,"avrxmega6"=106,"avrxmega7"=107
- If mcu specifies a device, this macro gets set accordingly. For example, with
-mmcu=atmega8the macro is defined to4. ๐
__AVR_Device__โ Setting-mmcu=devicedefines this macro, which reflects the device's name. For example,-mmcu=atmega8defines__AVR_ATmega8__, and-mmcu=attiny261adefines__AVR_ATtiny261A__, and so on. ๐ฆ- The 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 macro and device in-mmcu=deviceis that the latter is always lowercase. - If device isn't a device but only a core architecture like
avr51, this macro is not defined.
- The names follow the scheme
__AVR_DEVICE_NAME__โ Setting-mmcu=devicedefines this macro to the device's name. For example, with-mmcu=atmega8it's defined to"atmega8". If device is only a core architecture likeavr51, this macro is not defined. ๐__AVR_XMEGA__โ The device or architecture belongs to the XMEGA family of devices. โญ__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. This is the case for devices with more than 128 KiB of program memory. It also means the program counter (PC) is 3 bytes wide. ๐ง__AVR_2_BYTE_PC__โ The program counter (PC) is 2 bytes wide. This is the case for devices with up to 128 KiB of program memory. ๐ฆ__AVR_HAVE_8BIT_SP__and__AVR_HAVE_16BIT_SP__โ The compiler treats the stack pointer (SP) register as an 8-bit or 16-bit register, respectively. 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,RAMPY, andRAMPZspecial function registers, respectively. ๐ธ__NO_INTERRUPTS__โ This macro reflects the-mno-interruptscommand-line option. ๐__AVR_ERRATA_SKIP__and__AVR_ERRATA_SKIP_JMP_CALL__โ Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum. The skip instructions areSBRS,SBRC,SBIS,SBIC, andCPSE. The second macro is only defined if__AVR_HAVE_JMP_CALL__is also set.
โ ๏ธ Those devices really can't skip 32-bit instructions, so keep that in mind when you're writing skip logic. ๐
__AVR_ISA_RMW__โ The device has Read-Modify-Write instructions (XCH,LAC,LAS, andLAT). ๐ฅ__AVR_SFR_OFFSET__=offsetโ Instructions that can address I/O special function registers directly, likeIN,OUT,SBI, and so on, may use a different address than an instruction that accesses 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โ Some devices can read from flash memory usingLD*instructions. The flash memory shows up in the data address space at an offset of__AVR_PM_BASE_ADDRESS__. If this macro isn't defined, the feature isn't available. If it is defined, the address space is linear, so there's no need to put.rodatainto RAM. The default linker description file handles this, and it's currently available foravrtinyandavrxmega3. Even better, you don't need address spaces like__flashor attributes likeprogmemandpgm_read_*. ๐__AVR_HAVE_FLMAP__โ This macro is defined 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.
- The device has the
This implies the compiler was configured with GNU Binutils that implement PR31124 (https://sourceware.org/PR31124). ๐
__AVR_RODATA_IN_RAM__โ This macro is undefined when the code is compiled for a core architecture. When the code is compiled for a device, the macro is defined to1if the.rodatasections for read-only data are located in RAM, and defined to0otherwise. ๐__WITH_AVRLIBC__โ The compiler is configured to be used together with AVR-Libc. See the--with-avrlibcconfigure option. ๐ซถ__HAVE_DOUBLE_MULTILIB__โ Defined if-mdouble=acts as a multilib option. โจ__HAVE_DOUBLE32__and__HAVE_DOUBLE64__โ Defined if the compiler supports 32-bit double or 64-bit double, respectively. The actual layout is specified by option-mdouble=. ๐ฆ__DEFAULT_DOUBLE__โ The size in bits ofdoubleif-mdouble=is not set. To test the layout ofdoublein a program, use the built-in macro__SIZEOF_DOUBLE__. ๐__HAVE_LONG_DOUBLE32__,__HAVE_LONG_DOUBLE64__,__HAVE_LONG_DOUBLE_MULTILIB__and__DEFAULT_LONG_DOUBLE__โ Same as above, but forlong doubleinstead ofdouble. ๐ธ__WITH_DOUBLE_COMPARISON__โ Reflects the--with-double-comparison={tristate|bool|libf7}configure option (https://gcc.gnu.org/install/configure.html#avr), and is defined to2or3. ๐__WITH_LIBF7_LIBGCC__,__WITH_LIBF7_MATH__and__WITH_LIBF7_MATH_SYMBOLS__โ Reflect the--with-libf7={libgcc|math|math-symbols}configure option (https://gcc.gnu.org/install/configure.html#avr). ๐
๐ฅ AVR Internal Options ๐ฅ
These options are used internally by the compiler and to communicate between device specs files and the compiler proper. You don't need to set them by hand, and they are definitely not optimization options. Using them the wrong way may lead to sub-optimal or wrong code. They're documented for completeness, and so you can better understand device specs files (https://gcc.gnu.org/wiki/avr-gcc#spec-files). ๐ง
๐ Seriously, don't go poking these unless you know exactly what you're doing, or your code could come out sub-optimal or just plain wrong.
-mn-flash=numโ Assumes the flash memory has a size ofnumtimes 64 KiB. This determines which__flashNaddress spaces are available. ๐งฉ-mflmapโ The device has theFLMAPbit field, located in the special function registerNVMCTRL_CTRLB. ๐บ๏ธ-mrmwโ Assumes the device supports the Read-Modify-Write instructionsXCH,LAC,LAS, andLAT. ๐ฅ-mshort-callsโ AssumesRJMPandRCALLcan target the whole program memory. This option is used for multilib generation and selection for 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, meaning it assumes the high byte of the stack pointer is zero. The compiler uses this option to select and build multilibs for architecturesavr2andavr25, since these architectures mix devices with and withoutSPH. ๐
๐ Blackfin Options ๐
-mcpu=cpu[-sirevision]โ Specifies the name of the target Blackfin processor. Currently, cpu can be one 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. โจ
Okay so the optional sirevision lets you tell GCC exactly which silicon revision of the Blackfin processor you're targeting ๐ฆ. Every workaround for that revision gets switched on โจ. If sirevision is none, no workarounds are enabled at all ๐. If it's any, every workaround for the targeted processor gets enabled ๐.
GCC also defines the __SILICON_REVISION__ macro as two hexadecimal digits that represent the major and minor numbers of the silicon revision ๐ธ. With none, that macro isn't defined at all ๐. With any, it's defined to be 0xffff ๐ฅ. And if you skip the optional sirevision completely, GCC just 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 from libgloss to get linked in, as long as -msim isn't given ๐.
Without this option, bf532 is the default processor ๐
.
Heads up, though: support for bf561 is incomplete ๐ญ. For bf561, only the preprocessor macro gets defined.
-msimโ Okay, this one's for the simulator ๐ฅ๏ธ. It links in the simulator BSP fromlibgloss. It only does anything for thebfin-elftoolchain. Some other options, like-mid-shared-libraryand-mfdpic, imply-msimon their own ๐ซถ.-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions ๐. You skip the instructions that save, set up, and restore frame pointers, and you get an extra register to play with in leaf functions โจ.-mspecld-anomalyโ When this is on, the compiler makes sure the generated code has no speculative loads right after jump instructions ๐ก๏ธ. If you use it,__WORKAROUND_SPECULATIVE_LOADSgets defined.-mno-specld-anomalyโ Don't generate the extra code that stops speculative loads from happening ๐ โโ๏ธ.-mcsync-anomalyโ When this is on, the compiler makes sure noCSYNCorSSYNCinstructions show up too soon after conditional branches ๐. If you use it,__WORKAROUND_SPECULATIVE_SYNCSgets defined.-mno-csync-anomalyโ Don't generate the extra code that stopsCSYNCorSSYNCinstructions from landing too soon after a conditional branch ๐.-mlow64kโ When enabled, the compiler can take advantage of knowing the whole program fits into the low 64k of memory ๐ง .-mno-low64kโ Assume the program could be arbitrarily large. This is the default ๐ธ.-mstack-check-l1โ Do stack checking using the info that the uClinux kernel puts into L1 scratchpad memory ๐ง.-mid-shared-libraryโ Generate code that supports shared libraries through the library ID method โจ. This lets you do execute in place and shared libraries in an environment without virtual memory management ๐ฆ. It implies-fPIC, and with abfin-elftarget it also implies-msim๐.-mno-id-shared-libraryโ Generate code that doesn't assume ID-based shared libraries are in use. This is the default ๐.-mleaf-id-shared-libraryโ Generate code that supports shared libraries through 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 won't link against any ID shared libraries ๐. You get slower code for jump and call instructions ๐ข.-mshared-library-id=nโ Specifies the identification number of the ID-based shared library you're compiling ๐. A value of0gives you more compact code ๐ . Other values force that number onto the current library, but it's no more space- or time-efficient than leaving this option out ๐ญ.-msep-dataโ Generate code that lets the data segment sit in a different area of memory from the text segment ๐. This allows execute in place in an environment without virtual memory management, because it gets rid of relocations against the text section โจ.-mno-sep-dataโ Generate code that assumes the data segment follows the text segment. This is the default ๐.-mlong-calls,-mno-long-callsโ-mlong-callstells the compiler to make function calls by first loading the function's address into a register, then doing a subroutine call on that register ๐. You need this if the target function is outside the 24-bit addressing range of the offset-based subroutine call instruction ๐. It's not enabled by default, and-mno-long-callsputs you back to the default behavior ๐. Heads up, these switches have no effect on how function calls through function pointers get generated ๐.-mfast-fpโ Link with the fast floating-point library โก. It relaxes some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN), all in the name of performance ๐ฅ.-minline-pltโ Enable inlining of PLT entries in function calls to functions that aren't known to bind locally ๐งฉ. It has no effect without-mfdpic๐.-mmulticoreโ Build a standalone application for multicore Blackfin processors ๐ง . This option uses the proper start files and link scripts for multicore, and it defines the__BFIN_MULTICOREmacro ๐. It can only be used with-mcpu=bf561[-sirevision]๐ธ.
This option can go with -mcorea or -mcoreb, which pick the one-application-per-core programming model ๐. Without either of those, you get the single-application/dual-core programming model ๐ฆ. In that model, the main function of Core B should be named coreb_main ๐ซถ.
Without this option, you get the single-core application programming model ๐.
-mcoreaโ Build a standalone application for Core A of BF561 when you're using the one-application-per-core programming model ๐ ฐ๏ธ. Proper start files and link scripts support Core A, and the__BFIN_COREAmacro gets defined ๐. This can only be used together with-mmulticore๐ .-mcorebโ Build a standalone application for Core B of BF561 when you're using the one-application-per-core programming model ๐ ฑ๏ธ. Proper start files and link scripts support Core B, and the__BFIN_COREBmacro gets defined ๐. When you use this option,coreb_mainshould be used instead ofmainโจ. This can only be used together with-mmulticore๐ฅ.-msdramโ Build a standalone application for SDRAM ๐งธ. Proper start files and link scripts put the application into SDRAM, and the__BFIN_SDRAMmacro gets defined ๐ฆ. The loader should initialize SDRAM before it loads the application ๐ญ.-micplbโ Assume ICPLBs are enabled at run time. This affects certain anomaly workarounds ๐ง . For Linux targets, the default is to assume ICPLBs are enabled ๐ง. For standalone applications, the default is off ๐.
๐ง C6X Options ๐ง
-march=nameโ This specifies the name of the target architecture ๐๏ธ. GCC uses this name to figure out which kinds of instructions it can emit when generating assembly code ๐. The permissible names arec62x,c64x,c64x+,c67x,c67x+, andc674xโจ.-mbig-endianโ Generate code for a big-endian target ๐ธ.-mlittle-endianโ Generate code for a little-endian target. This is the default ๐.-msimโ Choose startup files and a linker script that suit the simulator ๐ฅ๏ธ.-msdata=defaultโ Put small global and static data in the.neardatasection, which is pointed to by registerB14๐. Put small uninitialized global and static data in the.bsssection, which sits right next to.neardata๐ซถ. Put small read-only data into the.rodatasection ๐. The matching sections for large chunks of data are.fardata,.far, and.const๐งณ.-msdata=allโ Put all data, not just the small stuff, into the sections reserved for small data ๐. Then use addressing relative to theB14register to get at them ๐ฅ.-msdata=noneโ Don't use the sections reserved for small data at all ๐ โโ๏ธ. Use absolute addresses to access all data ๐. Put all initialized global and static data in.fardata, and all uninitialized data in.far๐. Put all constant data into.const๐.
๐ฆ CRIS Options ๐ฆ
These options are defined specifically for the CRIS ports ๐ .
-march=architecture-type,-mcpu=architecture-typeโ Generate code for the specified architecture ๐๏ธ. The choices for architecture-type arev3,v8, andv10, which are for ETRAX 4, ETRAX 100, and ETRAX 100 LX respectively โจ. The default isv0๐.-mtune=architecture-typeโ Tune everything that applies to the generated code for architecture-type, except for the ABI and the set of available instructions ๐ถ. The choices are the same as for-march=architecture-type๐ซถ.-mmax-stack-frame=nโ Warn when a function's stack frame goes overnbytes ๐จ.-metrax4,-metrax100โ These are synonyms for-march=v3and-march=v8respectively ๐.-mmul-bug-workaround,-mno-mul-bug-workaroundโ Work around a bug in themulsandmuluinstructions, for the CPU models where it applies ๐. This option is disabled by default ๐.-mpdebugโ Enable CRIS-specific verbose debug info in the assembly code ๐. This also turns off the#NO_APPformatted-code indicator that goes to the assembler at the start of the assembly file ๐ซ .-mcc-initโ Don't use condition-code results from the previous instruction. Always emit compare and test instructions before condition codes get used ๐งผ.-mno-side-effectsโ Don't emit instructions with side effects in addressing modes other than post-increment ๐ฟ.-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ These no- options eliminate the alignment arrangements, and the others arrange alignment ๐. Arrangement means the stack frame, individual data, and constants get aligned to the maximum single data access size for the chosen CPU model โจ. The default is to arrange for 32-bit alignment ๐. ABI details such as structure layout aren't affected by these options ๐.-m32-bit,-m16-bit,-m8-bitโ Same energy as the stack-, data- and const-align options from up above ๐ These make the stack frame, writable data and constants all 32-bit, 16-bit or 8-bit aligned. The default is 32-bit alignment ๐ธ-mno-prologue-epilogue,-mprologue-epilogueโ With-mno-prologue-epilogue, the usual function prologue and epilogue that set up the stack frame get skipped, and no return instructions or return sequences show up in the code ๐
Bestie, use this one ONLY if you're going to visually inspect the compiled code yourself. No warnings or errors pop up when call-saved registers need saving or when storage for local variables needs allocating. Read your output!! ๐
-melfโ Legacy no-op option. It does nothing, but it's still here ๐ฆ-simโ This one links with input-output functions from a simulator library ๐ง Code, initialized data and zero-initialized data all get allocated back-to-back, consecutively.-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 options when you're compiling for C-SKY V2 processors ๐
-march=archโ Picks the C-SKY target architecture. The valid values forarchareck801,ck802,ck803,ck807, andck810. The default isck810๐-mcpu=cpuโ Picks the C-SKY target processor. The valid values forcpuareck801,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โ Pick big-endian or little-endian code. Little-endian is the default ๐-mfloat-abi=nameโ Chooses which floating-point ABI to use. The permissible values aresoft,softfpandhard๐ฅsoftโ GCC generates output full of library calls for floating-point operations ๐ซถsoftfpโ Lets you generate code that uses hardware floating-point instructions, but it still sticks with the soft-float calling conventions โจhardโ Allows floating-point instructions and uses FPU-specific calling conventions ๐
The default depends on the specific target configuration. Heads up: 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 ๐ญ
-mhard-float,-msoft-floatโ Pick hardware or software floating-point implementations. The default is soft float ๐ฆ-mdouble-float,-mno-double-floatโ When-mhard-floatis in effect, this turns on generation of double-precision float instructions. It's the default except when you're compiling for CK803 ๐ธ-mfdivdu,-mno-fdivduโ When-mhard-floatis in effect, this turns on generation of"frecipd","fsqrtd", and"fdivd"instructions. It's the default except when you're compiling for CK803 ๐-mfpu=fpuโ Selects the floating-point processor. This option can ONLY be used with-mhard-float. The values forfpuarefpv2_sf(equivalent to-mno-double-float -mno-fdivdu),fpv2(-mdouble-float -mno-divdu), andfpv2_divd(-mdouble-float -mdivdu) ๐ง-melrw,-mno-elrwโ Enables the extended"lrw"instruction. This defaults to on for CK801 and off otherwise ๐-mistack,-mno-istackโ Enables interrupt stack instructions. The default is off ๐
The -mistack option is required if you want to handle the "interrupt" and "isr" function attributes ๐ซถ
-mmpโ Enables multiprocessor instructions. The default is off ๐-mcpโ Enables coprocessor instructions. The default is off โญ-mcacheโ Enables coprocessor instructions. The default is off ๐-msecurityโ Enables C-SKY security instructions. The default is off ๐ฅ-mtrustโ Enables C-SKY trust instructions. The default is off ๐-mdsp,-medsp,-mvdspโ Enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively. All of these default to off ๐ฆ-mdiv,-mno-divโ Generates divide instructions. The 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 option is ignored for CK801, where this is the required behavior, and it defaults to on for CK802. For other targets, the default is off.-mhigh-registers,-mno-high-registersโ Generates code using the high registers numbered 16-31 โจ This option is not supported on CK801, CK802, or CK803, and it's enabled by default for other processors.-manchor,-mno-anchorโ Generates code using global anchor symbol addresses ๐ง-mpushpop,-mno-pushpopโ Generates code using"push"and"pop"instructions. This option defaults to on ๐-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ Generates code using"stm"and"ldm"instructions. This option 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 handing that job off to the assembler ๐ซถ This option is the default and is 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. This option defaults to off ๐-mccrt,-mno-ccrtโ Generates code for the C-SKY compiler runtime instead of libgcc. This option defaults to off ๐-mbranch-cost=nโ Sets the branch costs to roughly"n"instructions. The default is 1 ๐ฆ-msched-prolog,-mno-sched-prologโ Permits scheduling of function prologue and epilogue sequences. It's disabled by default.
Warning, bestie!! Using this option can result in code that isn't compliant with the C-SKY V2 ABI prologue requirements, and that code can't be debugged or backtraced. Proceed with caution ๐ญ
-msimโ Links the librarylibsemi.a, which is compatible with the simulator. This only applies to the ELF compiler ๐ฅ
๐ Darwin Options ๐
These options are defined for all architectures running the Darwin operating system ๐ธ
FSF GCC on Darwin does NOT create "fat" object files. Instead, it creates an object file for the single architecture that GCC was built to target. Apple's GCC on Darwin, on the other hand, DOES create "fat" files if you use multiple -arch options. It does this by running the compiler or linker multiple times and then joining the results together with lipo ๐
The subtype of the file it creates (like ppc7400 or ppc970 or i686) is determined by the flags that specify the ISA GCC is targeting, like -mcpu or -march. The -force_cpusubtype_ALL option can be used to override this ๐
The Darwin tools behave differently when they're presented with an ISA mismatch. The assembler, as, only lets you use instructions that are valid for the subtype of the file it's generating, 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 create 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 will get rejected ๐ The linker for executables, ld, quietly gives the executable the most restrictive subtype of any of its input files ๐คซ
-Fdirโ Adds the framework directorydirto the HEAD of the list of directories searched for header files ๐ง These directories are interleaved with the ones specified by-Ioptions, and they're scanned in a left-to-right order.
So what even is a framework directory? It's a directory with frameworks in it ๐ A framework is a directory that has a Headers and/or PrivateHeaders directory sitting directly inside it, and its name ends in .framework. The name of a framework is the name of that directory minus the .framework part. Headers for the framework are found in one of those two directories, and Headers gets searched first โจ
A subframework is a framework directory that lives inside a framework's Frameworks directory. Includes of subframework headers can only show up in a header of the framework that contains the subframework, or in a sibling subframework header. Two subframeworks are siblings if they occur in the same framework ๐ซถ A subframework should NOT have the same name as a framework, and a warning is issued if that rule gets broken ๐ญ Right now a subframework can't have subframeworks of its own, but the mechanism may be extended to support that in the future ๐
The standard frameworks live in /System/Library/Frameworks and /Library/Frameworks ๐ An example include looks like #include <Framework/header.h>, where Framework is the name of the framework and header.h is found in the PrivateHeaders or Headers directory ๐ฆ
-iframeworkdirโ This is like-F, except the directory is treated as a system directory ๐ธ The main difference is that with-iframework, the compiler does NOT warn about constructs contained within header files found viadir. This option is only valid for the C family of languages ๐-gusedโ Emits debugging information for symbols that are used. For the stabs debugging format, this enables-feliminate-unused-debug-symbols. This is ON by default โญ-gfullโ Emits debugging information for ALL symbols and types ๐ฅ-fconstant-cfstringsโ This is an alias for-mconstant-cfstrings๐-mconstant-cfstringsโ When the NeXT runtime is being used (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โ The earliest version of MacOS X that this executable will run on isversion๐ Typical values supported forversioninclude12,10.12, and10.5.8.
If the compiler was built to use the system's headers by default, then the default for this option is the system version the compiler is running on ๐ง Otherwise, the default is to make choices that are compatible with as many systems and code bases as possible ๐
-mkernelโ ๐ง Okay bestie, this one switches 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 applicable. For PowerPC targets it also sets-mno-altivec,-msoft-float,-fno-builtinand-mlong-branch๐-mone-byte-boolโ ๐ฆ This one overrides the defaults forboolso thatsizeof(bool)==1. By default, sizeof(bool) is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86, so it does absolutely nothing on x86 ๐
Warning: The -mone-byte-bool switch causes GCC to generate code that is not binary compatible with code generated without that switch. Using this switch may require recompiling all other modules in a program, including system libraries. Use this switch to conform to a non-default data model. ๐
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ ๐ฅ These generate code built for fast turnaround development, like letting GDB dynamically load.ofiles into programs that are already running ๐-findirect-dataand-ffix-and-continueonly stick around for backwards compatibility, so bestie, you probably want-mfix-and-continue๐ซถ-all_loadโ ๐ธ Loads every member of static archive libraries. Check outman ld(1)for the full tea โ-arch_errors_fatalโ ๐ Makes the errors about files with the wrong architecture fatal. No warnings-and-keep-going, it's game over ๐-bind_at_loadโ โญ Marks the output file so the dynamic linker binds all undefined references when the file gets loaded or launched ๐ง-bundleโ ๐ Produces a Mach-o bundle format file. Peek atman ld(1)for more info ๐-bundle_loaderexecutable โ ๐ Specifies the executable that will load the build output file being linked. Again,man ld(1)has the details โจ-dynamiclibโ ๐ Passes the Darwin libtool command so GCC makes a dynamic library instead of an executable when linking ๐ฆ-force_cpusubtype_ALLโ ๐ Gives GCC's output file the ALL subtype, instead of the one controlled by the-mcpuor-marchoption ๐ซถ-nodefaultrpathsโ ๐ Stops default run paths for the compiler library directories from getting added to executables, modules or dynamic libraries. On macOS 10.5 and later, the embedded runpath gets added by default unless you pass-nodefaultrpathson the link line. Run paths are needed (and therefore enforced) to build on macOS 10.11 or later ๐
These options are passed to the Darwin linker, and the Darwin linker man page describes them in detail. Here's the whole lineup ๐
-allowable_clientclient_name โ ๐ธ Passed to the Darwin linker, which has the full details-client_nameโ ๐ธ Passed to the Darwin linker, which has the full details-compatibility_versionโ ๐ธ Passed to the Darwin linker, which has the full details-current_versionโ ๐ธ Passed to the Darwin linker, which has the full details-dead_stripโ ๐ธ Passed to the Darwin linker, which has the full details-dependency-fileโ ๐ธ Passed to the Darwin linker, which has the full details-dylib_fileโ ๐ธ Passed to the Darwin linker, which has the full details-dylinker_install_nameโ ๐ธ Passed to the Darwin linker, which has the full details-dynamicโ ๐ธ Passed to the Darwin linker, which has the full details-exported_symbols_listโ ๐ธ Passed to the Darwin linker, which has the full details-filelistโ ๐ธ Passed to the Darwin linker, which has the full details-flat_namespaceโ ๐ธ Passed to the Darwin linker, which has the full details-force_flat_namespaceโ ๐ธ Passed to the Darwin linker, which has the full details-headerpad_max_install_namesโ ๐ธ Passed to the Darwin linker, which has the full details-image_baseโ ๐ธ Passed to the Darwin linker, which has the full details-initโ ๐ธ Passed to the Darwin linker, which has the full details-install_nameโ ๐ธ Passed to the Darwin linker, which has the full details-keep_private_externsโ ๐ธ Passed to the Darwin linker, which has the full details-multi_moduleโ ๐ธ Passed to the Darwin linker, which has the full details-multiply_definedโ ๐ธ Passed to the Darwin linker, which has the full details-multiply_defined_unusedโ ๐ธ Passed to the Darwin linker, which has the full details-noall_loadโ ๐ธ Passed to the Darwin linker, which has the full details-no_dead_strip_inits_and_termsโ ๐ธ Passed to the Darwin linker, which has the full details-nofixprebindingโ ๐ธ Passed to the Darwin linker, which has the full details-nomultidefsโ ๐ธ Passed to the Darwin linker, which has the full details-noprebindโ ๐ธ Passed to the Darwin linker, which has the full details-noseglinkeditโ ๐ธ Passed to the Darwin linker, which has the full details-pagezero_sizeโ ๐ธ Passed to the Darwin linker, which has the full details-prebindโ ๐ธ Passed to the Darwin linker, which has the full details-prebind_all_twolevel_modulesโ ๐ธ Passed to the Darwin linker, which has the full details-private_bundleโ ๐ธ Passed to the Darwin linker, which has the full details-read_only_relocsโ ๐ธ Passed to the Darwin linker, which has the full details-sectalignโ ๐ธ Passed to the Darwin linker, which has the full details-sectobjectsymbolsโ ๐ธ Passed to the Darwin linker, which has the full details-whyloadโ ๐ธ Passed to the Darwin linker, which has the full details-seg1addrโ ๐ธ Passed to the Darwin linker, which has the full details-sectcreateโ ๐ธ Passed to the Darwin linker, which has the full details-sectobjectsymbolsโ ๐ธ Passed to the Darwin linker, which has the full details-sectorderโ ๐ธ Passed to the Darwin linker, which has the full details-segaddrโ ๐ธ Passed to the Darwin linker, which has the full details-segs_read_only_addrโ ๐ธ Passed to the Darwin linker, which has the full details-segs_read_write_addrโ ๐ธ Passed to the Darwin linker, which has the full details-seg_addr_tableโ ๐ธ Passed to the Darwin linker, which has the full details-seg_addr_table_filenameโ ๐ธ Passed to the Darwin linker, which has the full details-seglinkeditโ ๐ธ Passed to the Darwin linker, which has the full details-segprotโ ๐ธ Passed to the Darwin linker, which has the full details-segs_read_only_addrโ ๐ธ Passed to the Darwin linker, which has the full details-segs_read_write_addrโ ๐ธ Passed to the Darwin linker, which has the full details-single_moduleโ ๐ธ Passed to the Darwin linker, which has the full details-staticโ ๐ธ Passed to the Darwin linker, which has the full details-sub_libraryโ ๐ธ Passed to the Darwin linker, which has the full details-sub_umbrellaโ ๐ธ Passed to the Darwin linker, which has the full details-twolevel_namespaceโ ๐ธ Passed to the Darwin linker, which has the full details-umbrellaโ ๐ธ Passed to the Darwin linker, which has the full details-undefinedโ ๐ธ Passed to the Darwin linker, which has the full details-unexported_symbols_listโ ๐ธ Passed to the Darwin linker, which has the full details-weak_reference_mismatchesโ ๐ธ Passed to the Darwin linker, which has the full details-whatsloadedโ ๐ธ Passed to the Darwin linker, which has the full details
๐ฆ DEC Alpha Options ๐ฆ
These -m options are defined for the DEC Alpha implementations ๐
-mno-soft-float,-msoft-floatโ โจ Use (or don't use) the hardware floating-point instructions for floating-point operations. With-msoft-float, functions inlibgcc.ado the floating-point work. Unless they're replaced by routines that emulate those operations, or compiled to call such emulation routines, these routines issue floating-point operations. If you're compiling for an Alpha without floating-point operations, you must make sure the library is built so it doesn't call them ๐
Note that Alpha implementations without floating-point operations are required to have floating-point registers ๐ซถ
-mfp-reg,-mno-fp-regsโ ๐ Generate code that uses (or doesn't use) the floating-point register set.-mno-fp-regsimplies-msoft-float. If the floating-point register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results get passed in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value called by code compiled with-mno-fp-regsmust also be compiled with that option ๐
A typical use of this option is building a kernel that doesn't use, and so doesn't need to save and restore, any floating-point registers ๐
-mieeeโ ๐ The Alpha architecture has floating-point hardware tuned for maximum performance, and it's mostly IEEE compliant. For full compliance, though, it needs software help. This option generates fully IEEE-compliant code, except the inexact-flag isn't maintained (see below). When it's turned on, the preprocessor macro_IEEE_FPgets defined during compilation. The resulting code is less efficient, but it can correctly support 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. The reason is that the software functions in the GNU libc math libraries generate denormalized numbers, NaNs, and infs, and all of those will cause a program to 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. Turning it on makes the generated code fully-compliant IEEE math. Along with_IEEE_FP, the preprocessor macro_IEEE_FP_EXACTis defined. On some Alpha implementations the resulting code may run significantly slower than the default. Very little code depends on the inexact-flag, so you should normally not specify this option ๐ง Other Alpha compilers call this option-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 set to one of four values:nโ The default (normal) setting. The only traps enabled are the ones that can't be disabled in software (for example, the division by zero trap) ๐uโ In addition to the traps enabled byn, underflow traps are enabled as well ๐ธ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 option-fprm rounding-mode. The rounding-mode can be one of:nโ Normal IEEE rounding mode. Floating-point numbers are 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 are 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 initializes this register for rounding towards plus infinity. So unless your program modifies the fpcr,dcorresponds to round towards plus infinity ๐ง
-mtrap-precision=trap-precisionโ ๐ธ On the Alpha architecture, floating-point traps are imprecise. Without software help, that means it's impossible to recover from a floating trap, and program execution normally has to be terminated. GCC can generate code that helps operating system trap handlers figure out the exact location that caused a floating-point trap. Depending on what your application needs, you can pick different levels of precision:pโ Program precision. This is the default, and it means a trap handler can only identify which program caused a floating-point exception ๐fโ Function precision. The trap handler can determine the function that caused a floating-point exception ๐ซถiโ Instruction precision. The trap handler can determine the exact instruction that caused a floating-point exception ๐
Other Alpha compilers provide the equivalent options called -scope_safe and -resumption_safe โจ
-mieee-conformantโ ๐ Marks the generated code as IEEE conformant. You must not use this option 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 examines 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 it takes more instructions (the maximum is six). You typically use this option to build a shared library dynamic loader. Since it's itself a shared library, it has to relocate itself in memory before it can find the variables and constants in its own data segment ๐-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ okay so these are your on/off switches for the optional BWX, CIX, FIX and MAX instruction sets โจ. By default GCC uses whatever the CPU type from-mcpu=supports, or the CPU GCC was built on if you didn't pick one ๐ซถ.-mfloat-vax,-mfloat-ieeeโ this one decides whether the code uses VAX F and G floating-point arithmetic (-mfloat-vax) or sticks with IEEE single and double precision (-mfloat-ieee) ๐ธ.-mexplicit-relocs,-mno-explicit-relocsโ ngl this one has a whole backstory ๐. Older Alpha assemblers couldn't make symbol relocations except through assembler macros, and those macros don't let the instruction scheduling be optimal ๐. GNU binutils 2.12 and newer has a new syntax that lets the compiler explicitly mark which relocations go with which instructions. This is mostly a debugging tool, since GCC checks what the assembler can do when it's built and sets the default to match ๐ฅ.-msmall-data,-mlarge-dataโ when-mexplicit-relocsis on, static data is reached through gp-relative relocations ๐ง.- With
-msmall-data, objects 8 bytes or smaller get tucked into a small data area (the".sdata"and".sbss"sections) and are accessed through 16-bit relocations off the$gpregister. That caps the small data area at 64KB, but the variables can be reached with a single instruction ๐. - The default is
-mlarge-data. With this option the data area is limited to just below 2GB. Programs that need more than 2GB of data have to use"malloc"or"mmap"to put the data on the heap instead of in the program's data segment ๐ญ. - When generating code for shared libraries,
-fpicimplies-msmall-dataand-fPICimplies-mlarge-data๐.
- With
-msmall-text,-mlarge-textโ with-msmall-text, the compiler assumes the code for the whole program (or shared library) fits in 4MB, so it's reachable with a branch instruction ๐ฆ. If-msmall-datais also used, 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 โจ.- The default is
-mlarge-text.
- The default is
-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 picks the default instruction set from the processor you name. No processor type? GCC defaults to the one it was built on.- Supported values for
cpu_typeare: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
native, which picks the best architecture option for the host processor.-mcpu=nativedoes nothing if GCC doesn't recognize the processor ๐.
- Supported values for
-mtune=cpu_typeโ only sets the instruction scheduling parameters forcpu_type. The instruction set stays exactly the same ๐.- Native toolchains also support
native, which picks the best architecture option for the host processor.-mtune=nativedoes nothing if GCC doesn't recognize the processor.
- Native toolchains also support
-mmemory-latency=timeโ sets the latency the scheduler should assume for typical memory references as the application sees them โฑ๏ธ. That number really depends on the app's memory access patterns and the size of the machine's external cache.- Valid options for
timeare:numberโ a decimal number of clock cycles.L1,L2,L3,mainโ GCC has estimates of clock cycles for "typical" EV4 & EV5 hardware at the Level 1, 2 & 3 caches (also called Dcache, Scache, and Bcache), plus main memory. Heads up:L3is only valid for EV5 โ ๏ธ.
- Valid options for
๐ฆ eBPF Options ๐ฆ
-mframe-limit=bytesโ sets the hard limit for frame sizes, in bytes ๐ง. The value you give should be less than or equal to32767. If you don't set it, the limit is whatever 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โ turns the extra conditional-branch instructions on or off. Enabled for CPU v2 and above ๐ฅ.-mjmp32,-mno-jmp32โ turns 32-bit jump instructions on or off. Enabled for CPU v3 and above.-malu32,-mno-alu32โ turns 32-bit ALU instructions on or off. Enabled for CPU v3 and above.-mv3-atomics,-mno-v3-atomicsโ turns the general atomic operations introduced in CPU v3 on or off. Enabled for CPU v3 and above.-mbswap,-mno-bswapโ turns byte swap instructions on or off. Enabled for CPU v4 and above.-msdiv,-mno-sdivโ turns signed division and modulus instructions on or off. Enabled for CPU v4 and above.-msmov,-mno-smovโ turns sign-extending move and memory load instructions on or off. Enabled for CPU v4 and above.-mcpu=versionโ picks which version of the eBPF ISA you're targeting ๐ . Newer versions might not be supported by every kernel. The default isv4.- Supported values for
versionare:v1โ the first stable eBPF ISA, with no special features or extensions.v2โ supports the jump extensions, as in-mjmpext.v3โ all the 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 the 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>
- Supported values for
-mco-reโ enables BPF Compile Once - Run Everywhere (CO-RE) support ๐งฉ. Requires and is implied by-gbtf.-mno-co-reโ disables BPF CO-RE support ๐ . BPF CO-RE support is turned on by default when you generate BTF debug information for the BPF target.-mxbpfโ generates code for an expanded version of BPF that relaxes some of the usual BPF restrictions โจ.-<Save and restore callee-saved registers at function entry and exit, respectively.>
-masm=dialectโ outputs assembly instructions in the eBPF dialect you select. The default isnormal.- Supported values for
dialectare:normalโ outputs the normal assembly dialect.pseudocโ outputs the pseudo-c assembly dialect.
- Supported values for
-minline-memops-threshold=bytesโ sets a size threshold in bytes, at or below whichmemmove,memcpyandmemsetalways get expanded inline ๐ง . Anything bigger would need a library call instead of inline expansion, but BPF doesn't allow libcalls, so going over the threshold gives a compile-time error. The default is1024bytes.
Going over this threshold is a compile-time error ๐, because BPF doesn't allow libcalls.
๐ 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 assumes that all symbolic values and addresses fit into a 20-bit range.-mno-lsimโ assumes runtime support has already been provided, so there's no need to include the simulator library (libsim.a) on the linker command line.
๐ FT32 Options ๐
These options are defined specifically for the FT32 port ๐ฆ.
-msimโ says 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 that will run on real hardware ๐ซ. You have to provide your own runtime library for whatever I/O functions you need.
-mlraโ enables Local Register Allocation. It's still experimental for FT32, so by default the compiler uses standard reload.-mnodivโ don't usedivandmodinstructions.-mft32bโ enables the extended instructions of the FT32B processor.-mcompressโ compresses all code using the Ft32B code compression scheme ๐๏ธ.-mnopmโ don't generate code that reads program memory.
๐ FRV Options ๐
-mgpr-32โ only use the first 32 general-purpose registers.-mgpr-64โ use all 64 general-purpose registers.-mfpr-32โ only use the first 32 floating-point registers.-mfpr-64โ use all 64 floating-point registers.-mhard-floatโ use hardware instructions for floating-point operations.-msoft-floatโ use library routines for floating-point operations.-malloc-ccโ dynamically allocate condition code registers.-mfixed-ccโ don't try to dynamically allocate condition code registers. Only use"icc0"and"fcc0".-mdwordโ changes the ABI to use double word instructions.-mno-dwordโ don't use double word instructions.-mdoubleโ use floating-point double instructions.-mno-doubleโ don't use floating-point double instructions.-mmediaโ use media instructions.-mno-mediaโ don't use media instructions.-mmuladdโ use multiply and add/subtract instructions.-mno-muladdโ don't use multiply and add/subtract instructions.-mfdpicโ ๐ฆ Okay so this picks the FDPIC ABI, which uses function descriptors to stand in for pointers to functions. With no PIC/PIE options at all, it implies-fPIE. With-fpicor-fpie, GOT entries and small data are assumed to sit within a 12-bit range from the GOT base address. With-fPICor-fPIE, GOT offsets get computed with 32 bits. On a bfin-elf target, this also implies-msim๐-minline-pltโ โจ This turns on inlining of PLT entries for function calls to functions that aren't known to bind locally. It does nothing without-mfdpic. It's on by default when you're optimizing for speed and compiling shared libraries (that's-fPICor-fpic), or when something like-O3or higher shows up on the command line ๐ฅ-mTLSโ ๐ธ Assumes a large TLS segment when generating thread-local code.-mtlsโ ๐ The opposite energy: does not assume a large TLS segment when generating thread-local code.-mgprel-roโ ๐ง This enables "GPREL" relocations in the FDPIC ABI for data known to be in read-only sections. It's on by default, except with-fpicor-fpie. Even though it might shrink the global offset table, it trades 1 instruction for 4 there. With-fPICor-fPIE, it trades 3 instructions for 4 (one of which can be shared by multiple symbols), and it skips needing a GOT entry for the referenced symbol, so it's more likely to be a win ๐ If it isn't,-mno-gprel-roturns it off.-multilib-library-picโ ๐ Links with the (library, not FD) pic libraries. It's implied by-mlibrary-pic, and also by-fPICand-fpicwithout-mfdpic. You should basically never have to use it explicitly ๐-mlinked-fpโ ๐ Follows the EABI rule of always creating a frame pointer whenever a stack frame gets allocated. It's on by default, and you can turn it off with-mno-linked-fp.-mlong-callsโ ๐ Uses indirect addressing to call functions outside the current compilation unit. This lets those functions 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 enabled. It doesn't make new packets, it just adds NOPs to packets that already exist.-mlibrary-picโ ๐ Generates position-independent EABI code.-macc-4โ ๐ฆ Uses only 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โ ๐ธ Does not mark ABI switches ine_flags.-mcond-moveโ โจ Enables 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โ ๐ Disables conditional-move instructions. ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-msccโ ๐ง Enables conditional set instructions (default). ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mno-sccโ ๐ซ Disables conditional set instructions. ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mcond-execโ ๐ Enables conditional execution (default). ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mno-cond-execโ ๐ Disables 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 (default). ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mno-vliw-branchโ ๐ Does not run the pass that packs branches into VLIW instructions. ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mmulti-cond-execโ ๐ Enables optimization of"&&"and"||"in conditional execution (default). ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mno-multi-cond-execโ ๐ Disables 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โ ๐ฆ Enables nested conditional execution optimizations (default). ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-mno-nested-cond-execโ ๐ซถ Disables nested conditional execution optimizations. ๐ ๏ธ This switch is mainly for debugging the compiler and will likely be removed in a future version.-moptimize-membarโ ๐งน This one cleans house by removing redundant"membar"instructions from the compiler-generated code. It's enabled by default.-mno-optimize-membarโ ๐ โโ๏ธ Turns off that 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 possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300andsimple๐
โจ GNU/Linux Options โจ
Okay, these -m options are defined just 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-exceptionsand-fno-rttiby default. When linking, it makes the GCC driver pass Android-specific options to the linker. It also causes the preprocessor macro"__ANDROID__"to be defined ๐ซถ-tno-android-ccโ ๐ โโ๏ธ Turns off the compilation effects of-mandroid. So it does not enable-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default.-tno-android-ldโ ๐ Turns off the linking effects of-mandroid, so standard Linux linking options get passed to the linker.
โจ H8/300 Options โจ
These -m options are defined for the H8/300 implementations ๐ง
-mrelaxโ ๐ Shortens some address references at link time, when that'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 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 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, this 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. It has no effect on the H8/300.
โจ HPPA Options โจ
These -m options are defined for the HPPA family of computers ๐ฅ๏ธ
-march=architecture-typeโ ๐ฆ Generates code for the specified architecture. The choices for architecture-type are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors. To figure out the right architecture option for your machine, check/usr/lib/sched.modelson an HP-UX system. Code compiled for lower numbered architectures runs on higher numbered ones, but not the other way around ๐-mpa-risc-1-0,-mpa-risc-1-1,-mpa-risc-2-0โ ๐ฏ These are synonyms for-march=1.0,-march=1.1, and-march=2.0respectively.-matomic-libcallsโ โ๏ธ Generates libcalls for atomic loads and stores when sync libcalls are disabled. This is enabled by default, and it only affects atomic libcall generation by the HPPA backend. Both the sync and libatomic libcall implementations use locking, so processor stores aren't atomic with respect to other atomic operations. Processor loads up to 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 inlibgcc.a, and atomic libcall support lives inlibatomic. 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. Use this with care, because it isn't compatible with the default 32-bit runtime. Only aggregates larger than eight bytes are passed by hidden reference, though, and this option gives better compatibility with OpenMP ๐ซถ-mcoherent-ldcwโ ๐ง Uses theldcw/ldcdcoherent cache-control hint.-mdisable-fpregsโ ๐ซ Disables floating-point registers. It's equivalent to"-msoft-float".-mdisable-indexingโ ๐ Stops the compiler from using indexing address modes. This avoids some pretty obscure problems when compiling MIG generated code under MACH.-mfast-indirect-callsโ ๐ Generates code that assumes calls never cross space boundaries, so GCC can emit code that makes indirect calls faster.
โ ๏ธ Heads up, bestie: this option does not work in the presence of shared libraries or nested functions. Don't use it there!
-mfixed-range=register-rangeโ okay so this one tells GCC to treat the register range you give it as fixed registers ๐, which means the register allocator is not allowed to touch them. It's super handy when compiling kernel code ๐ป. A register range is two registers separated by a dash, and you can list several ranges separated by a comma โจ.-mgasโ turns on assembler directives that only GAS understands ๐ง-mgnu-ldโ this one uses options specific to GNU ld ๐ฆ and passes-sharedto ld when you build a shared library. It's the default when GCC is configured (explicitly or implicitly) with the GNU linker. Just so you know, it doesn't change which ld gets called. It only changes the parameters that get passed to it ๐- The ld that gets called is decided by the
--with-ldconfigure option, then GCC's program search path, and finally yourPATH. - You can print the linker GCC uses with which
gcc -print-prog-name=ld. - This option is only available on the 64-bit HP-UX GCC, i.e. configured with
hppa*64*-*-hpux*.
- The ld that gets called is decided by the
-mhp-ldโ the HP version of the GNU ld vibe ๐ It passes-bto ld when building a shared library and passes+Accept TypeMismatchto ld on all links. It's the default when GCC is configured (explicitly or implicitly) with the HP linker ๐ธ- Same deal as above: this doesn't change which ld is called, only the parameters passed to it.
- The ld that is called is determined by the
--with-ldconfigure option, GCC's program search path, and finally by the user'sPATH. - The linker GCC uses can be printed using which
gcc -print-prog-name=ld. - This option is only available on the 64-bit HP-UX GCC, i.e. configured with
hppa*64*-*-hpux*.
-mlinker-optโ enables the optimization pass in the HP-UX linker ๐ฅ
โ ๏ธ bestie, this makes symbolic debugging impossible ๐ญ It also triggers a bug in the HP-UX 8 and HP-UX 9 linkers, where they give bogus error messages when linking some programs. Not it. ๐
-mlong-callsโ generates code that uses long call sequences ๐ This makes sure a call can always reach linker-generated stubs โจ By default, long calls are only generated when the distance from the call site to the beginning of the function or translation unit (whichever applies) goes over a predefined limit set by the branch type being used.- The limits for normal calls are 7,600,000 and 240,000 bytes, respectively, for the PA 2.0 and PA 1.X architectures. Sibcalls are always limited at 240,000 bytes.
- Distances are measured from the beginning of functions when using the
-ffunction-sectionsoption, or when using the-mgasand-mno-portable-runtimeoptions together under HP-UX with the SOM linker. - It's normally not desirable to use this option, since it degrades performance ๐ However, it may be useful in large applications, particularly when partial linking is used to build the application ๐งฉ
- The types of long calls used depend on the capabilities of the assembler and linker, and on the type of code being generated. The impact on systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, should be relatively small. However, 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 are sometimes required by the HP-UX 10 linker ๐ ๏ธ This is equivalent to the+koption to the HP compilers.-mjump-in-delayโ this one is ignored and only here for compatibility purposes ๐ซถ-mno-space-regsโ generates code that assumes the target has no space registers ๐ This lets GCC generate faster indirect calls and use unscaled index address modes. Such code is suitable for level 0 PA systems and kernels ๐-morderedโ assumes memory references are ordered, so barriers are not 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 for cpu-type are 700 7100, 7100LC, 7200, 7300 and 8000. If you want to figure out the right scheduling option for your machine, check out/usr/lib/sched.modelson an HP-UX system ๐ The default scheduling is 8000.-msioโ generates the predefine_SIOfor server IO ๐ฅ๏ธ The default is-mwsio. This generates the predefines__hp9000s700,__hp9000s700__and_WSIOfor workstation IO. These options are available under HP-UX and HI-UX ๐-msoft-floatโ generates output containing library calls for floating point ๐
โ ๏ธ the requisite libraries are not available for all HPPA targets. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation ๐ฌ
Also, -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 UNIX standard you pick ๐ The choices for unix-std are 93, 95 and 98. 93 is supported on all HP-UX versions. 95 is available on HP-UX 10.10 and later. 98 is available on HP-UX 11.11 and later. The defaults are 93 for HP-UX 10.00, 95 for HP-UX 10.10 through 11.00, and 98 for HP-UX 11.11 and later ๐๏ธ-munix=93provides the same predefines as GCC 3.3 and 3.4.-munix=95provides additional predefines for"XOPEN_UNIX"and"_XOPEN_SOURCE_EXTENDED", and the startfileunix95.o.-munix=98provides additional predefines for"_XOPEN_UNIX","_XOPEN_SOURCE_EXTENDED","_INCLUDE__STDC_A1_SOURCE"and"_INCLUDE_XOPEN_SOURCE_500", and the startfileunix98.o.
๐จ this option changes the interfaces for various library routines, and it also affects the operational behavior of the C library. Thus, extreme care is needed when using it, bestie ๐
Library code that is 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 ๐ฅบ
-nolibdldโ suppresses the generation of link options that searchlibdld.slwhen-staticis specified on HP-UX 10 and later ๐ โโ๏ธ-staticโ okay so the HP-UX 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.slwhen-staticis specified. This causes the resulting binary to be dynamic. On the 64-bit port, the linkers generate dynamic binaries by default in any case. - The
-nolibdldoption can be used to stop the GCC driver from adding these link options.
- On HP-UX 10 and later, the GCC driver adds the necessary options to link with
-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. Use with caution, babe.
-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, and honestly it's giving clarity ๐ง-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 for"sqrt"๐ซ-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 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 does not always do so ๐คทโโ๏ธ-mfixed-range=register-rangeโ okay so this one tells the compiler to treat the register range you give it as fixed registers ๐. A fixed register is one the register allocator isn't allowed to touch. It's super useful when you're compiling kernel code ๐ป. You write a range as two registers joined by a dash, and you can list several ranges separated by commas โจ.-mtls-size=tls-sizeโ this sets the bit size of immediate TLS offsets ๐. The valid values are14,22, and64.-mtune=cpu-typeโ tunes the instruction scheduling for one particular CPU ๐ฆ. The valid values areitanium,itanium1,merced,itanium2, andmckinley.-milp32,-mlp64โ these make code for a 32-bit or 64-bit environment ๐ธ. The 32-bit one setsint,long, and pointers to 32 bits. The 64-bit one setsintto 32 bits andlongand pointers to 64 bits. Heads up: these are HP-UX specific flags ๐.-mno-sched-br-data-spec,-msched-br-data-specโ the-mno-one disables data speculative scheduling before reload and the plain one turns it on ๐ . When it's on you getld.ainstructions plus their check instructions (ld.c/chk.a). It's disabled by default.-msched-ar-data-spec,-mno-sched-ar-data-specโ plain turns on data speculative scheduling after reload, and-mno-turns it off ๐ฅ. This also gives yould.ainstructions with the matching check instructions (ld.c/chk.a). It's enabled by default โจ.-mno-sched-control-spec,-msched-control-specโ the-mno-one disables control speculative scheduling and plain turns it on ๐ง . It only works during region scheduling (aka before reload). When it's active you getld.sinstructions pluschk.scheck instructions. It's disabled by default.-msched-br-in-data-spec,-mno-sched-br-in-data-specโ plain enables and-mno-disables speculative scheduling of instructions that depend on data speculative loads before reload ๐. This only does anything if-msched-br-data-specis turned on. It's enabled by default.-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ same vibe, but for after reload ๐. Plain enables it and-mno-disables it. It only matters when-msched-ar-data-specis enabled, and it's enabled by default.-msched-in-control-spec,-mno-sched-in-control-specโ plain enables and-mno-disables speculative scheduling of instructions that depend on control speculative loads โญ. It's only effective when-msched-control-specis enabled, and the default is enabled.-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ if you turn the plain one on, data-speculative instructions only get picked for scheduling when there are no other choices at the moment ๐. This makes data speculation way more conservative. It's disabled by default.-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ same energy, but for control-speculative instructions ๐. Turn on the plain one and they're only scheduled when nothing else is available, which makes control speculation much more conservative. It's disabled by default.-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ if the plain one is enabled, speculative dependencies get counted when the instruction priorities are computed ๐งฎ. That makes speculation a bit more conservative. It's disabled by default.-msched-spec-ldcโ uses a simple data speculation check ๐ซถ. It's on by default.-msched-control-spec-ldcโ uses a simple check for control speculation ๐ธ. It's on by default too.-msched-stop-bits-after-every-cycleโ places a stop bit after every cycle when scheduling โน๏ธ. It's on by default.-msched-fp-mem-deps-zero-costโ assumes floating-point stores and loads won't likely conflict when they end up in the same instruction group ๐ค. It's 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โ puts a limit on how many memory insns can go in one instruction group ๐ง. Later memory insns trying to schedule into the same group get lower priority. This is often handy for stopping cache bank conflicts ๐. The default value is1.-msched-max-memory-insns-hard-limitโ turns themsched-max-memory-insnslimit into a hard limit ๐ซ, so you can't go over that number in an instruction group. Without it, the limit is "soft", which means non-memory operations get preferred once the limit is hit, but memory operations can still get scheduled ๐ท.
๐ LM32 Options
These -m options are defined for the LatticeMico32 architecture ๐:
-mbarrel-shift-enabledโ enables barrel-shift instructions ๐.-mdivide-enabledโ enables divide and modulus instructions โ.-mmultiply-enabledโ enables multiply instructions โ๏ธ.-msign-extend-enabledโ enables sign extend instructions โ.-muser-enabledโ enables user-defined instructions ๐งโ๐ป.
๐ง LoongArch Options
These command-line options are defined for LoongArch targets ๐:
-march=cpu-typeโ tells GCC to generate instructions for a specific machine type ๐. Here's the tea:-mtune=cpu-typeonly tunes the code for that CPU, but-march=cpu-typelets GCC generate code that might not run at all on other processors ๐ญ. Specifying-march=cpu-typeimplies-mtune=cpu-type, unless noted otherwise. The choices forcpu-typeare:nativeโ picks the CPU to generate code for at compile time by checking the processor type of the machine doing the compiling ๐ฅ๏ธ.-march=nativeenables every instruction subset the local machine supports, so the result might not run on other machines.-mtune=nativegives code optimized for the local machine within the limits of the chosen instruction set.loongarch64โ a generic CPU with 64-bit extensions ๐.la464โ the LoongArch LA464 CPU, with LBT, LSX, LASX, and LVZ ๐ .
-mtune=cpu-typeโ optimizes the output for the given processor, specified by its microarchitecture name ๐ฏ.-mabi=base-abi-typeโ generates code for the calling convention you pick ๐.base-abi-typecan 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 andlong 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 andlong 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 andlong intand pointers are 64 bits.
-mfpu=fpu-typeโ generates code for the FPU type you specify, which can be one of these ๐ง:64โ allows hardware floating-point instructions for 32-bit and 64-bit operations ๐ช.32โ allows hardware floating-point instructions for 32-bit operations only ๐.none,0โ stops hardware floating-point instructions from being used ๐ โโ๏ธ.
-msimd=simd-typeโ turns on LoongArch SIMD instructions for vectorization and builtin functions โก. The value can be one of:lasxโ enables generating instructions from the 256-bit LoongArch Advanced SIMD Extension (LASX) and the 128-bit LoongArch SIMD Extension (LSX) ๐ฆ.lsxโ enables generating 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 one may change the target ABI.-msingle-floatโ forces-mfpu=32and lets you use 32-bit floating-point registers for parameter passing ๐ฆ. This one may change the target ABI too.-mdouble-floatโ forces-mfpu=64and lets you use 32/64-bit floating-point registers for parameter passing ๐. Also may change the target ABI.-mlasx,-mno-lasx,-mlsx,-mno-lsxโ these tweak the scope of the SIMD extensions (none / LSX / LASX) the compiler can use for code generation, one step at a time ๐งฉ. Enabling LASX withmlasxautomatically enables LSX, and disabling LSX withmno-lsxautomatically disables LASX. These are driver-only options. They act on the finalmsimdconfiguration and make incremental changes in the order they show up on the GCC driver's command line, which gives the final, canonicalizedmsimdoption passed to the compiler proper โจ.-mbranch-cost=nโ sets the cost of branches to roughlyninstructions ๐ฃ๏ธ.-mcheck-zero-division,-mno-check-zero-divisonโ the first one traps on integer division by zero, and the-mno-one doesn't trap โ ๏ธ. 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 are enabled by plain and disabled by-mno-๐ท. The default is-mcond-move-int.-mcond-move-float,-mno-cond-move-floatโ same deal for floating-point registers ๐ผ. Plain enables them and-mno-disables them. The default is-mcond-move-float.-mmemcpy,-mno-memcpyโ plain forces the use ofmemcpyfor non-trivial block moves, and-mno-makes sure it isn't forced ๐ง . The default is-mno-memcpy, which lets GCC inline most constant-sized copies. Setting the optimization level to-Osalso forcesmemcpy, but-mno-memcpycan override that if you set it explicitly, no matter what order the options appear on the command line ๐.-mstrict-align,-mno-strict-alignโ the plain one avoids generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification, and-mno-allows them ๐ซถ. The default is-mno-strict-align.-msmall-data-limit=numberโ puts global and static data smaller thannumberbytes into a special section (on some targets) ๐. The default value is0.-mmax-inline-memcpy-size=*n*โ okay bestie, this one tells GCC to inline all block moves (likememcpycalls or structure copies) that are less than or equal to n bytes ๐ฆโจ The default for n is1024.-mcmodel=code-modelโ lets you pick your code model ๐ The options are:tiny-staticโ not implemented yet ๐tinyโ not implemented yet ๐normalโ the text segment has to live within a 128MB addressing space, and the data segment has to live within a 2GB addressing space ๐ธmediumโ both the text segment and the data segment have to fit within a 2GB addressing space ๐ฆlargeโ not implemented yet ๐extremeโ no limits on how big the code segment and data segment can be ๐
Heads up, bestie:-mcmodel=extremedoes NOT play nicely with-fpltand/or-mexplicit-relocs=none๐
The default code model is normal ๐
-mexplicit-relocs=*style*โ this 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 ๐ง The styles are:noneโ assembler macros are always used ๐ โโ๏ธalwaysโ assembler relocation operators are always used ๐autoโ the compiler uses relocation operators where linker relaxation is impossible and it helps the code quality, and macros everywhere else ๐ซถ
The default depends on what the assembler can do when GCC gets built, plus the setting of -mrelax. It's -mexplicit-relocs=none if the assembler doesn't support relocation operators at all. It's -mexplicit-relocs=always if the assembler supports them but -mrelax isn't enabled. And it's -mexplicit-relocs=auto if the assembler supports them AND -mrelax is enabled ๐ฅ
-mexplicit-relocsโ an alias of-mexplicit-relocs=always, kept around for backward compatibility ๐-mno-explicit-relocsโ an alias of-mexplicit-relocs=none, also kept for backward compatibility ๐-mdirect-extern-access,-mno-direct-extern-accessโ this one controls 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 is skipped completely and every external symbol gets PC-relative addressing. This is only suitable where no dynamic linking happens, like firmware, OS kernels, or executables linked with-staticor-static-pie๐ And-mdirect-extern-accessis not compatible with-fPICor-fpic.-mrelax,-mno-relaxโ takes (or doesn't take) advantage of linker relaxations โจ If-mpass-mrelax-to-asis enabled, this option gets passed to the assembler too. The default gets figured out when GCC is built, by checking what the assembler supports. It's-mrelaxif the assembler supports both the-mrelaxoption AND conditional branch relaxation. That second part is required, otherwise the.aligndirectives and conditional branch instructions in GCC's assembly output might get rejected by the assembler because of a relocation overflow ๐ญ Otherwise the default is-mno-relax.-mpass-mrelax-to-as,-mno-pass-mrelax-to-asโ passes (or doesn't pass) the-mrelaxor-mno-relaxoption to the assembler ๐ฆ The default is found at GCC build-time too. It's-mpass-mrelax-to-asif the assembler supports the-mrelaxoption, and-mno-pass-mrelax-to-asotherwise. This one is mostly useful for debugging, or for playing nice with assemblers that aren't the same one used at build-time ๐-mrecipโ this turns on the reciprocal estimate and reciprocal square root estimate instructions, with extra Newton-Raphson steps to boost precision ๐งฎ It's used instead of doing a divide, or a square root and then a 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, make sure the target CPU supports thefrecipeandfrsqrteinstructions ๐ The sequence has higher throughput than the non-reciprocal instruction, BUT the precision can drop by up to 2 ulp (i.e. the inverse of1.0comes out as0.99999994) ๐-mrecip=*opt*โ this controls which reciprocal estimate instructions are allowed to be used ๐ opt is a comma-separated list of options, and any of them can get a!in front to invert it. The choices are:allโ enables every estimate instruction ๐ฅdefaultโ enables the default instructions, same as-mrecip๐ธnoneโ disables all estimate instructions, same as-mno-recip๐ โโ๏ธdivโ enables the approximation for scalar division โจvec-divโ enables the approximation for vectorized division ๐งsqrtโ enables the approximation for scalar square root ๐ฆvec-sqrtโ enables the approximation for vectorized square root ๐rsqrtโ enables the approximation for scalar reciprocal square root ๐ซถvec-rsqrtโ enables the approximation for vectorized reciprocal square root ๐
So for example, -mrecip=all,!sqrt turns on ALL of the reciprocal approximations EXCEPT scalar square root ๐ญ
-mfrecipe,-mno-frecipeโ uses (or doesn't use) thefrecipe.{s/d}andfrsqrte.{s/d}instructions ๐ When you build with-march=la664, this is enabled by default. The default otherwise is-mno-frecipe๐-mdiv32,-mno-div32โ uses (or doesn't use) thediv.w[u]andmod.w[u]instructions with input that is NOT sign-extended ๐ง When you build with-march=la664, it's enabled by default. The default otherwise is-mno-div32โจ-mlam-bh,-mno-lam-bhโ uses (or doesn't use) theam{swap/add}[_db].{b/h}instructions ๐ธ When you build with-march=la664, it's enabled by default. The default is-mno-lam-bh๐-mlamcas,-mno-lamcasโ uses (or doesn't use) theamcas[_db].{b/h/w/d}instructions ๐ฅ When you build with-march=la664, it's enabled by default. The default is-mno-lamcas๐ฆ-mld-seq-sa,-mno-ld-seq-saโ decides whether a load-load barrier (dbar 0x700) is needed ๐ง When you build 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 can be used for the general dynamic and local dynamic TLS models ๐ The choices are:tradโ uses traditional TLS, and this is the default โจdescโ uses TLS descriptors ๐
loongarch-vect-unroll-limitโ the vectorizer uses the available tuning info to figure out whether it'd be worth unrolling the main vectorized loop, and by how much ๐ง This sets the upper bound on how much the vectorizer will unroll the main loop. The default value issix๐
๐ธ M32C Options ๐ธ
-mcpu=nameโ picks the CPU that code gets generated for ๐ name can be one ofr8cfor 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 stuff like file I/O, for example.
Warning, bestie: do NOT use this option when generating programs that will run on real hardware ๐ You have to provide your own runtime library for whatever I/O functions you need.
-memregs=*number*โ specifies 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 penalty of using memory instead ๐ Every module in a program has to be compiled with the same value for this option. Because of that, you must NOT use this option with GCC's default runtime libraries ๐
๐ฆ M32R/D Options ๐ฆ
These -m options are defined for Renesas M32R/D architectures ๐ง
-m32r2โ generates code for the M32R/2 ๐ธ-m32rxโ generates code for the M32R/X ๐-m32rโ generates code for the M32R ๐ This is the default โจ-mmodel=smallโ assumes all objects live in the lower 16MB of memory, so their addresses can be loaded with theld24instruction, and assumes all subroutines are reachable with theblinstruction ๐ซถ This is the default โจ
The addressability of a particular object can be set with the model attribute ๐
-mmodel=mediumโ assumes objects may be anywhere in the 32-bit address space (the compiler generatesseth/add3instructions to load their addresses), and assumes all subroutines are reachable with theblinstruction ๐-mmodel=largeโ assumes objects may be anywhere in the 32-bit address space (the compiler generatesseth/add3instructions to load their addresses), and assumes subroutines may NOT be reachable with theblinstruction ๐ข In that case the compiler generates the much slowerseth/add3/jlinstruction sequence ๐ญ-msdata=noneโ disables use of the small data area ๐ โโ๏ธ Variables get put into one of.data,.bss, or.rodata(unless thesectionattribute has been 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 ๐ง
-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 to num bytes into the small data or BSS sections, instead of the normal data or BSS sections ๐ฆ The default value of num is8. The-msdataoption has to be set to eithersdataorusefor this option to do anything โจ
All modules should be compiled with the same -G num value ๐ซถ Compiling with different values of num may or may not work. If it doesn't, the linker gives an error message, so incorrect code is NOT generated ๐ก๏ธ
-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โ Skip the 32-byte alignment for loops ๐ This is already the default, so you're basically set โจ-missue-rate=numberโ Tells the compiler how many instructions to issue per cycle ๐ฅnumbercan only be1or2, no other vibes allowed.-mbranch-cost=numberโnumbercan only be1or2๐ธ If it's1, branches get the VIP pass over conditional code. If it's2, it's the opposite.-mflush-trap=numberโ Picks the trap number used to flush the cache ๐ง The default is12, and valid numbers are0through15inclusive.-mno-flush-trapโ Says the cache can't be flushed by using a trap ๐-mflush-func=nameโ Names the operating system function to call for flushing the cache ๐ The default is_flush_cache, but the function call only gets used if a trap isn't available.-mno-flush-funcโ Says there's no OS function for flushing the cache ๐
โจ M680x0 Options โจ
These are the -m options for M680x0 and ColdFire processors ๐ฆ The defaults depend on which architecture was picked when the compiler was configured, so the defaults for the most common choices are listed below.
-march=archโ Generates code for a specific M680x0 or ColdFire instruction set architecture ๐ For M680x0, the allowed values ofarchare68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures get picked using Freescale's ISA classification, and the allowed values areisaa,isaaplus,isabandisac.
GCC defines the macro __mcfarch__ whenever it's generating code for a ColdFire target ๐ง The arch in that macro is one of the -march arguments from above.
When you use -march and -mtune together, you get code that runs on a whole family of similar processors but is optimized for one particular microarchitecture โจ
-mcpu=cpuโ Generates code for a specific M680x0 or ColdFire processor ๐ The M680x0 cpus are68000,68010,68020,68030,68040,68060,68302,68332andcpu32. The ColdFire cpus are in the table below, which also sorts them into families:
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
-mcpu=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 still 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 relatively well on 68020, 68030 and 68040 targets ๐ -mtune=68020-60 is similar, but it also includes 68060 targets. These two options select the same tuning decisions as -m68020-40 and -m68020-60 respectively.
GCC defines the macros __mcarch and __mcarch__ when tuning for 680x0 architecture arch. It also defines mcarch unless either -ansi or a non-GNU -std option is used. If GCC is tuning for a range of architectures, as selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in that range ๐ซถ
GCC also defines the macro __muarch__ when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments listed above ๐
-m68000,-mc68000โ Generates output for a 68000 ๐ This is the default when the compiler is configured for 68000-based systems, and it's equivalent to-march=68000.
Use this 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 would 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 would 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 one 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 one 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 (e.g. 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 can run relatively efficiently on a 68020/68881, a 68030 or a 68040. The generated code does use the 68881 instructions that get emulated on the 68040.
The 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 can run relatively efficiently on a 68020/68881, a 68030 or a 68040. The generated code does use the 68881 instructions that get emulated on the 68060.
The 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; 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 specified by-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โ Treats type "int" as 16 bits wide, like "short int" ๐ฆ Parameters passed on the stack are also aligned to a 16-bit boundary, even on targets whose API mandates promotion to 32-bit.-mno-shortโ Doesn't treat type "int" as 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 โจ Functions that take a fixed number of arguments return with the "rtd" instruction, which pops their arguments while returning. This 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 is 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, bestie, so you only get it if you ask. ๐
-malign-int,-mno-align-intโ Okay so this one decides whetherint,long,long long,float,double, andlong doublevariables get lined up on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int). The 32-bit version runs somewhat faster on processors with 32-bit busses, but it eats more memory. Trade-offs, babe ๐ง
โ ๏ธ Warning: if you use -malign-int, GCC lines up structures containing those types differently than most published application binary interface specifications for the m68k. Not me being dramatic, this is a real heads-up ๐
-mpcrelโ Uses the 68000's pc-relative addressing mode directly, so there's no global offset table. For now this implies-fpic, which allows at most a 16-bit offset for pc-relative addressing.-fPICisn't supported alongside-mpcrelyet, though it could be for 68020 and higher processors ๐ธ-mno-strict-align,-mstrict-alignโ Doesn't assume (-mno-strict-align) or does assume (-mstrict-align) that the system handles unaligned memory references for you ๐ซถ-msep-dataโ Generates code where the data segment can live in a totally different area of memory from the text segment. This is what makes execute-in-place work 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. That means execute-in-place and shared libraries, again without virtual memory management. It implies-fPICโจ-mno-id-shared-libraryโ Generates code that doesn't assume ID-based shared libraries are in use. This is the default ๐-mshared-library-id=nโ Sets the identification number of the ID-based shared library being compiled. Using0gives you more compact code. Other values force that number onto the current library, but it's no more space- or time-efficient than skipping this option ๐-mxgot,-mno-xgotโ When you're making position-independent code for ColdFire,-mxgotgenerates code that still works if the GOT has more than 8192 entries. It's bigger and slower than the normal stuff. On M680x0 processors you don't need it, since-fPICis enough ๐
GCC normally loads values from the GOT with a single instruction. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger and the linker throws an error that looks something 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 built with -mxgot is less efficient, because 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 linkers need it, honestly iykyk ๐
These options have no effect unless GCC is generating position-independent code.
-mlong-jump-table-offsetsโ Uses 32-bit offsets in"switch"tables. The default is 16-bit offsets ๐ฅ
โจ MCore Options โจ
These are the -m options defined for the Motorola M*Core processors. Main character energy ๐
-mhardlit,-mno-hardlitโ Inlines constants into the code stream if it can be done in two instructions or less ๐ธ-mdiv,-mno-divโ Uses the divide instruction. (Enabled by default). โจ-mrelax-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 already been provided, so it leaves the simulator library (libsim.a) 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 trigger a segmentation fault if the stack gets extended too much. The default value is0x1000๐ญ
โจ MicroBlaze Options โจ
-msoft-floatโ Uses software emulation for floating point (default) ๐ธ-mhard-floatโ Uses hardware floating-point instructions ๐ฅ-mmemcpyโ Doesn't optimize block moves, and uses"memcpy"instead ๐-mno-clearbssโ Deprecated. Use-fno-zero-initialized-in-bssinstead ๐-mcpu=cpu-typeโ Uses the 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,v6.00.aโจ-mxl-soft-mulโ Uses software multiply emulation (default) ๐-mxl-soft-divโ Uses software emulation for divides (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โ 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. The valid models are:executableโ normal executable (default), uses the startup codecrt0.o.xmdstubโ for use with the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent calledxmdstub. This uses the startup filecrt1.oand sets the start address of the program to0x800.bootstrapโ for applications that are loaded using a bootloader. This model uses the startup filecrt2.o, which does not contain a processor reset vector handler. It's suitable for handing control to the bootloader on a processor reset instead of the application ๐งnovectorsโ for applications that don't need any of the MicroBlaze vectors. This can be useful for apps running inside a monitoring application. This model usescrt3.oas its startup file ๐ฆ
Heads up: -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 be 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 are: mips1, mips2, mips3, mips4, mips32, mips32r2, mips32r3, mips32r5, mips32r6, mips64, mips64r2, mips64r3, mips64r5 and mips64r6.
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 selects the most compatible architecture for the selected ABI (that is, mips1 for 32-bit ABIs and mips3 for 64-bit ABIs) ๐
The native Linux/GNU toolchain also supports the value native, which selects the best architecture option for the host processor. -march=native has no effect if GCC does not recognize the processor ๐ฅ
In processor names, a final 000 can be abbreviated as k (for example, -march=r2k). Prefixes are optional, and vr may be written r ๐ฆ
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core, names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core, and names of the form nf3_2 refer to processors with FPUs clocked at a ratio of 3:2 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 does not 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 is all about tuning for one specific chip ๐ It optimizes forarch, and among other things it controls how instructions get scheduled and the perceived cost of arithmetic operations. The list ofarchvalues is the same as for-march.
When you skip this flag, GCC optimizes for whatever processor -march picked. Using -march and -mtune together is the move if you want code that runs on a whole family of processors but gets optimized for one particular member of that family ๐ฆ
-mtune also defines the macros _MIPS_TUNE and _MIPS_TUNE_foo, which work the same way as the -march ones we covered above โจ
-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 this is the MIPS16 toggle ๐ง-mips16makes GCC generate MIPS16 code, and-mno-mips16says "absolutely not" to it. If you're targeting MIPS32 or MIPS64, GCC uses the MIPS16e ASE to get there.
MIPS16 generation can also be controlled per function with the "mips16" and "nomips16" attributes, so you can be extra specific about which functions get the treatment ๐
-mmips16e2,-mno-mips16e2โ use (or don't use) the MIPS16e2 ASE. This one changes how-mips16behaves, because it makes that flag target the MIPS16e2 ASE instead ๐-mflip-mips16โ generates MIPS16 code on alternating functions. This is only here for regression testing of mixed MIPS16/non-MIPS16 code generation, so please don't use it for your everyday code. It is not intended for ordinary use in compiling user code ๐-minterlink-compressed,-mno-interlink-compressedโ require (or don't require) that code using the standard (uncompressed) MIPS ISA be link-compatible with MIPS16 and microMIPS code, and the other way around too ๐
For example, code using the standard ISA encoding can't jump directly to MIPS16 or microMIPS code. It has to use a call or an indirect jump instead. So -minterlink-compressed disables direct jumps unless GCC knows the jump 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 hang around for backwards compatibility ๐ง-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generate code for the ABI you pick ๐
Heads up: the EABI comes in a 32-bit and a 64-bit variant. GCC normally makes 64-bit code when you pick a 64-bit architecture, but if you want 32-bit code anyway, use -mgp32 ๐ซถ
If you want the details on the O64 ABI, check out <https://gcc.gnu.org/projects/mipso64-abi.html> ๐
GCC also supports a version of the o32 ABI where the floating-point registers are 64 bits wide instead of 32. You get this combo with -mabi=32 -mfp64. This ABI depends on the mthc1 and mfhc1 instructions, so it's only supported for MIPS32R2, MIPS32R3, and MIPS32R5 processors ๐ฅ
The register assignments for arguments and return values stay the same, but each scalar value rides in a single 64-bit register instead of a pair of 32-bit ones. So for example, scalar floating-point values get returned in $f0 only, not a $f0/$f1 pair. The set of call-saved registers also stays the same, meaning the even-numbered double-precision registers are the ones that get saved โจ
Two more variants of the o32 ABI exist to help with the jump from 32-bit to 64-bit registers. They're FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg) ๐ฆ The FPXX extension says all code has to run correctly with 32-bit or 64-bit registers. It can be interlinked with either FP32 or FP64, but never both at once. FP64A is kind of like FP64, except it forbids the use of odd-numbered single-precision registers. It can be paired with the "FRE" mode of FPUs in MIPS32R5 processors, which lets FP32 and FP64A code interlink and run in the same process without changing FPU modes ๐
-mabicalls,-mno-abicallsโ generate (or don't generate) code that works with SVR4-style dynamic objects.-mabicallsis the default on SVR4-based systems ๐-mshared,-mno-sharedโ generate (or don't generate) code that's fully position-independent, so it can be linked into shared libraries. This option only affects-mabicalls๐ง
All -mabicalls code has traditionally been position-independent, no matter what you pass like -fPIC or -fpic. BUT, as an extension, the GNU toolchain lets executables use absolute accesses for locally-binding symbols. It can also use shorter GP initialization sequences and generate direct calls to locally-defined functions. That mode gets selected by -mno-shared ๐
-mno-shared depends on binutils 2.16 or higher, and it generates objects that can only be linked by the GNU linker. The good news is it doesn't change the ABI of the final executable. It only changes the ABI of relocatable objects. Using -mno-shared generally makes executables both smaller and quicker ๐๏ธ
-mshared is the default โจ
-mplt,-mno-pltโ assume (or don't assume) that the static and dynamic linkers support PLTs and copy relocations. This only affects-mno-shared -mabicalls. For the n64 ABI, this option does nothing without-msym32๐คทโโ๏ธ
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt ๐
-mxgot,-mno-xgotโ lift (or don't lift) the usual restrictions on the size of the global offset table ๐ธ
GCC normally uses a single instruction to load values from the GOT. It's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker report an error like this:
relocation truncated to fit: R_MIPS_GOT16 foobar
If that happens, recompile your code with -mxgot. It works with very large GOTs, but the code is less efficient because it takes three instructions to fetch the value of a global symbol ๐ญ
Some linkers can create multiple GOTs. If you have one of those, you should only need -mxgot when a single object file accesses more than 64k's worth of GOT entries. Very few linkers do that, honestly ๐
These options have no effect 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 anything about the width of floating-point registers ๐ฆ-mhard-floatโ use the floating-point coprocessor instructions ๐ช-msoft-floatโ don't use the floating-point coprocessor instructions. Floating-point math gets done with library calls instead ๐-mno-floatโ same as-msoft-float, but it also swears that the program being compiled does zero floating-point operations ๐ โโ๏ธ Right now this is only supported by some bare-metal MIPS configurations, where it might pick a special set of libraries that have no floating-point support at all. That includes stuff like the floating-point"printf"formats.
If code compiled with -mno-float accidentally has floating-point operations in it, it's likely to fail at link time or at run time. Be careful, bestie ๐
-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โ enable (or disable) the use of odd-numbered single-precision floating-point registers for the o32 ABI. Enabled is the default for processors known to support these registers. When you're using the o32 FPXX ABI,-mno-odd-spreggets set by default ๐ง-mabs=2008,-mabs=legacyโ these control how the special not-a-number (NaN) IEEE 754 floating-point data gets treated by theabs.fmtandneg.fmtmachine instructions ๐
By default, or when you use -mabs=legacy, you get the legacy treatment. Here those instructions count as arithmetic, so GCC avoids them wherever correct operation matters and the input might be a NaN. Instead it uses a longer sequence of instructions that manually manipulates the sign bit of the floating-point datum, unless -ffinite-math-only was also specified ๐ซ
-mabs=2008 selects the IEEE 754-2008 treatment. In this case those instructions count as non-arithmetic, so they work correctly in all cases, including when the input operand is a NaN. That means these instructions are always used for the respective operations ๐ฅ
-mnan=2008,-mnan=legacyโ these control how the special not-a-number (NaN) IEEE 754 floating-point data gets encoded ๐
-mnan=legacy selects the legacy encoding. Here, quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, while signaling NaNs (sNaNs) are marked by that first bit being 1 ๐
-mnan=2008 selects the IEEE 754-2008 encoding. Here, qNaNs are marked by the first bit of their trailing significand field being 1, while sNaNs are marked by that first bit being 0 โจ
The default is -mnan=legacy, unless GCC was configured with --with-nan=2008 ๐
-mllsc,-mno-llscโ use (or don't use) thell,sc, andsyncinstructions to implement the atomic memory built-in functions. If you specify neither option, GCC uses those instructions as long as the target architecture supports them ๐
Okay so -mllsc is clutch when the runtime can emulate those instructions, and -mno-llsc slays when you're compiling for nonstandard ISAs ๐ง. You can make either one the default by configuring GCC with --with-llsc or --without-llsc, respectively. Heads up: --with-llsc is already the default for some configurations, so check the installation docs for the deets ๐.
-mdsp,-mno-dspโ Use (do not use) revision 1 of the MIPS DSP ASE ๐- This option defines the preprocessor macro
__mips_dsp. It also defines__mips_dsp_revto 1.
- This option defines the preprocessor macro
-mdspr2,-mno-dspr2โ Use (do not use) revision 2 of the MIPS DSP ASE โจ- This option defines the preprocessor macros
__mips_dspand__mips_dspr2. It also defines__mips_dsp_revto 2.
- This option defines the preprocessor macros
-msmartmips,-mno-smartmipsโ Use (do not use) the MIPS SmartMIPS ASE ๐-mpaired-single,-mno-paired-singleโ Use (do not use) paired-single floating-point instructions ๐ฆ- This option requires hardware floating-point support to be enabled.
-mdmx,-mno-mdmxโ Use (do not use) MIPS Digital Media Extension instructions ๐ธ- This option can only be used when generating 64-bit code and requires hardware floating-point support to be enabled.
-mips3d,-mno-mips3dโ Use (do not use) the MIPS-3D ASE ๐ง- The option
-mips3dimplies-mpaired-single.
- The option
-mmicromips,-mno-micromipsโ Generate (do not generate) microMIPS code ๐- MicroMIPS code generation can also be controlled on a per-function basis by means of
micromipsandnomicromipsattributes.
- MicroMIPS code generation can also be controlled on a per-function basis by means of
-mmt,-mno-mtโ Use (do not use) MT Multithreading instructions ๐ซถ-mmcu,-mno-mcuโ Use (do not use) the MIPS MCU ASE instructions ๐-meva,-mno-evaโ Use (do not use) the MIPS Enhanced Virtual Addressing instructions ๐-mvirt,-mno-virtโ Use (do not use) the MIPS Virtualization (VZ) instructions ๐-mxpa,-mno-xpaโ Use (do not use) the MIPS eXtended Physical Address (XPA) instructions โญ-mcrc,-mno-crcโ Use (do not use) the MIPS Cyclic Redundancy Check (CRC) instructions ๐-mginv,-mno-ginvโ Use (do not use) the MIPS Global INValidate (GINV) instructions ๐ฅ-mloongson-mmi,-mno-loongson-mmiโ Use (do not use) the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐-mloongson-ext,-mno-loongson-extโ Use (do not use) the MIPS Loongson EXTensions (EXT) instructions ๐ฆ-mloongson-ext2,-mno-loongson-ext2โ Use (do not use) the MIPS Loongson EXTensions r2 (EXT2) instructions ๐ธ-mlong64โ Forcelongtypes to be 64 bits wide ๐- See
-mlong32for an explanation of the default and the way that the pointer size is determined.
- See
-mlong32โ Forcelong,int, and pointer types to be 32 bits wide ๐ง- The default size of
ints,longs and pointers depends on the ABI. All the supported ABIs use 32-bitints. The n64 ABI uses 64-bitlongs, as does the 64-bit EABI; the others use 32-bitlongs. Pointers are the same size aslongs, or the same size as integer registers, whichever is smaller.
- The default size of
-msym32,-mno-sym32โ Assume (do not assume) that all symbols have 32-bit values, regardless of the selected ABI ๐- This option is useful in combination with
-mabi=64and-mno-abicallsbecause it allows GCC to generate shorter and faster references to symbolic addresses.
- This option is useful in combination with
-G numโ Put definitions of externally-visible data in a small data section if that data is no bigger than num bytes ๐- GCC can then generate more efficient accesses to the data; see
-mgpoptfor details. - The default
-Goption depends on the configuration.
- GCC can then generate more efficient accesses to the data; see
-mlocal-sdata,-mno-local-sdataโ Extend (do not extend) the-Gbehavior to local data too, such as to static variables in C โจ-mlocal-sdatais the default for all configurations.- If the linker complains that an application is using too much small data, you might want to try rebuilding the less performance-critical parts with
-mno-local-sdata. You might also want to build large libraries with-mno-local-sdata, so that the libraries leave more room for the main program.
-mextern-sdata,-mno-extern-sdataโ Assume (do not assume) that externally-defined data is in a small data section if the size of that data 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-Gsetting or attach asectionattribute to Var's definition. If Var is common, you must link the application with a high-enough-Gsetting. - The easiest way of satisfying these restrictions is to compile and link every module with the same
-Goption. However, you may wish to build a library that supports several different small data limits. You can do this by compiling the library with the highest supported-Gsetting and additionally using-mno-extern-sdatato stop the library from making assumptions about externally-defined data.
-mgpopt,-mno-gpoptโ Use (do not 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-gpoptis useful for cases where the$gpregister 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 such situations, the boot monitor itself is usually compiled with-G0.)-mno-gpoptimplies-mno-local-sdataand-mno-extern-sdata.
-membedded-data,-mno-embedded-dataโ Allocate variables to the read-only data section first if possible, then next in the small data section if possible, otherwise in data ๐ธ- This gives slightly slower code than the default, but reduces the amount of RAM required when executing, and thus may be preferred for some embedded systems.
-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ Put uninitializedconstvariables in the read-only data section ๐- This option is only meaningful in conjunction with
-membedded-data.
- This option is only meaningful in conjunction with
-mcode-readable=settingโ Specify whether GCC may generate code that reads from executable sections ๐- There are three possible settings:
-mcode-readable=yesโ Instructions may 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 option is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It is 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 option can be useful on targets that are configured to have a dual instruction/data SRAM interface but that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM. ๐
- There are three possible settings:
-msplit-addresses,-mno-split-addressesโ Enable (disable) use of the%hi()and%lo()assembler relocation operators ๐- This option has been superseded by
-mexplicit-relocsbut is retained for backwards compatibility.
- This option has been superseded by
-mexplicit-relocs=none,-mexplicit-relocs=base,-mexplicit-relocs=pcrel,-mexplicit-relocs,-mno-explicit-relocsโ These options control whether explicit relocs (such as%gp_rel) are used โญ- The default value depends on the version of GAS when GCC itself was built.
- The
baseexplicit-relocs support was introduced into GAS in 2001. - The
pcrelexplicit-relocs support was introduced into GAS in 2014, and it supports%pcrel_hiand%pcrel_lo.
-mcheck-zero-division,-mno-check-zero-divisionโ Trap (do not trap) on integer division by zero ๐- The default is
-mcheck-zero-division.
- The default is
-mdivide-traps,-mdivide-breaksโ MIPS systems check for division by zero by generating either a conditional trap or abreakinstruction ๐ฅ- Using traps results in smaller code, but is only supported on MIPS II and later. Also, some versions of the Linux kernel have a bug that prevents
trapfrom generating the proper signal (SIGFPE). Use-mdivide-trapsto allow conditional traps on architectures that support them and-mdivide-breaksto force the use ofbreaks. - The default is usually
-mdivide-traps, but this can be overridden at configure time using--with-divide=breaks. Divide-by-zero checks can be completely disabled using-mno-check-zero-division.
- Using traps results in smaller code, but is only supported on MIPS II and later. Also, some versions of the Linux kernel have a bug that prevents
-mload-store-pairs,-mno-load-store-pairsโ Enable (disable) an optimization that pairs consecutive load or store instructions to enable load/store bonding ๐- This option is enabled by default but only takes effect when the selected architecture is known to support bonding.
-mstrict-align,-mno-strict-align,-munaligned-access,-mno-unaligned-accessโ Disable (enable) direct unaligned access for MIPS Release 6 ๐ฆ- MIPSr6 requires load/store unaligned-access support, by hardware or
trap&emulate. So-mstrict-alignmay be needed by kernel. - > The options
-munaligned-accessand-mno-unaligned-accessare obsoleted, and only for backward-compatible.
- MIPSr6 requires load/store unaligned-access support, by hardware or
-mmemcpy,-mno-memcpyโ Force (do not force) the use ofmemcpyfor non-trivial block moves ๐ธ- The default is
-mno-memcpy, which allows GCC to inline most constant-sized copies.
- The default is
-mlong-calls,-mno-long-callsโ Disable (do not disable) use of thejalinstruction ๐ง- Calling functions using
jalis more efficient but requires the caller and callee to be in the same 256 megabyte segment. - This option has no effect on
abicallscode. The default is-mno-long-calls.
- Calling functions using
-mmad,-mno-madโ Enable (disable) use of themad,maduandmulinstructions, as provided by the R4650 ISA ๐-mimadd,-mno-imaddโ okay so these turn themaddandmsubinteger instructions on (-mimadd) or off (-mno-imadd) ๐ The default is-mimaddon architectures that supportmaddandmsub, except the 74k architecture, where it was found to generate slower code ๐ข-mfused-madd,-mno-fused-maddโ this one enables or disables the floating-point multiply-accumulate instructions whenever they're available โจ The default is-mfused-madd.- Heads up, bestie ๐ On the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product is calculated to infinite precision and is not subject to the FCSR Flush to Zero bit. This may be undesirable in some circumstances.
- On other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions.
-nocppโ tells the MIPS assembler to skip its preprocessor when it assembles user assembler files with a.ssuffix ๐ง-mfix-24k,-mno-fix-24kโ works around the 24K E48 errata (lost data on stores during refill) ๐ ๏ธ The assembler handles these workarounds, not GCC.-mfix-r4000,-mno-fix-r4000โ works around certain R4000 CPU errata ๐ญ- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
- A double-word or a variable shift may give an incorrect result if executed while an integer multiplication is in progress.
- An integer division may give an incorrect result if started in a delay slot of a taken branch or a jump.
-mfix-r4400,-mno-fix-r4400โ works around certain R4400 CPU errata ๐ธ- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
-mfix-r10000,-mno-fix-r10000โ works around certain R10000 errata ๐"ll"/"sc"sequences may not behave atomically on revisions prior to 3.0. They may deadlock on revisions 2.6 and earlier.- This option can only be used if the target architecture supports branch-likely instructions.
-mfix-r10000is the default when-march=r10000is used;-mno-fix-r10000is the default otherwise.
-mfix-r5900,-mno-fix-r5900โ basically, don't try to schedule the preceding instruction into the delay slot of a branch sitting at the end of a short loop of six instructions or fewer. Always put anopthere instead ๐ The short loop bug can make loops run only once or twice because of a hardware bug in the R5900 chip. The assembler does this workaround, not GCC.-mfix-rm7000,-mno-fix-rm7000โ works around the RM7000dmult/dmultuerrata ๐ The assembler handles the workarounds, not 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 present, these functions are only provided by themips64vr*-elfconfigurations. - Other VR4120 errata require a NOP to be inserted between certain pairs of instructions. These are handled by the assembler, not by GCC itself.
-mfix-vr4130โ works around the VR4130mflo/mfhierrata โจ The assembler does the workarounds, 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 only works around the SB-1 revision 2"F1"and"F2"floating-point errata.)-mr10k-cache-barrier=settingโ decides whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors ๐- Like lots of processors, the R10K tries to guess the outcome of a conditional branch and speculatively runs instructions from the "taken" branch. It later aborts them if the guess was wrong. But on the R10K, even aborted instructions can leave side effects behind.
- This problem only affects kernel stores and, depending on the system, kernel loads. For example, a speculatively-executed store may load the target memory into cache and mark the cache line as dirty, even if the store itself is later aborted. If a DMA operation writes to the same area of memory before the "dirty" line is flushed, the cached data overwrites the DMA-ed data. See the R10K processor manual for a full description, including other potential problems.
- One workaround is to insert cache barrier instructions before every memory access that might be speculatively executed and that might have side effects even if aborted.
-mr10k-cache-barrier=settingcontrols GCC's implementation of 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 is the kernel's responsibility to ensure that speculative accesses to these regions are indeed safe.
- If the input program contains a function declaration such as
void foo (void);, then the implementation offoomust allowj fooandjal footo be executed speculatively. GCC honors this restriction for functions it compiles itself. It expects non-GCC functions (such as hand-written assembly code) to do the same. - The option has three forms:
-mr10k-cache-barrier=load-storeโ inserts a cache barrier before a load or store that might be speculatively executed and that might have side effects even if aborted.-mr10k-cache-barrier=storeโ inserts a cache barrier before a store that might be speculatively executed and that might have side effects even if aborted.-mr10k-cache-barrier=noneโ disables the insertion of cache barriers. This is the default setting.
-mflush-func=func,-mno-flush-funcโ picks the function to call to flush the I and D caches, or tells GCC to not call any such function ๐งน If it's 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 number 3 (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 isn't guaranteed to produce consistent results across releases. A zero cost redundantly selects the default, which is based on the-mtunesetting.-mbranch-likely,-mno-branch-likelyโ enables or disables Branch Likely instructions, no matter what the default is 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, plus processors that implement those architectures. For those, Branch Likely instructions are not generated by default, because the MIPS32 and MIPS64 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=neverensures that compact branch instructions are never generated.-mcompact-branches=alwaysensures that a compact branch instruction is generated if one is available, for MIPS Release 6 onwards. If a compact branch instruction is not available (or the target is pre-R6), a delay slot form of the branch is 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 is 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 is enabled by default at optimization level
-O3.
- 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 is enabled by default at optimization level
-msynci,-mno-synciโ enables (or disables) generation ofsynciinstructions on architectures that support it ๐ฅ Thesynciinstructions (if enabled) are 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 is 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 behavior. ๐
- This option defaults to
-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 if the destination is within range for a direct call.
Okay so -mrelax-pic-calls is the default ๐
if GCC was configured to use an assembler and a linker that support the .reloc assembly directive, and -mexplicit-relocs is in effect. With -mno-explicit-relocs, the assembler and linker can handle this optimization all on their own, no compiler help needed ๐ฆ
-mmcount-ra-address,-mno-mcount-ra-addressโ Okay, this one is giving return address drama ๐ With-mmcount-ra-address, GCC emits code that lets_mcountchange the calling function's return address. It basically extends the usual_mcountinterface with a new ra-address parameter. That parameter is typeintptr_t *and gets passed in register$12. So_mcountcan change 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 one is a lil bit of stack tidying โจ In the o32 ABI, calling functions normally reserve 16 bytes on the stack so the called function has somewhere to write out its register arguments. With-mframe-header-opt, GCC skips reserving that frame header if it can tell it's unused.-mno-frame-header-optturns that off. This optimization is off by default at all optimization levels ๐ธ-mlxc1-sxc1,-mno-lxc1-sxc1โ When it applies,-mlxc1-sxc1lets GCC generatelwxc1,swxc1,ldxc1andsdxc1instructions, and-mno-lxc1-sxc1stops it. It's enabled by default ๐ฆ-mmadd4,-mno-madd4โ When it applies,-mmadd4lets GCC generate 4-operandmadd.s,madd.dand related instructions.-mno-madd4says no thanks. Enabled by default ๐
๐ธ MMIX Options ๐ธ
These options are defined for the MMIX ๐ง
-mlibfuncs,-mno-libfuncsโ-mlibfuncssays you're compiling intrinsic library functions, so every value gets passed in registers, no matter how big it is.-mno-libfuncsis the opposite vibe ๐-mepsilon,-mno-epsilonโ-mepsilonmakes GCC generate floating-point comparison instructions that compare with respect to therEepsilon register.-mno-epsilonskips that โจ-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code where function parameters and return values are seen as registers$0and up, in the called function. The GNU ABI, on the other hand, uses global registers$231and up. Pick your fighter ๐-mzero-extend,-mno-zero-extendโ When reading data from memory in sizes shorter than 64 bits,-mzero-extenduses zero-extending load instructions by default, instead of sign-extending ones.-mno-zero-extendmeans don't use them ๐-mknuthdiv,-mno-knuthdivโ-mknuthdivmakes the remainder of a division have the same sign as the divisor. With the default,-mno-knuthdiv, the remainder's sign follows the sign of the dividend. Both methods are arithmetically valid, but the latter is the one almost everyone uses ๐งฎ-mtoplevel-symbols,-mno-toplevel-symbolsโ-mtoplevel-symbolsputs a:in front of all global symbols, so your assembly code can work with thePREFIXassembly directive.-mno-toplevel-symbolsdoesn't add the colon ๐-melfโ Generates an executable in the ELF format, instead of the default mmo format that the mmix simulator uses ๐ฆ-mbranch-predict,-mno-branch-predictโ-mbranch-predictuses the probable-branch instructions when static branch prediction says a branch is probable.-mno-branch-predictdoesn't use them ๐ฅ-mbase-addresses,-mno-base-addressesโ-mbase-addressesgenerates code that uses base addresses. Using a base address automatically makes a request, which the assembler and linker take care of, for a constant to be set up in a global register. That register then 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 might need-mno-base-addresses๐-msingle-exit,-mno-single-exitโ-msingle-exitforces the generated code to have a single exit point in each function.-mno-single-exitdoesn't force that ๐
๐ MN10300 Options ๐
These -m options are defined for Matsushita MN10300 architectures ๐
-mmult-bugโ Generates code that avoids bugs in the multiply instructions for MN10300 processors. This is the default ๐-mno-mult-bugโ Does not generate code to avoid those multiply bugs for 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. This does not change the targeted processor type. The CPU type must 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, the pointer is only returned ina0, and trying to call those functions without a prototype results in errors. Note that this option is on by default, so 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 option only has an effect when it's used on the command line for the final link step.
Heads up: this option makes symbolic debugging impossible ๐
-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โ Stops the compiler from generating Long Instruction Word instructions. This option defines the preprocessor macro__NO_LIW__๐-msetlbโ Lets the compiler generate SETLB and Lcc instructions if the target is AM33 or later. This is the default. This option defines the preprocessor macro__SETLB__๐-mno-setlbโ Stops the compiler from generating 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 these constants are signed decimals, but this option is there 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__. Themsp430.hheader file then uses that symbol to pick an MCU-specific supplementary header file ๐ง
This option also sets the ISA to use. If the MCU name is one that's known to only support the 430 ISA, that one gets selected. Otherwise, the 430X ISA is selected. The generic MCU name 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 -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 supported for the different MCUs are hard-coded into GCC. However, an external devices.csv file can extend device support beyond those hard-coded ones ๐
GCC searches for devices.csv using the methods below, in this precedence order. The first method beats the second, and the second beats the third ๐
- Include path specified with
-Iand-L:devices.csvgets searched for in each of the directories specified by include paths and linker library search paths. - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIR: Set the global environment variableMSP430_GCC_INCLUDE_DIRto the full path of the directory containingdevices.csv, and GCC will search that directory fordevices.csv. Ifdevices.csvis found there, the directory also gets registered as an include path and a linker library path. Header files and linker scripts in this directory can then be used without manually specifying-Iand-Lon the command line โจ - The
msp430-elf{,bare}/include/devicesdirectory: GCC will examinemsp430-elf{,bare}/include/devicesfrom the toolchain root directory. This directory doesn't exist in a default installation, but if you've created it and copieddevices.csvinto it, the MCU data gets read. As above, this directory also gets registered as an include path and a linker library path ๐ธ
If none of the above search methods find devices.csv, the hard-coded MCU data is used ๐
-mwarn-mcu,-mno-warn-mcuโ-mwarn-mcuturns on warnings about conflicts between the MCU name set by-mmcuand 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.-mno-warn-mcuturns all of those warnings off ๐-mcpu=โ Specifies the ISA to use. Accepted values aremsp430,msp430xandmsp430xv2.
Deprecated: this option is deprecated. The -mmcu= option should be used to select the ISA ๐
-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, with 20-bit pointers and a 20-bitsize_t๐-msmallโ Uses small-model addressing, with 16-bit pointers and a 16-bitsize_t๐-mrelaxโ This option gets passed to the assembler and linker, and it lets the linker do certain optimizations that can't happen until the final link ๐ฆ-mhwmult=โ okay so this one tells GCC what kind of hardware multiply your chip actually has ๐งฎโจ The accepted values are:noneโ no hardware multiply, bestie ๐16bitโ the original 16-bit-only multiply from the early MCUs ๐ธ32bitโ the 16/32-bit multiply on the later MCUs ๐ฅf5seriesโ the 16/32-bit multiply on F5-series MCUs ๐autoโ the default ๐ It tells GCC to figure out the hardware multiply support from the MCU name you gave to-mmcu. If you skip-mmcuor the MCU name isn't recognized, GCC assumes no hardware multiply support at all.
Hardware multiplies usually get handled by calling a library routine, which saves space in the generated code ๐ But when you compile at -O3 or higher, the hardware multiplier gets invoked inline instead. That makes the code bigger but faster, so it's a total glow-up trade-off ๐ฆ
The hardware multiply routines turn off interrupts while they run and then restore the previous interrupt state when they're done ๐ซถ That's the reason they're safe to use inside interrupt handlers as well as in normal code โจ
-minrtโ enables a minimum runtime environment, which means 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 are required ๐-mtiny-printfโ enables reduced code sizeprintfandputslibrary functions ๐ Heads up though: these tiny versions are not reentrant, so you have to be careful with them in multi-threaded apps ๐ญ
Stream support has been removed, so the string you print always goes to stdout through the write syscall. It isn't buffered before it gets sent to write ๐
This option requires Newlib Nano IO, which means GCC must be configured with --enable-newlib-nano-formatted-io ๐
-mmax-inline-shift=โ takes an integer from 0 to 64 inclusive and sets the maximum number of inline shift instructions that can be emitted for a shift by a constant amount ๐ฆ Once that limit would be exceeded, anmspabihelper function gets used instead. The default is 4 โจ
This only matters when a shift by multiple positions can't be done with one instruction, like all shifts greater than 1 on the 430 ISA ๐ Shifts of a 32-bit value are at least twice as costly, so the value you pass gets divided by 2 and that result is used instead ๐งฎ
-mcode-region=and-mdata-region=โ these tell the compiler where to put functions and data that don't have one of thelower,upper,either, orsectionattributes ๐ The possible values arelower,upper,either, orany. The first three behave like the matching attribute, andanyis the default ๐ธ Withany, placement is left entirely up to the linker script and how it assigns the standard sections (.text,.data, etc.) to the memory regions ๐ซถ-msilicon-errata=โ passes a request to the assembler to enable the fixes for the named silicon errata ๐งโจ-msilicon-errata-warn=โ passes a request to the assembler to turn on warning messages for when a silicon errata might need to be applied ๐-mwarn-devices-csvand-mno-warn-devices-csvโ warn ifdevices.csvisn't found or there are problems parsing it (default: on) ๐๐
โจ 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 reduced-set registers for register allocation ๐ฆ-mfull-regsโ uses 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 v3push25/pop25instructions ๐ง-mno-v3pushโ does not generate v3push25/pop25instructions ๐-m16-bitโ generates 16-bit instructions ๐-mno-16-bitโ does not generate 16-bit instructions ๐ธ-misr-vector-size=numโ specifies the size of each interrupt vector, which must be4or16โญ-mcache-block-size=numโ specifies the size of each cache block, which must be a power of 2 between4and512๐ง-march=archโ specifies the name of the target architecture ๐น-mcmodel=code-modelโ sets the code model to one of these:smallโ all the data and read-only data segments must be within 512KB of addressing space, and 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 ๐ซถ
โจ Nios II Options โจ
These are the options defined for the Altera Nios II processor ๐
-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 โจ-mgpopt=option,-mgpopt, and-mno-gpoptโ generate (or don't generate) GP-relative accesses ๐งญ The following option names are recognized:noneโ does not generate GP-relative accesses ๐ โโ๏ธlocalโ generates GP-relative accesses for small data objects that are not external, weak, or uninitialized common symbols. It also uses GP-relative addressing for objects that have been explicitly placed in a small data section via asectionattribute ๐ธglobalโ works likelocal, but also generates GP-relative accesses for small data objects that are external, weak, or common. If you use this option, you must make sure that all parts of your program (including libraries) are compiled with the same-Gsetting ๐ซถdataโ generates GP-relative accesses for all data objects in the program. If you use this option, the entire data and BSS segments of your program must fit in 64K of memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer ๐ฅallโ generates GP-relative addresses for function pointers as well as data pointers. If you use this option, the entire text, data, and BSS segments of your program must fit in 64K of memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer ๐
-mgpopt is equivalent to -mgpopt=local, and -mno-gpopt is equivalent to -mgpopt=none ๐ง
The default is -mgpopt unless -fpic or -fPIC is specified to generate position-independent code ๐ Note that the Nios II ABI does not permit GP-relative accesses from shared libraries ๐ญ
You may need to specify -mno-gpopt explicitly when building programs that include large amounts of small data, including large GOT data sections. In this case, the 16-bit offset for GP-relative addressing may not be large enough to allow access to the entire small data section ๐
-mgprel-sec=regexpโ specifies additional section names that can be accessed via GP-relative addressing ๐ It's most useful alongsidesectionattributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression ๐
This option doesn't affect how -G behaves. The specified sections are in addition to the standard .sdata and .sbss small-data sections that are recognized by -mgpopt ๐ฆ
-mr0rel-sec=regexpโ specifies names of sections that can be accessed via a 16-bit offset fromr0, meaning in the low 32K or high 32K of the 32-bit address space ๐ง It's most useful alongsidesectionattributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression ๐
Unlike GP-relative addressing for small data, zero-based addressing is never generated by default, and there are no conventional section names used in standard linker scripts for sections in the low or high areas of memory ๐ โโ๏ธ
-meland-mebโ generate little-endian (default) or big-endian (experimental) code, respectively ๐ท-march=archโ specifies the name of the target Nios II architecture ๐น GCC uses this name to figure out what kind of instructions it can emit when generating assembly code. The permissible names arer1andr2โจ
The preprocessor macro __nios2_arch__ is available to programs, with a value of 1 or 2, indicating the targeted ISA level ๐ง
-mbypass-cacheand-mno-bypass-cacheโ force all load and store instructions to always bypass the cache by using I/O variants of the instructions ๐ The default is not to bypass the cache ๐-mno-cache-volatileand-mcache-volatileโ volatile memory access bypasses the cache using the I/O variants of the load and store instructions ๐ง The default is not to bypass the cache ๐ฅ-mno-fast-sw-divand-mfast-sw-divโ-mno-fast-sw-divstops the use of table-based fast divide for small numbers ๐ The default is to use the fast divide at-O3and above โก-mno-hw-mul,-mhw-mul,-mno-hw-mulx,-mhw-mulx,-mno-hw-div, and-mhw-divโ enable or disable emitting themul,mulx, anddivfamily of instructions by the compiler ๐งฎ The default is to emitmuland not emitdivandmulx๐-mbmx,-mno-bmx,-mcdx, and-mno-cdxโ enable or disable generation of Nios II R2 BMX (bit manipulation) and CDX (code density) instructions ๐ฆ Enabling these instructions also requires-march=r2. Since they're optional extensions to the R2 architecture, the default is not to emit them ๐
-mcustom-insn=N, -mno-custom-insn
Okay bestie, so -mcustom-insn=N lets you hand a custom instruction with encoding N to any insn you pick ๐
For example, -mcustom-fadds=253 makes single-precision float adds use custom instruction 253 instead of the default library call. Iconic ๐ฆ
The supported values of insn are below. Unless noted otherwise, floating-point ops are expected to follow normal IEEE 754 semantics and match the C operators or the equivalent GCC built-in functions โจ
๐ Single-precision floating point
fadds,fsubs,fdivs,fmulsโ binary arithmetic ops ๐งฎfnegsโ unary negationfabssโ unary absolute valuefcmpeqs,fcmpges,fcmpgts,fcmples,fcmplts,fcmpnesโ comparisons ๐fmins,fmaxsโ floating-point min and max. These only get generated if-ffinite-math-onlyis specified ๐fsqrtsโ unary square rootfcoss,fsins,ftans,fatans,fexps,flogsโ floating-point trig and exponential functions. These only get generated if-funsafe-math-optimizationsis also specified โ ๏ธ
๐ Double-precision floating point
faddd,fsubd,fdivd,fmuldโ binary arithmetic ops ๐งฎfnegdโ unary negationfabsdโ unary absolute valuefcmpeqd,fcmpged,fcmpgtd,fcmpled,fcmpltd,fcmpnedโ comparisons ๐fmind,fmaxdโ double-precision min and max. These only get generated if-ffinite-math-onlyis specified ๐fsqrtdโ unary square rootfcosd,fsind,ftand,fatand,fexpd,flogdโ double-precision trig and exponential functions. These only get generated if-funsafe-math-optimizationsis also specified โ ๏ธ
๐ Conversions
fextsdโ single precision to double precision ๐ฆftruncdsโ double precision to single precision ๐ฆfixsi,fixsu,fixdi,fixduโ floating point to signed or unsigned integers, truncating toward zero โ๏ธroundโ single-precision float to signed integer, rounding to the nearest integer with ties going away from zero. This matches the"__builtin_lroundf"function when-fno-math-errnois used ๐floatis,floatus,floatid,floatudโ signed or unsigned integers to floating point ๐ธ
Also, ngl, every double-precision instruction needs these transfer instructions for the internal registers X and Y to be provided first ๐ซถ Custom instructions that take two double-precision source operands expect the first operand in the 64-bit register X. The other operand (or the only operand of a unary op) goes to the custom arithmetic instruction with the least significant half in source register src1 and the most significant half in src2. A custom instruction that returns a double-precision result gives back the most significant 32 bits in the destination register, and the other half lands in the 32-bit register Y. GCC handles the setup code for writing X and/or reading Y automatically whenever you use double-precision instructions, so you don't have to ๐
fwrxโ writessrc1into the least significant half ofXandsrc2into the most significant half ofXfwryโ writessrc1intoYfrdxhi,frdxloโ reads the most or least significant half ofX(respectively) and stores it indestfrdyโ readsYand stores it intodest
Note that you can get more local control over Nios II custom instruction generation with the target("custom-insn=N") and target("no-custom-insn") function attributes or pragmas ๐ฅ
-mcustom-fpu-cfg=nameโ this enables a predefined, named set of custom instruction encodings (see-mcustom-insnabove). Currently these sets are defined ๐
-mcustom-fpu-cfg=60-1 is equivalent to: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -fsingle-precision-constant
-mcustom-fpu-cfg=60-2 is equivalent to: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant
-mcustom-fpu-cfg=72-3 is equivalent to: -mcustom-floatus=243 -mcustom-fixsi=244 -mcustom-floatis=245 -mcustom-fcmpgts=246 -mcustom-fcmples=249 -mcustom-fcmpeqs=250 -mcustom-fcmpnes=251 -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant
-mcustom-fpu-cfg=fph2 is equivalent to: -mcustom-fabss=224 -mcustom-fnegs=225 -mcustom-fcmpnes=226 -mcustom-fcmpeqs=227 -mcustom-fcmpges=228 -mcustom-fcmpgts=229 -mcustom-fcmples=230 -mcustom-fcmplts=231 -mcustom-fmaxs=232 -mcustom-fmins=233 -mcustom-round=248 -mcustom-fixsi=249 -mcustom-floatis=250 -mcustom-fsqrts=251 -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255
Heads up, bestie ๐ Custom instruction assignments from individual -mcustom-insn= options always beat the ones from -mcustom-fpu-cfg=, no matter what order they show up in on the command line ๐
Note that you can get more local control over which FPU configuration gets picked by using the target("custom-fpu-cfg=name") function attribute or pragma ๐
The name fph2 is short for Nios II Floating Point Hardware 2 Component ๐ง Also, the custom instructions enabled by -mcustom-fmins=233 and -mcustom-fmaxs=234 only get generated if -ffinite-math-only is specified. The custom instruction enabled by -mcustom-round=248 only gets generated if -fno-math-errno is specified. Unlike the other configurations, -fsingle-precision-constant is not set here ๐ญ
These extra -m options are available for the Altera Nios II ELF (bare-metal) target ๐ฆ
-mhalโ links with the HAL BSP. This skips the GCC-provided C runtime startup and termination code, and it's usually paired with-msys-crt0=to point at the alternate startup code from the HAL BSP ๐ง-msmallcโ links with a limited version of the C library,-lsmallc, instead of Newlib ๐ธ-msys-crt0=startfileโstartfileis the file name of the startfile (crt0) to use when linking. This only works together with-mhal๐-msys-lib=systemlibโsystemlibis the library name for the low-level system calls the C library needs, like"read"and"write". This is usually used to link with a library from a HAL BSP โจ
๐ 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 specified PTX ISA target architecture (e.g.sm_35). Valid architecture strings aresm_30,sm_35,sm_53,sm_70,sm_75andsm_80. The default depends on how the compiler was configured, see--with-arch๐ฅ
This option also sets the preprocessor macro "__PTX_SM__". For example, for sm_35 it has the value 350 ๐
-misa=architecture-stringโ alias of-march=๐-march-map=architecture-stringโ picks the closest available-march=value that isn't more capable. For instance,-march-map=sm_50selects-march=sm_35, and-march-map=sm_53selects-march=sm_53๐ง-mptx=version-stringโ generates code for the specified PTX ISA version (e.g.7.0). Valid version strings include3.1,6.0,6.3, and7.0. The default PTX ISA version is6.0, unless a higher version is needed for the PTX ISA target architecture given via-march=๐
This option sets the values of the preprocessor macros "__PTX_ISA_VERSION_MAJOR__" and "__PTX_ISA_VERSION_MINOR__". For instance, for 3.1 the macros have the values 3 and 1, respectively ๐
-mmainkernelโ links in code for a__mainkernel. This is for stand-alone execution instead of offloading ๐ง-moptimizeโ applies partitioned execution optimizations. This is the default whenever any level of optimization is selected โจ-msoft-stackโ generates code that doesn't use".local"memory directly for stack storage. Instead, a per-warp stack pointer gets maintained explicitly. This enables variable-length stack allocation (with variable-length arrays or"alloca"), and when global memory is used as the underlying storage, it makes it possible to access automatic variables from other threads, or with atomic instructions. This codegen 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-mgompinstead ๐ซถ-muniform-simtโ switches to a codegen variant that lets all threads in each warp execute, while keeping memory state and side effects as if only one thread in each warp were active outside of OpenMP SIMD regions. All atomic operations and calls to the runtime (malloc,free,vprintf) are conditionally executed (iff the current lane index equals the master lane index), and the register being assigned is copied via a shuffle instruction from the master lane. Outside of SIMD regions, lane 0 is the master; inside, each thread sees itself as the master. The shared memory arrayint __nvptx_uni[]stores all-zeros or all-ones bitmasks for each warp, indicating the current mode (0 outside of SIMD regions). Each thread can bitwise-and the bitmask at positiontid.ywith the current lane index to compute the master lane index ๐ธ-mgompโ generates code for OpenMP offloading. It enables-msoft-stackand-muniform-simtand selects the corresponding 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 is"or1ksim"๐-mnewlibโ Total ghost energy ๐ป This option is ignored and only hangs around for compatibility. It used to pick linker and preprocessor options for newlib ๐-msoft-div,-mhard-divโ Choose software or hardware divide (l.div,l.divu) instructions ๐ Hardware divide is the default, so you're already getting the good stuff โจ-msoft-mul,-mhard-mulโ Choose software or hardware multiply (l.mul,l.muli) instructions ๐ฅ Hardware multiply is the default, no notes ๐-msoft-float,-mhard-floatโ Pick software or hardware for floating point operations ๐ฆ Software is the default, so it's a whole vibe.-mdouble-floatโ When-mhard-floatis selected, this turns on double-precision floating point instructions ๐ธ By default, functions fromlibgcchandle double-precision floating point operations.-munordered-floatโ When-mhard-floatis selected, this unlocks unordered floating point compare and set flag (lf.sfun*) instructions ๐ซถ By default, functions fromlibgcchandle unordered floating point compare and set flag operations.-mcmovโ Turns on conditional move (l.cmov) instructions โญ Without it, the same result is made with set and branch.-mrorโ Turns on rotate right (l.ror) instructions ๐ By default, functions fromlibgcchandle rotate right operations.-mroriโ Turns on rotate right with immediate (l.rori) instructions ๐ง By default, functions fromlibgcchandle rotate right with immediate operations.-msextโ Turns on sign extension (l.ext*) instructions ๐ By default, memory loads do the sign extension work.-msfimmโ Turns on compare and set flag with immediate (l.sf*i) instructions ๐ By default, extra instructions get generated to store the immediate in a register first.-mshftimmโ Turns on shift with immediate (l.srai,l.srli,l.slli) instructions ๐ By default, extra instructions get generated to store the immediate in a register first.-mcmodel=smallโ Generates OpenRISC code for the small model ๐ฆ The GOT is limited to 64k. This is the default model.-mcmodel=largeโ Generates OpenRISC code for the large model ๐ The GOT may grow up to 4G in size.
๐ง PDP-11 Options ๐ง
These options are defined for the PDP-11:
-mfpuโ Uses hardware FPP floating point ๐ This is the default. (FIS floating point on the PDP-11/40 is not supported.) Implies-m45.-msoft-floatโ 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 PRU target:
-minrtโ Links with a minimum runtime environment ๐ซถ This can significantly shrink 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 won't 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 theLOOPinstruction ๐-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 โ 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. TI ABI, though, mandates that the pointer can be
NULLin case the caller is not using the returned value. GNU always passes and expects a valid return value pointer ๐
The current -mabi=ti implementation 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, do or don'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 ๐ABI-stringhas 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. Contrast this with-march=rv64ifd -mabi=lp64f, which still lets the compiler generate code that uses the F and D extensions, but only allows floating-point values up to 32 bits long to be passed in registers. Or there's-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers ๐ง
The default for this argument is system dependent, so 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's also the ilp32e ABI, which can only be used with the rv32e architecture, and the lp64e ABI, which can only be used with rv64e. Those ABIs are not well specified at present and are subject to change.
-mfdiv,-mno-fdivโ Do or don'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.-mdiv,-mno-divโ Do or don'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 forISA-spec-stringare:2.2โ Produce code conforming to version 2.2.20190608โ Produce code conforming to version 20190608.20191213โ Produce 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. There's also a special value,help(-march=help), that lists all supported extensions ๐ฆ
The syntax of the ISA string is defined as follows:
- "The string must start with rv32 or rv64, followed by"
i,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 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 ๐
Extension Name : Supported Version : Description
i @tab 2.0, 2.1 @tab Base integer extension.
e @tab 2.0 @tab Reduced base integer extension.
g @tab - @tab General-purpose computing base extension, g will expand to i, m, a, f, d, zicsr and zifencei.
m @tab 2.0 @tab Integer multiplication and division extension.
a @tab 2.0, 2.1 @tab Atomic extension.
f @tab 2.0, 2.2 @tab Single-precision floating-point extension.
d @tab 2.0, 2.2 @tab Double-precision floating-point extension.
c @tab 2.0 @tab Compressed extension.
h @tab 1.0 @tab Hypervisor extension.
v(1.0) โ ๐ the Vector extension, the main vibe for all things vector! โจzicsr(2.0) โ ๐ control and status register access, literally the CSR stuff ๐ฅzifencei(2.0) โ ๐ง the instruction-fetch fence extension ๐ซถzicond(1.0) โ ๐ integer conditional operations, lowkey so usefulza64rs(1.0) โ ๐ reservation set size of 64 bytesza128rs(1.0) โ ๐ reservation set size of 128 bytes, the bigger siblingzawrs(1.0) โ โณ wait-on-reservation-set extension, patience is a vibe ๐ธzba(1.0) โ ๐ฆ address calculation extensionzbb(1.0) โ ๐ง basic bit manipulation, very smart energy ๐zbc(1.0) โ โจ carry-less multiplication extensionzbs(1.0) โ ๐ single-bit operation extensionzfinx(1.0) โ ๐ฅ single-precision floating-point in integer registers extensionzdinx(1.0) โ ๐ฅ double-precision floating-point in integer registers extensionzhinx(1.0) โ ๐ฅ half-precision floating-point in integer registers extensionzhinxmin(1.0) โ ๐ฅ the minimal half-precision version of the integer-register floating-point extensionzbkb(1.0) โ ๐ cryptography bit-manipulation extensionzbkc(1.0) โ ๐ cryptography carry-less multiply extensionzbkx(1.0) โ ๐ cryptography crossbar permutation extensionzkne(1.0) โ ๐๏ธ AES encryption extensionzknd(1.0) โ ๐๏ธ AES decryption extensionzknh(1.0) โ ๐ซถ hash function extensionzkr(1.0) โ ๐ฒ entropy source extension, very random, very cutezksed(1.0) โ ๐ SM4 block cipher extensionzksh(1.0) โ ๐ SM3 hash function extensionzkt(1.0) โ โฑ๏ธ data independent execution latency extensionzk(1.0) โ ๐ standard scalar cryptography extension, the whole crypto packagezkn(1.0) โ ๐ NIST algorithm suite extensionzks(1.0) โ ๐ ShangMi algorithm suite extensionzihintntl(1.0) โ ๐ท non-temporal locality hints extensionzihintpause(1.0) โ โธ๏ธ pause hint extension, chill momentzicboz(1.0) โ ๐ง cache-block zero extensionzicbom(1.0) โ ๐ง cache-block management extensionzicbop(1.0) โ ๐ง cache-block prefetch extensionzic64b(1.0) โ ๐ง the cache block size is 64 bytes, no capziccamoa(1.0) โ ๐ง main memory supports all atomics in Aziccif(1.0) โ ๐ง main memory supports instruction fetch with an atomicity requirementzicclsm(1.0) โ ๐ง main memory supports misaligned loads and storesziccrse(1.0) โ ๐ง main memory supports forward progress on LR/SC sequenceszicntr(2.0) โ โฐ standard extension for base counters and timerszihpm(2.0) โ ๐ standard extension for hardware performance countersztso(1.0) โ ๐งฑ total store ordering extensionzve32x(1.0) โ ๐ธ vector extensions for embedded processorszve32f(1.0) โ ๐ธ vector extensions for embedded processorszve64x(1.0) โ ๐ธ vector extensions for embedded processorszve64f(1.0) โ ๐ธ vector extensions for embedded processorszve64d(1.0) โ ๐ธ vector extensions for embedded processorszvl32b(1.0) โ ๐ minimum vector length standard extensionzvl64b(1.0) โ ๐ minimum vector length standard extensionzvl128b(1.0) โ ๐ minimum vector length standard extensionzvl256b(1.0) โ ๐ minimum vector length standard extensionzvl512b(1.0) โ ๐ minimum vector length standard extensionzvl1024b(1.0) โ ๐ minimum vector length standard extensionzvl2048b(1.0) โ ๐ minimum vector length standard extensionzvl4096b(1.0) โ ๐ minimum vector length standard extensionzvbb(1.0) โ ๐ง vector basic bit-manipulation extensionzvbc(1.0) โ โจ vector carry-less multiplication extensionzvkb(1.0) โ ๐ vector cryptography bit-manipulation extensionzvkg(1.0) โ ๐ vector GCM/GMAC extensionzvkned(1.0) โ ๐๏ธ vector AES block cipher extensionzvknha(1.0) โ ๐ซถ vector SHA-2 secure hash extensionzvknhb(1.0) โ ๐ซถ vector SHA-2 secure hash extensionzvksed(1.0) โ ๐ vector SM4 block cipher extensionzvksh(1.0) โ ๐ vector SM3 secure hash extensionzvkn(1.0) โ ๐ vector NIST algorithm suite extension, and it expands tozvkned,zvknhb,zvkbandzvkt๐zvknc(1.0) โ ๐ vector NIST algorithm suite with carry-less multiply extension, and it expands tozvknandzvbc๐zvkng(1.0) โ ๐ vector NIST algorithm suite with GCM extension, and it expands tozvknandzvkg๐zvks(1.0) โ ๐ vector ShangMi algorithm suite extension, and it expands tozvksed,zvksh,zvkbandzvkt๐zvksc(1.0) โ ๐ vector ShangMi algorithm suite with carry-less multiplication extension, and it expands tozvksandzvbc๐zvksg(1.0) โ ๐ vector ShangMi algorithm suite with GCM extension, and it expands tozvksandzvkg๐zvkt(1.0) โ โฑ๏ธ vector data independent execution latency extensionzfh(1.0) โ ๐ฅ half-precision floating-point extensionzfhmin(1.0) โ ๐ฅ minimal half-precision floating-point extensionzvfh(1.0) โ ๐ฅ vector half-precision floating-point extensionzvfhmin(1.0) โ ๐ฅ vector minimal half-precision floating-point extensionzvfbfmin(1.0) โ ๐ฅ vector BF16 converts extensionzfa(1.0) โ โ additional floating-point extensionzmmul(1.0) โ โ๏ธ integer multiplication extensionzca(1.0) โ ๐๏ธ integer compressed instruction extensionzcf(1.0) โ ๐๏ธ compressed single-precision floating-point loads and stores extensionzcd(1.0) โ ๐๏ธ compressed double-precision floating-point loads and stores extensionzcb(1.0) โ ๐๏ธ simple compressed instruction extensionzce(1.0) โ ๐๏ธ compressed instruction extensions for embedded processorszcmp(1.0) โ ๐ compressed push and pop extensionzcmt(1.0) โ ๐ table jump instruction extensionsmaia(1.0) โ ๐๏ธ advanced interrupt architecture extensionsmepmp(1.0) โ ๐ก๏ธ PMP enhancements for memory access and execution prevention in machine modesmstateen(1.0) โ ๐ state enable extensionssaia(1.0) โ ๐๏ธ advanced interrupt architecture extension for supervisor modesscofpmf(1.0) โ ๐ count overflow and filtering extensionssstateen(1.0) โ ๐ state-enable extension for supervisor modesstc(1.0) โ โฐ supervisor-mode timer interrupts extensionsvinval(1.0) โ ๐งน fine-grained address-translation cache invalidation extensionsvnapot(1.0) โ ๐บ๏ธ NAPOT translation contiguity extensionsvpbmt(1.0) โ ๐บ๏ธ page-based memory types extensionxcvmac(1.0) โ ๐ค Core-V multiply-accumulate extensionxcvalu(1.0) โ ๐ค Core-V miscellaneous ALU extensionxcvelw(1.0) โ ๐ค Core-V event load word extensionxtheadba(1.0) โ ๐ T-Head address calculation extensionxtheadbb(1.0) โ ๐ T-Head basic bit-manipulation extensionxtheadbs(1.0) โ ๐ T-Head single-bit instructions extensionxtheadcmo(1.0) โ ๐ T-Head cache management operations extensionxtheadcondmov(1.0) โ ๐ T-Head conditional move extensionxtheadfmemidx(1.0) โ ๐ T-Head indexed memory operations for floating-point registers extensionxtheadfmv(1.0) โ ๐ T-Head double floating-point high-bit data transmission extensionxtheadint(1.0) โ ๐ T-Head acceleration interruption extensionxtheadmac(1.0) โ ๐ T-Head multiply-accumulate extensionxtheadmemidx(1.0) โ ๐ T-Head indexed memory operation extensionxtheadmempair(1.0) โ ๐ T-Head two-GPR memory operation extensionxtheadsync(1.0) โ ๐ T-Head multi-core synchronization extensionxventanacondops(1.0) โ ๐ Ventana integer conditional operations extension
When -march= is not specified, use the setting from -mcpu. ๐ซถ
If both -march and -mcpu= are not specified, the default for this argument is system dependent, so bestie, if you want a specific architecture extension, you should specify one explicitly. ๐
โจ -mcpu=processor-string
Use the architecture of, and optimize the output for, the given processor, specified by a particular CPU name. ๐ Permissible values for this option are: sifive-e20, sifive-e21, sifive-e24, sifive-e31, sifive-e34, sifive-e76, sifive-s21, sifive-s51, sifive-s54, sifive-s76, sifive-u54, sifive-u74, sifive-x280, sifive-xp450 and sifive-x670. ๐ฆ
Note that -mcpu does not override -march or -mtune. ๐
๐ธ -mtune=processor-string
Optimize the output for the given processor, specified by microarchitecture or a particular CPU name. โญ Permissible values for this option are: rocket, sifive-3-series, sifive-5-series, sifive-7-series, thead-c906, size, sifive-p400-series, sifive-p600-series, and all valid options for -mcpu=. ๐
When -mtune= is not specified, use the setting from -mcpu. The default is rocket if both are not specified. ๐ง
โ ๏ธ Thesizechoice is not intended for use by end-users, bestie, so hands off! ๐ It is used when-Osis specified. It overrides the instruction cost info provided by-mtune=, but it does not override the pipeline info. This helps reduce code size while still giving good performance. ๐
-mpreferred-stack-boundary=numโ okay so this one tries to keep the stack boundary lined up to a2raised to num byte boundary ๐โจ. If you don't specify it, the default is4(that's 16 bytes or 128-bits) ๐ .
โ ๏ธ Warning, bestie ๐จ: if you use this switch, you HAVE to build every single module with the same value, libraries included. That covers the system libraries and startup modules too ๐ญ.
-msmall-data-limit=nโ puts global and static data smaller thannbytes into a special section ๐ง, but only on some targets ๐.-msave-restore,-mno-save-restoreโ these decide whether you get the smaller-but-slower prologue and epilogue code that calls library functions ๐ข. The default is the fast inline prologues and epilogues โก, so you're only switching to the slow lane if you ask for it ๐.-mmovcc,-mno-movccโ this one is giving branchless conditional-move code sequences ๐ฆ, even on targets that don't have special instructions for conditional operations. If it's enabled, sequences of ALU operations get built from base integer ISA instructions wherever that's profitable ๐ฅ.-minline-atomics,-mno-inline-atomicsโ choose between smaller but slower subword atomic emulation that callslibatomicfunctions ๐, or the fast inline subword atomics that don't needlibatomicat all ๐. The default is the fast inline version, obviously ๐.-minline-strlen,-mno-inline-strlenโ you can ask GCC to try inliningstrlencalls if it's possible ๐ธ. It'll only actually do it if the string is properly aligned and the accelerated instructions are around โจ. By default, it does NOT inlinestrlencalls ๐.-minline-strcmp,-mno-inline-strcmpโ same vibe asstrlen, but forstrcmpcalls ๐ . Inlining only happens when the strings are properly aligned and the accelerated instructions are available ๐ฅ. The default is to not inlinestrcmpcalls ๐ซถ.
The --param riscv-strcmp-inline-limit=n parameter controls the maximum number of bytes compared by the inlined code ๐. Its default value is 64 ๐.
-minline-strncmp,-mno-inline-strncmpโ thestrncmpversion of the same story ๐. Inlining only happens when the strings are properly aligned and the accelerated instructions exist โจ. Default is to not inlinestrncmpcalls ๐ฆ.
Same deal with --param riscv-strcmp-inline-limit=n: it sets the maximum number of bytes compared by the inlined code, and the default is 64 ๐.
-mshorten-memrefs,-mno-shorten-memrefsโ this one is lowkey genius ๐ง . It 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 targets 32-bit integer load/stores ๐ฏ.-mstrict-align,-mno-strict-alignโ decides whether unaligned memory accesses get generated or not ๐ โโ๏ธ. The default depends on whether the processor you're optimizing for supports fast unaligned access ๐โโ๏ธ.-mcmodel=medlowโ generates code for the medium-low code model ๐. The program and its statically defined symbols have to live inside a single 2 GiB address range, sitting between absolute addresses-2 GiBand+2 GiB๐. Programs can be statically or dynamically linked ๐. This is the default code model ๐.-mcmodel=medanyโ generates code for the medium-any code model ๐. The program and its statically defined symbols just need to be within any single 2 GiB address range ๐ซ. Programs can be statically or dynamically linked ๐ง.
Heads up though ๐จ: the code from medium-any is position-independent, but it's NOT guaranteed to work correctly when linked into position-independent executables or libraries ๐.
-mexplicit-relocs,-mno-exlicit-relocsโ you either use assembler relocation operators when dealing with symbolic addresses ๐งฉ, or you don't. The alternative is assembler macros instead, and those might limit optimization ๐.-mrelax,-mno-relaxโ takes advantage of linker relaxations ๐ชถ to cut down on the number of instructions needed to materialize symbol addresses โ๏ธ. The default is to take advantage of linker relaxations ๐.-mriscv-attribute,-mno-riscv-attributeโ emits (or doesn't emit) a RISC-V attribute that records extra information into ELF objects ๐ฆ. This feature needs at least binutils 2.32 ๐ ๏ธ.-mcsr-check,-mno-csr-checkโ enables or disables the CSR checking ๐.-malign-data=typeโ controls how GCC aligns variables and constants of array, structure, or union types ๐. The supported values for type arexlen, 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โ 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 ๐งต.
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to decide which register is used as the base register for reading the canary ๐ฏ, and what offset from that base register it's read from ๐. There's no default register or offset here, because this is entirely for use within the Linux kernel ๐ง.
-mtls-dialect=descโ uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables ๐งตโจ.-mtls-dialect=tradโ uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐ฐ๏ธ. This is the default ๐.
๐ธ RL78 Options ๐ธ
-msimโ links in additional target libraries so things can run inside a simulator ๐ฎ.-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ picks the type of hardware multiplication and division support you want ๐งฎ. The simplest is"none", which uses software for both multiplication and division, and it's the default ๐ . The"g13"value is for the hardware multiply/divide peripheral on the RL78/G13 (S2 core) targets ๐ง. The"g14"value selects the multiplication and division instructions supported by the RL78/G14 (S3 core) parts ๐. The value"rl78"is an alias for"g14", and the value"mg10"is an alias for"none"๐ฆ.
Also, a C preprocessor macro gets defined based on this setting ๐ช. 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 you're targeting ๐ฏ. The default is the G14 core, which is also known as an S3 core or just RL78 ๐. The G13 (or S2) core doesn't have multiply or divide instructions, so it uses a hardware peripheral for those operations instead ๐ง. The G10 (or S1) core doesn't have register banks, so it uses a different calling convention ๐.
If you set this option, it also picks the type of hardware multiply support to use ๐, unless you override it with an explicit -mmul=none on the command line. So -mcpu=g13 turns on the G13 hardware multiply peripheral, and -mcpu=g10 turns hardware multiplications off altogether ๐
โโ๏ธ.
Now, the RL78/G14 core is the default target, BUT specifying -mcpu=g14 or -mcpu=rl78 on the command line really 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 ๐ข. That's there for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ซถ.
And yep, a C preprocessor macro gets defined based on this setting too ๐. The possible values are "__RL78_G10__", "__RL78_G13__", or "__RL78_G14__" ๐.
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the matching-mcpu=option ๐. They only exist for backwards compatibility ๐ฐ๏ธ.-mallregsโ lets the compiler use all of the available registers ๐ง . By default, registersr24..r31are reserved for interrupt handlers ๐ง. With this option on, those registers can be used in ordinary functions as well ๐.-m64bit-doubles,-m32bit-doublesโ makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size ๐. The default is-m32bit-doubles๐ .-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ says whether interrupt handler functions should preserve the MDUC registers ๐ก๏ธ. This is only necessary if normal code might use the MDUC registers, like when it does multiplication and division operations โ๏ธโ. The default is to ignore the MDUC registers, because that makes the interrupt handlers faster โก. The target option-mg13needs to be passed for this to work, since this feature is only available on the G13 target (S2 core) ๐ง. The MDUC registers only get saved if the interrupt handler performs a multiplication or division operation, or if it 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
You use these options to say which instructions are available on the processor you're using ๐. The default value of these options gets determined when GCC is configured ๐ ๏ธ. Specifying -mcpu=cpu_type overrides whatever you set with these options ๐
โโ๏ธ, so we recommend using the -mcpu=cpu_type option instead of the options listed above ๐ซถ.
Specifying -mpowerpc-gpopt lets GCC use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root ๐ฅ. Specifying -mpowerpc-gfxopt lets GCC use the optional PowerPC architecture instructions in the Graphics group, including floating-point select โจ.
The POWER feature flags are next, bestie, and they're a whole vibe ๐ธ Each one switches on an instruction set that a specific chip family shipped with ๐ฆ
-mmfcrfโ lets GCC emit the move from condition register field instruction ๐ That's the one from the POWER4 processor, plus other chips that support the PowerPC V2.01 architecture.-mpopcntbโ unlocks the popcount and double-precision FP reciprocal estimate instruction โจ That's from the POWER5 processor, plus other chips that support the PowerPC V2.02 architecture.-mpopcntdโ unlocks the popcount instruction ๐ฅ That's from the POWER7 processor, plus other chips that support the PowerPC V2.06 architecture.-mfprndโ unlocks the FP round to integer instructions ๐ That's from the POWER5+ processor, plus other chips that support the PowerPC V2.03 architecture.-mcmpbโ unlocks the compare bytes instruction ๐ That's from the POWER6 processor, plus other chips that support the PowerPC V2.05 architecture.-mhard-dfpโ unlocks the decimal floating-point instructions, which show up on some POWER processors ๐ง
The -mpowerpc64 option lets GCC generate the extra 64-bit instructions from the full PowerPC64 architecture, and it treats GPRs as 64-bit doubleword quantities ๐ GCC defaults to -mno-powerpc64, so you have to ask for it on purpose.
-mcpu=cpu_typeโ this one sets the architecture type, register usage, and instruction scheduling parameters for the machine type you name ๐ The supported values are:
401, 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, powerpc, powerpc64, powerpc64le, rs64, and native.
Bestie, -mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le are the generic ones ๐ซถ They give you pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC architecture machine types. GCC assumes an appropriate, generic processor model for scheduling purposes.
Specifying native as the cpu type detects the host processor of the system doing the compilation and picks the architecture option that matches it ๐ฆ -mcpu=native has no effect if GCC doesn't recognize the processor, so it just does nothing, which is fine.
The other values name one specific processor. Code generated for those runs best on that chip, and it may not run at all on others.
Heads up, babe: if you target a specific processor, the code might not run on anything else at all ๐ Keep that in mind before you ship it.
The -mcpu options automatically enable or disable the following options ๐ธ
-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple -mpopcntb
-mpopcntd -mpowerpc64 -mpowerpc-gpopt -mpowerpc-gfxopt -mmulhw
-mdlmzb -mmfpgpr -mvsx -mcrypto -mhtm -mpower8-fusion
-mquad-memory -mquad-memory-atomic -mfloat128 -mfloat128-hardware
-mprefixed -mpcrel -mmma -mrop-protect
The exact set for each CPU changes between compiler versions. GCC picks whatever seems to produce the best code for that CPU, so it doesn't always match what the hardware can actually do ๐ If you want to set one individual option to a specific value, put it after the -mcpu option, like -mcpu=970 -mno-altivec. Main character move ๐
On AIX, -maltivec and -mpowerpc64 aren't enabled or disabled by -mcpu right now, because AIX doesn't have full support for those options yet ๐ญ You can still turn them on or off one at a time if you're sure it'll work in your environment.
-mtune=cpu_typeโ this sets only the instruction scheduling parameters for the machine type you name โจ It does not set the architecture type or register usage the way-mcpu=cpu_typedoes. The same values forcpu_typework for-mtuneas for-mcpu. If you specify both, the code uses the architecture and registers from-mcpu, but the scheduling parameters come from-mtune.-mcmodel=smallโ generates PowerPC64 code for the small model, where the TOC is limited to 64k ๐ง-mcmodel=mediumโ generates PowerPC64 code for the medium model, where the TOC and other static data can total up to 4G in size. This is the default for 64-bit Linux ๐-mcmodel=largeโ generates PowerPC64 code for the large model, where the TOC can be up to 4G in size. Other data and code is only limited by the 64-bit address space ๐-maltivec,-mno-altivecโ makes GCC generate (or not generate) AltiVec instructions, and also turns on (or off) built-in functions that give you more direct access to the AltiVec instruction set ๐ You might also need to set-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 the target's endianness ๐ซถ On a big-endian target, element zero is the leftmost element in a vector register. On a little-endian target, element zero is the rightmost element in a vector register.
-mvrsave,-mno-vrsaveโ makes GCC generate (or not generate) VRSAVE instructions when it's generating AltiVec code ๐-msecure-pltโ generates code that letsldandld.sobuild executables and shared libraries with non-executable.pltand.gotsections ๐ This is a PowerPC 32-bit SYSV ABI option.-mbss-pltโ generates code that uses a BSS.pltsection thatld.sofills in. It requires.pltand.gotsections that are both writable and executable ๐ This is a PowerPC 32-bit SYSV ABI option.-misel,-mno-iselโ turns the generation of ISEL instructions on or off โจ-mvsx,-mno-vsxโ makes GCC generate (or not generate) vector/scalar (VSX) instructions, and also turns on (or off) built-in functions that give you more direct access to the VSX instruction set ๐ฅ-mcrypto,-mno-cryptoโ enables (or disables) the built-in functions that give you direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐ฆ-mhtm,-mno-htmโ enables (or disables) the built-in functions that give you direct access to the Hardware Transactional Memory (HTM) instructions added in version 2.07 of the PowerPC ISA ๐ธ-mpower8-fusion,-mno-power8-fusionโ the first one generates code that keeps some integer operations adjacent, so the instructions can be fused together on POWER8 and later processors ๐ง The second one generates code that does not keep them adjacent.-mquad-memory,-mno-quad-memoryโ makes GCC generate (or not generate) the non-atomic quad word memory instructions ๐-mquad-memoryrequires 64-bit mode.-mquad-memory-atomic,-mno-quad-memory-atomicโ makes GCC generate (or not generate) the atomic quad word memory instructions ๐-mquad-memory-atomicrequires 64-bit mode.-mfloat128,-mno-float128โ enables or disables the__float128keyword for IEEE 128-bit floating point, and picks either software emulation or hardware instructions for it ๐
The VSX instruction set (-mvsx) has to be enabled before you can use IEEE 128-bit floating point support ๐ซถ Also, IEEE 128-bit floating point is only supported on Linux.
Only Linux gets IEEE 128-bit floating point support, so it's a no-go anywhere else ๐
The default for -mfloat128 is enabled on PowerPC Linux systems that use the VSX instruction set, and disabled on other systems โจ
If you use the ISA 3.0 instruction set (-mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support also enables 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 is done with software emulation.
-mfloat128-hardware,-mno-float128-hardwareโ enables (or disables) using ISA 3.0 hardware instructions to support the__float128data type ๐ฅ
The default for -mfloat128-hardware is enabled on PowerPC Linux systems that use the ISA 3.0 instruction set, and disabled on other systems ๐
-m32,-m64โ generates code for 32-bit or 64-bit environments on Darwin and SVR4 targets, including GNU/Linux ๐ The 32-bit environment setsint,long, and pointer to 32 bits, and generates code that runs on any PowerPC variant. The 64-bit environment setsintto 32 bits, setslongand pointer to 64 bits, and generates code for PowerPC64, as if you'd used-mpowerpc64.-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ these change how the TOC (Table Of Contents) is generated. Every executable file gets one ๐ง-mfull-tocis selected by default. With it, GCC allocates at least one TOC entry for each unique non-automatic variable reference in your program, and it also puts floating-point constants in the TOC. The catch is that only 16,384 entries are available in the TOC ๐ญ
If the linker tells you that you've overflowed the available TOC space, you can shrink the TOC usage with -mno-fp-in-toc and -mno-sum-in-toc ๐ซถ -mno-fp-in-toc stops GCC from putting floating-point constants in the TOC. -mno-sum-in-toc makes GCC generate code that calculates the sum of an address and a constant at run time, instead of storing that sum in the TOC. You can use one or both. Each one makes the code very slightly slower and larger, which is the price of saving TOC space.
If you still run out of TOC space even with both of those, use -mminimal-toc instead ๐ It makes GCC create only one TOC entry for every file. The code is slower and larger, but it uses extremely little TOC space. You might only want to use it on files with less frequently-executed code.
-maix64,-maix32โ enables the 64-bit AIX ABI and calling convention, with 64-bit pointers, a 64-bitlongtype, and the infrastructure needed to support them โจ Specifying-maix64implies-mpowerpc64, while-maix32disables the 64-bit ABI and implies-mno-powerpc64. GCC defaults to-maix32.-mxl-compat,-mno-xl-compatโ okay so this one makes your code act more like IBM XL compiler output when you're on the AIX-compatible ABI ๐ โจ It passes floating-point arguments to prototyped functions past the register save area (RSA) on the stack, in addition to the argument FPRs ๐ฆ It also stops assuming that the most significant double in a 128-bitlong doubleis properly rounded when you compare values and convert todouble๐ And it uses XL symbol names forlong doublesupport routines ๐ซถ
The AIX calling convention got extended, but that wasn't documented at first. It was for an obscure K&R C situation: calling a function that takes the address of its arguments with fewer arguments than it declares ๐ IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine is compiled without optimization. Storing floating-point arguments on the stack all the time is inefficient and rarely needed, so this is not on by default. You only need it when calling subroutines that IBM XL compiled without optimization ๐ธ
-mpeโ slay, support 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. Your system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you need to override the specs file with-specs=to point at the right directory ๐บ๏ธ Heads up: PE doesn't support threads, so-mpeand-pthreadare incompatible ๐ซ-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 from the ABI ๐
On 64-bit Darwin, natural alignment is the default, and -malign-power is not supported there ๐
โโ๏ธ
-msoft-float,-mhard-floatโ-msoft-floatgenerates code that doesn't touch the floating-point register set, and-mhard-floatgenerates code that does use it ๐ง With-msoft-float, software floating-point emulation is provided, but you have to pass the option to GCC when linking too ๐-mmultiple,-mno-multipleโ-mmultiplegenerates code that uses the load multiple word and store multiple word instructions, and-mno-multiplegenerates code that doesn't ๐งฉ These are generated by default on POWER systems, and not on PowerPC systems. Do not use-mmultipleon little-endian PowerPC systems, since those instructions don't work when the processor is in little-endian mode ๐ญ The exceptions are PPC740 and PPC750, which do permit these instructions in little-endian mode ๐ฆ-mupdate,-mno-updateโ-mupdategenerates code that uses load or store instructions that update the base register to the address of the calculated memory location, and-mno-updategenerates code that doesn't ๐ These instructions are 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 is stored.
Careful bestie! With -mno-update, code that walks the stack frame across interrupts or signals may end up with corrupted data ๐
-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ-mavoid-indexed-addressestries to avoid indexed load or store instructions, and-mno-avoid-indexed-addressesdoes not avoid them ๐ Indexed instructions can take a performance hit on Power6 processors in certain situations, like stepping through big arrays that cross a 16M boundary. This option is enabled by default when targeting Power6 and disabled otherwise โจ-mfused-madd,-mno-fused-maddโ-mfused-maddgenerates code that uses floating-point multiply and accumulate instructions, and-mno-fused-maddgenerates code that doesn't ๐ง These are generated by default if hardware floating point is used. The machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fastoption, and-mno-fused-maddis mapped to-ffp-contract=off๐ฅ-mmulhw,-mno-mulhwโ-mmulhwgenerates code that uses the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors, and-mno-mulhwgenerates code that doesn't ๐ธ These are generated by default when targeting those processors ๐-mdlmzb,-mno-dlmzbโ-mdlmzbgenerates code that uses the string-searchdlmzbinstruction on the IBM 405, 440, 464 and 476 processors, and-mno-dlmzbgenerates code that doesn't ๐ This instruction is generated by default when targeting those processors ๐-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems,-mno-bit-aligndoes not force structures and unions containing bit-fields to be aligned to the base type of the bit-field, and-mbit-aligndoes ๐งธ
Here's the tea โ By default, a structure with nothing but 8 "unsigned" bit-fields of length 1 is aligned to a 4-byte boundary and has a size of 4 bytes. With -mno-bit-align, that same structure is 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,-mno-strict-aligndoes not assume that unaligned memory references are handled by the system, and-mstrict-aligndoes assume that ๐ซถ-mrelocatable,-mno-relocatableโ-mrelocatablegenerates code that allows a static executable to be relocated to a different address at run time, and-mno-relocatablegenerates code that doesn't ๐ฆ 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. Also,-mrelocatablecode aligns the stack to an 8-byte boundary ๐-mrelocatable-lib,-mno-relocatable-libโ just like-mrelocatable,-mrelocatable-libgenerates a.fixupsection so static executables can be relocated at run time ๐ The difference is that it does not 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,-mno-tocdoes not assume that register 2 contains a pointer to a global area pointing to the addresses used in the program, and-mtocdoes assume it ๐งญ-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 that it is not relocatable, but its external references are relocatable ๐ The resulting code is suitable 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 this register with an appropriate value before execution begins ๐ซถ-mprioritize-restricted-insns=priorityโ this controls the priority assigned to dispatch-slot restricted instructions during the second scheduling pass ๐๏ธ The argument priority takes the value0,1, or2, which assigns no priority, highest priority, 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 argument dependence_type takes one of these values:noโ no dependence is costly ๐ โโ๏ธallโ all dependences are costly ๐ฅtrue_store_to_loadโ a true dependence from store to load is costly ๐งstore_to_loadโ any dependence from store to load is costly ๐ฆnumberโ any dependence whose latency is greater than or equal to number is costly ๐
-minsert-sched-nops=schemeโ this controls which NOP insertion scheme is used during the second scheduling pass ๐ธ The argument scheme takes one of these values:noโ don't insert NOPs ๐padโ pad with NOPs any dispatch group that has vacant issue slots, according to the scheduler's grouping ๐งธregroup_exactโ insert NOPs to force costly dependent insns into separate groups. 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. Insert number NOPs 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-meabioptions ๐-mcall-sysv-noeabiโ this specifies both-mcall-sysvand-mno-eabioptions ๐ฆ-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐ก-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐ก-mtraceback=traceback_typeโ this selects the type of traceback table ๐งพ Valid values for traceback_type arefull,part, andnoโจ-maix-struct-returnโ returns all structures in memory, as specified by the AIX ABI ๐ฆ-msvr4-struct-returnโ returns structures smaller than 8 bytes in registers, as specified by the SVR4 ABI ๐งบ-mabi=abi-typeโ this extends the current ABI with a particular extension, or removes that extension ๐ Valid values are:altivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1,elfv2, and for AIX:vec-extabi,vec-default๐-mabi=ibmlongdoubleโ okay so this one switches the ABI over to IBM extended-precisionlong double๐ . Heads up though, it's not likely to work if your system already defaults to IEEE extended-precisionlong double๐ญ. If you changelong doubleaway from IEEE extended-precision, the compiler will warn you unless you add-Wno-psabi. You also need-mlong-double-128enabled for this to work ๐ซถ.-mabi=ieeelongdoubleโ the mirror image of the one above โจ. It switches the ABI to IEEE extended-precisionlong double, but it's not likely to work if your system defaults to IBM extended-precisionlong 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โ this sets the ABI to ELFv1, which is the default for big-endian PowerPC 64-bit Linux ๐. Overriding the default needs special system support, and it's likely to fail in spectacular ways ๐๐ฅ.-mabi=elfv2โ this one sets the ABI to ELFv2, the default for little-endian PowerPC 64-bit Linux ๐ง. Overriding the default also needs special system support, and it's likely to fail in spectacular ways ๐.-mgnu-attribute,-mno-gnu-attributeโ the first one emits.gnu_attributeassembly directives that set tag/value pairs in a.gnu.attributessection. Those pairs spell out ABI variations in function parameters or return values ๐ฆ.-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems,-mprototypetells the compiler to assume every call to a variable argument function is properly prototyped ๐. Without it, the compiler has to slip in an instruction before every non-prototyped call to set or clear bit 6 of the condition code register ("CR"), so it can tell whether floating-point values get passed in the floating-point registers ๐ญ. 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๐. It's 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're building for a VxWorks system ๐ง.-membโ on embedded PowerPC systems, this sets the "PPC_EMB" bit in the ELF flags header, which signals that eabi extended relocations are being used ๐ซถ.-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems,-meabimakes the compiler adhere to the Embedded Applications Binary Interface (EABI), a set of modifications to the System V.4 specs ๐ . With it, the stack is aligned to an 8-byte boundary, a function__eabigets called frommainto set up the EABI environment, and the-msdataoption can use bothr2andr13to point to two separate small data areas โจ.-mno-eabidoes the opposite: the stack is aligned to a 16-byte boundary, no EABI initialization function gets called frommain, and-msdataonly usesr13to point to a single small data area ๐.-meabiis on by default if you configured GCC with one of thepowerpc*-*-eabi*options ๐.-msdata=eabiโ on System V.4 and embedded PowerPC systems, small initializedconstglobal and static data goes in the.sdata2section, whichr2points to ๐. Small initialized non-constglobal and static data goes in.sdata, whichr13points to ๐. Small uninitialized global and static data goes in.sbss, which sits right next to.sdataโญ. Heads up:-msdata=eabiis incompatible with-mrelocatable๐. It also sets-memb๐ฅ.-msdata=sysvโ on System V.4 and embedded PowerPC systems, small global and static data goes in.sdata, whichr13points to ๐. Small uninitialized global and static data goes in.sbss, next to.sdata๐ง. This one's incompatible with-mrelocatabletoo ๐.-msdata=default,-msdataโ on System V.4 and embedded PowerPC systems, if-meabiis used, this compiles the code the same way as-msdata=eabi๐ . Otherwise, it compiles it the same way as-msdata=sysvโจ.-msdata=dataโ on System V.4 and embedded PowerPC systems, small global data goes in.sdata๐ฆ. Small uninitialized global data goes in.sbss๐ธ. The catch is thatr13doesn't get used to address small data here ๐ซถ. This is the default behaviour unless other-msdataoptions are used ๐.-msdata=none,-mno-sdataโ on embedded PowerPC systems, all initialized global and static data goes in.data, and all uninitialized data goes in.bss๐.-mreadonly-in-sdataโ puts read-only objects in.sdataas well ๐. This is the default โจ.-mblock-move-inline-limit=numโ inlines all block moves (like calls tomemcpyor 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 is target-specific ๐.-mblock-compare-inline-limit=numโ generates non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal to num bytes ๐ซถ. If num is0, all inline expansion (both non-loop and loop) of block compare gets disabled ๐. The default 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 isn't constant, at most num bytes get compared beforememcmpis called to handle the rest of the block ๐. The default is target-specific ๐ฆ.-mstring-compare-inline-limit=numโ compares at most num string bytes with inline code ๐. If the difference or end of string isn't found by the end of the inline compare, a call tostrcmporstrncmptakes care of the rest ๐ธ. The default is 64 bytes ๐.-G numโ on embedded PowerPC systems, puts global and static items that are less than or equal to num bytes 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 ๐ฅ. All modules should be compiled with the same-G numvalue, bestie, or things get messy ๐ .-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-regnamesmakes it not do that ๐ฆ.-mlongcall,-mno-longcallโ by default, the compiler assumes every call is far away, so it uses a longer and more expensive calling sequence ๐. This is required for calls farther than 32 megabytes (33,554,432 bytes) from the current location ๐ซถ. A short call only gets generated if the compiler knows the call can't be that far away โจ. This setting can be overridden by theshortcallfunction attribute, or by#pragma longcall(0)๐.
Some linkers can spot 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 ๐ธ. Adding this feature to the GNU linker for 32-bit PowerPC systems is planned too ๐ง.
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 generates 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 then 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, which supports lazy linking and long calls to functions indlopen'd shared libraries ๐.-mno-pltseqmeans it doesn't implement them that way ๐ซถ. Inline PLT calls are only supported on PowerPC64 ELFv2 and on 32-bit PowerPC systems with newer GNU linkers ๐ฅ. They're enabled by default if support gets detected when configuring GCC, and, for 32-bit PowerPC, if GCC is configured with--enable-securepltโญ. Heads up:-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together ๐.-mtls-markers,-mno-tls-markersโ-mtls-markersmarks calls to__tls_get_addrwith a relocation that specifies the function argument ๐ง.-mno-tls-markersdoesn't do the marking ๐. The relocation lets the linker reliably associate the function call with the argument setup instructions for TLS optimization ๐ฆ, which in turn lets GCC schedule the sequence better ๐โจ.-mrecip,-mno-recipโ okay bestie, this one turns on the reciprocal estimate and reciprocal square root estimate instructions, then adds extra Newton-Raphson steps to win back precision ๐งฎโจ So instead of doing a full divide (or square root and then divide) for floating-point args, GCC can take the faster route ๐๏ธ. You should pair-mrecipwith-ffast-math๐ (or at least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math). The catch: the throughput is usually higher than the non-reciprocal instruction, but the precision can slip by up to 2 ulp for reciprocal square roots ๐ญ (like, the inverse of1.0comes out as0.99999994). Not a vibe for every app, so check your math ๐ค-mrecip=optโ this lets you pick exactly which estimate instructions are allowed ๐optis a comma-separated list, and you can put a!in front of any item to flip it ๐allโ enable all the estimate instructions, every single one ๐ฅdefaultโ enable the default instructions, same as-mrecip๐ธnoneโ disable all estimate instructions, same as-mno-recip๐ โโ๏ธdivโ enable the reciprocal approximation instructions for both single and double precision ๐divfโ enable the single-precision reciprocal approximation instructions ๐ฆdivdโ enable the double-precision reciprocal approximation instructions ๐งrsqrtโ enable the reciprocal square root approximation instructions for both single and double precision โจrsqrtfโ enable the single-precision reciprocal square root approximation instructions ๐rsqrtdโ enable the double-precision reciprocal square root approximation instructions ๐
So, for example, -mrecip=all,!rsqrtd turns on every reciprocal estimate instruction except the FRSQRTE, XSRSQRTEDP, and XVRSQRTEDP ones, which handle the double-precision reciprocal square root math ๐ that's a whole main character move right there ๐
-mrecip-precision,-mno-recip-precisionโ this tells GCC whether to assume (or not assume) that the reciprocal estimate instructions give you higher precision than the PowerPC ABI requires ๐ท Picking-mcpu=power6,-mcpu=power7or-mcpu=power8turns-mrecip-precisionon automatically ๐ซถ Also, 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โ this picks the ABI type for vectorizing intrinsics using an external library ๐ The only type supported right now ismass, which means using IBM's Mathematical Acceleration Subsystem (MASS) libraries to vectorize intrinsics ๐ฅ When you're generating code for power7, GCC emits calls to these functions (that's the whole squad ๐ ):
acosd2, acosf4, acoshd2, acoshf4, asind2, asinf4, asinhd2, asinhf4, atan2d2, atan2f4, atand2, atanf4, atanhd2, atanhf4, cbrtd2, cbrtf4, cosd2, cosf4, coshd2, coshf4, erfcd2, erfcf4, erfd2, erff4, exp2d2, exp2f4, expd2, expf4, expm1d2, expm1f4, hypotd2, hypotf4, lgammad2, lgammaf4, log10d2, log10f4, log1pd2, log1pf4, log2d2, log2f4, logd2, logf4, powd2, powf4, sind2, sinf4, sinhd2, sinhf4, sqrtd2, sqrtf4, tand2, tanf4, tanhd2, tanhf4
Both -ftree-vectorize and -funsafe-math-optimizations also have to be on ๐ And the MASS libraries must be specified at link time, no skipping that step ๐
โโ๏ธ
-mfriz,-mno-frizโ this tells GCC whether to generate thefrizinstruction ๐ฆ It only kicks in when-funsafe-math-optimizationsis on, and it speeds up rounding floating-point values to 64-bit integers and back again โจ Heads up though:frizdoesn't give back the same value if the float is too big to fit in an integer ๐ญ so be careful, bestie-mpointers-to-nested-functions,-mno-pointers-to-nested-functionsโ this makes GCC generate (or skip) code that loads the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems ๐ธ That's when 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๐ง-mpointers-to-nested-functionsis on by default ๐ But if you use-mno-pointers-to-nested-functions, you can't call through pointers to nested functions, or through pointers to functions compiled in other languages that use the static chain ๐-msave-toc-indirect,-mno-save-toc-indirectโ this decides whether GCC saves 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 ๐ If it isn't saved in the prologue, it gets saved just before the call through the pointer ๐ซถ-mno-save-toc-indirectis the default, so that's your baseline ๐-mcompat-align-parm,-mno-compat-align-parmโ this makes GCC generate (or not generate) code that passes structure parameters with a max alignment of 64 bits, so it matches older versions of GCC ๐ฐ๏ธ
Older GCC versions (before 4.9.0) messed up by not aligning a structure parameter on a 128-bit boundary when that structure had a member needing 128-bit alignment ๐ Newer versions fixed it, but if you need to play nice with functions compiled by the older ones, this option is your friend ๐ซถ
-mno-compat-align-parm is the default ๐ธ
-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset,-mstack-protector-guard-symbol=symbolโ these generate stack protection code using a canary at the guard ๐ก๏ธ The supported locations areglobal(for a global canary) ortls(for a per-thread canary in the TLS block, which is the default with GNU libc 2.4 or later) ๐งต
With tls, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset pick the base register used to read the canary, plus the offset from that base register ๐ฏ If you don't set them, the defaults come from the relevant ABI ๐ And -mstack-protector-guard-symbol=symbol overrides the offset with a symbol reference to a canary in the TLS block ๐ฅ
-mpcrel,-mno-pcrelโ this makes GCC generate (or not generate) pc-relative addressing ๐-mpcrelneeds the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) to be enabled first ๐ง-mprefixed,-mno-prefixedโ this makes GCC generate (or not generate) addressing modes that use prefixed load and store instructions โจ-mprefixedrequires-mcpu=power10(or later) to be enabled ๐-mmma,-mno-mmaโ this makes GCC generate (or not generate) the MMA instructions ๐ The-mmaoption requires-mcpu=power10(or later) to be enabled ๐-mrop-protect,-mno-rop-protectโ this makes GCC generate (or not generate) ROP protection instructions when the target processor supports them ๐ก๏ธ Heads up: right now this option disables the shrink-wrap optimization (-fshrink-wrap) ๐ญ-mprivileged,-mno-privilegedโ this makes GCC generate (or not generate) code that runs in privileged state ๐ Use with care, bestie ๐-mblock-ops-unaligned-vsx,-mno-block-ops-unaligned-vsxโ this makes GCC generate (or not generate) unaligned VSX loads and stores for inline expansion ofmemcpyandmemmove๐--param rs6000-vect-unroll-limit=โ the vectorizer checks with target info to decide whether unrolling the main vectorized loop would help, and by how much ๐ This parameter sets the upper bound on how much it'll unroll the main loop ๐ธ The default value isfour๐
๐ธ RX Options ๐ธ
These command-line options are defined for RX targets ๐ฆ
-m64bit-doubles,-m32bit-doublesโ this makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) ๐ The default is-m32bit-doubles, and the reason is that RX floating-point hardware only works on 32-bit values ๐ค-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 only get generated for 32-bit floating-point values, though, so the FPU hardware isn't used for doubles if -m64bit-doubles is in play ๐
If-fpuis enabled,-funsafe-math-optimizationsgets turned on automatically too ๐ That's because the RX FPU instructions are themselves unsafe.
-mcpu=nameโ this picks which type of RX CPU you're targeting ๐ฏ Three types are supported right now: 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 you select it ๐ซถ
-mbig-endian-data,-mlittle-endian-dataโ this stores data (but not code) in big-endian format โจ The default is-mlittle-endian-data, which means data gets stored in little-endian format ๐ท-msmall-data-limit=Nโ this sets the max 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, so it's on the programmer to make sure it doesn't overflow ๐ฌ Also, when the small data area is used, one of the RX's registers (usuallyr13) gets reserved to point to that area, so the compiler can't use it anymore ๐ That can mean slower and/or larger code if variables get pushed onto the stack instead of being held in that register ๐
Note: common variables (ones 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 ๐ง
okay so the default is 0, which means this feature is switched off ๐
โโ๏ธ it's NOT turned on at higher optimization levels (-O2 etc) bc reserving a register can be detrimental ๐ญ so it's up to you to experiment and see if it actually helps your program ๐ฌ for how the register that holds the small data area pointer gets picked, check out the -mpid entry ๐
-msim,-mno-simโ use the simulator runtime ๐ฅ๏ธ the default is the libgloss board-specific runtime-mas100-syntax,-mno-as100-syntaxโ when making assembler output, this makes it use a syntax that's compatible with Renesas's AS100 assembler ๐งต GAS can handle it too, but it has some restrictions, so it's not generated by default-mmax-constant-size=Nโ sets the max size, in bytes, of a constant that can be used as an operand in an RX instruction ๐ RX lets you use constants up to 4 bytes, but a bigger value = a bigger instruction, so sometimes it's smart to limit this ๐ง constants that are too big get tossed into a constant pool and referenced via register indirection ๐ฆ
The value N can be between 0 and 4. A value of 0 (the default) or 4 means constants of any size are allowed โจ
-mrelaxโ turns on linker relaxation ๐ช this is where the linker tries to shrink your program by finding shorter versions of instructions. It's disabled by default-mint-register=Nโ sets how many registers get reserved for fast interrupt handler functions ๐Ncan be between0and41reserves"r13"for the exclusive use of fast interrupt handlers2reserves"r13"and"r12"3reserves"r13","r12"and"r11"4reserves"r13"through"r10"
0 (the default) doesn't reserve any registers ๐ซถ
-msave-acc-in-interruptsโ tells interrupt handler functions to preserve the accumulator register ๐ this is only needed if normal code might use the accumulator, like if it does 64-bit multiplications ๐ข the default is to ignore the accumulator, bc that makes the interrupt handlers faster ๐๏ธ-mpid,-mno-pidโ turns on generation of position independent data ๐ฆ when it's on, any access to constant data is done via an offset from a base address held in a register. This lets the location of constant data get figured out at run time without the executable needing to be relocated, which is a huge win for embedded apps with tight memory constraints ๐ธ data that can be modified isn't affected by this option
heads up: using this feature reserves a register, usually "r13", for the constant data base address ๐ this can make code slower and/or larger, especially in complicated functions
Which register actually gets picked for the constant data base address depends on whether -msmall-data-limit and/or -mint-register are turned on ๐งฉ starting at "r13" and going downwards, registers are allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. So it's totally possible for the small data area register to be "r8" if both -mint-register=4 and -mpid are on the command line ๐คฏ
By default this feature is NOT enabled. You can restore the default with the -mno-pid command-line option ๐
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interruptsโ stops GCC from giving a warning if it finds more than one fast interrupt handler while compiling a file ๐ the default is to warn for each extra fast interrupt handler it finds, bc the RX only supports one such interrupt-mallow-string-insns,-mno-allow-string-insnsโ enables or disables the string manipulation instructions"SMOVF","SCMPU","SMOVB","SMOVU","SUNTIL""SWHILE"and also the"RMPA"instruction ๐งต these might prefetch data, which is NOT safe if you're accessing an I/O register ๐ซ (see section 12.2.7 of the RX62N Group User's Manual for more info ๐)
The default is to allow these instructions. BUT GCC can't reliably detect every situation where a string instruction might touch an I/O register, so they can't be disabled automatically ๐ฌ it's on 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)JSRinstructions to access functions ๐ฏ you can use this when code size goes beyond the range ofBSRinstructions. Note that-mno-jsrdoesn't mean "don't useJSR" ๐ โโ๏ธ it just means any type of branch may be used
Note: the generic GCC command-line option -ffixed-reg has special significance to the RX port when it's used with the "interrupt" function attribute ๐ that attribute marks a function meant to process fast interrupts. GCC makes sure it only uses the registers "r10", "r11", "r12" and/or "r13", and only if the normal use of the corresponding registers has been restricted via the -ffixed-reg or -mint-register command-line options ๐
โจ S/390 and zSeries Options โจ
These are the -m options defined for the S/390 and zSeries architecture ๐ง
-mhard-float,-msoft-floatโ use (or don't use) the hardware floating-point instructions and registers for floating-point operations โก with-msoft-float, functions inlibgcc.ado the floating-point work. With-mhard-float, the compiler generates IEEE floating-point instructions. This is the default ๐-mhard-dfp,-mno-hard-dfpโ use (or don't use) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐ข with-mno-hard-dfp, functions inlibgcc.aare used instead. With-mhard-dfp, the compiler generates decimal-floating-point hardware instructions. This is the default for-march=z9-ecor higher ๐-mlong-double-64,-mlong-double-128โ these 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 into the callee's stack frame ๐ a backchain may be needed to allow debugging with tools that don't understand DWARF call frame information ๐ with-mno-packed-stackin effect, the backchain pointer is stored at the bottom of the stack frame. With-mpacked-stackin effect, the backchain is placed into the topmost word of the 96/160 byte register save area ๐งฑ
In general, code compiled with -mbackchain is call-compatible with code compiled with -mno-backchain. However, using the backchain for debugging usually requires the whole binary to be built with -mbackchain ๐ ๏ธ the combination of -mbackchain, -mpacked-stack and -mhard-float is NOT supported โ to build a linux kernel, use -msoft-float ๐ง
The default is to not maintain the backchain ๐ โโ๏ธ
-mpacked-stack,-mno-packed-stackโ uses (or doesn't use) the packed stack layout ๐ with-mno-packed-stack, the compiler uses all the fields of the 96/160 byte register save area only for their default purpose, so unused fields still take up stack space. With-mpacked-stack, register save slots are densely packed at the top of the register save area, and unused space gets reused for other purposes, which is way 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 combination of -mbackchain, -mpacked-stack and -mhard-float is NOT supported. For 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 using the"bras"instruction to do subroutine calls ๐ this only works reliably if the total executable size does not exceed 64k ๐ the default is to use the"basr"instruction instead, which doesn't have that limitation ๐ซ-m64,-m31โ when-m31is specified, code gets generated compliant to the GNU/Linux for S/390 ABI ๐งญ when-m64is specified, code is generated compliant to the GNU/Linux for zSeries ABI. This lets GCC in particular generate 64-bit instructions ๐ for the s390 targets, the default is-m31, while the s390x targets default to-m64๐-mzarch,-mesaโ with-mzarch, code is generated using the instructions available on z/Architecture ๐๏ธ with-mesa, code is generated using the instructions available on ESA/390. Note that-mesais NOT possible with-m64โ when generating code compliant to the GNU/Linux for S/390 ABI, the default is-mesa. When generating code compliant to the GNU/Linux for zSeries ABI, the default is-mzarch๐ฐ-mhtm,-mno-htmโ-mhtmenables a set of builtins that make use of instructions available with the transactional execution facility, introduced with the IBM zEnterprise EC12 machine generation ๐ธ see S/390 System z Built-in Functions for the details ๐-mhtmis enabled by default when using-march=zEC12๐
Okay so bestie, -mvx turns on the vector extension facility that came with the IBM z13 machine generation ๐. It's giving ABI drama though, because it changes how some vector type values get aligned and how they're passed around in calls ๐
. If vector types show up somewhere the ABI cares about, GCC adds a GAS .gnu_attribute command so the binary gets marked with the ABI it used ๐ซถ. And -mvx is switched on by default whenever you use -march=z13 โจ.
-mvx,-mno-vxโ generate code with the vector extension facility (the one from IBM z13) ๐ฆ. This changes the ABI for some vector type values, so it's a whole vibe with alignment and calling conventions. Adds a GAS.gnu_attributemarker for the ABI in ABI-relevant contexts.-mvxis on by default with-march=z13.-mzvector,-mno-zvectorโ enables vector language extensions and builtins using those same z13 vector instructions ๐. It makesvectorwork as a keyword for declaring vector type variables and arguments ๐. Heads up:vectoronly works when GNU extensions are on, and it won't expand if you ask for strict standard compliance like-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 actually use those, you need to include the header filevecintrin.h๐.-mzvectoris disabled by default.-mmvcle,-mno-mvcleโ generate code using the"mvcle"instruction for block moves ๐. With-mno-mvcle, GCC uses an"mvc"loop instead ๐. Using"mvcle"is the default unless you're optimizing for size.-mdebug,-mno-debugโ print extra debug info while compiling ๐. The default is to not print it ๐ .-march=cpu-typeโ generate code that runs oncpu-type, which is the name of a system representing a certain processor type ๐ฅ๏ธ. The valid values arez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12,z15/arch13,z16/arch14, andnative. The default is-march=z900. Pickingnativeselects the best architecture option for your host processor ๐ง .-march=nativehas no effect if GCC doesn't recognize the processor ๐ฌ.-mtune=cpu-typeโ tune everything applicable in the generated code forcpu-type, except for the ABI and the set of available instructions ๐ฏ. It takes the same list of values as-march. The default is whatever value-marchis using.-mtpf-trace,-mno-tpf-traceโ adds (or doesn't add) TPF OS specific branches to trace routines in the operating system ๐ค๏ธ. This is off by default, even when you're compiling for TPF OS.-mtpf-trace-skip,-mno-tpf-trace-skipโ changes (or doesn't change) the default branch targets enabled by-mtpf-traceso they point to specialized trace routines โญ๏ธ. That gives you the ability to selectively skip function trace entries for TPF OS. This is off by default, even when you're compiling for TPF OS and specifying-mtpf-trace.-mfused-madd,-mno-fused-maddโ uses (or doesn't use) the floating-point multiply and accumulate instructions ๐งฎ. These are generated by default if hardware floating point is in use.-mwarn-framesize=framesizeโ emits a warning if the current function exceeds the given frame size โ ๏ธ. It's a compile-time check, so it doesn't have to be a real problem when the program runs ๐ซ . It's meant to spot functions that are most likely to cause a stack overflow, which makes it 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.-mstack-guard=stack-guard,-mstack-size=stack-sizeโ debugging stack overflow problems ๐. When these are provided, the S/390 back end adds extra instructions to the function prologue that trigger a trap if the stack goesstack-guardbytes abovestack-size. (Remember, the stack on S/390 grows downward ๐.) If you leave outstack-guard, GCC picks the smallest power of 2 larger than the frame size of the compiled function ๐ข. The extra code causes only a little overhead, so it's fine for production-like systems too ๐. The values have to be exact powers of 2, andstack-sizehas to be greater thanstack-guardwithout going over 64k ๐. To be efficient, the extra code assumes the stack starts at an address aligned to the value given bystack-size๐งฉ. Thestack-guardoption can only be used together withstack-size.-mhotpatch=pre-halfwords,post-halfwordsโ if the hotpatch option is enabled, a "hot-patching" function prologue gets generated for all functions in the compilation unit ๐ฅ. The function label is prepended with the given number of two-byte NOP instructions (pre-halfwords, maximum 1000000) ๐ซง. After the label, 2 *post-halfwordsbytes are 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โ generate code for the SH1.-m2โ generate code for the SH2.-m2eโ generate code for the SH2e.-m2a-nofpuโ generate code for the SH2a without FPU, or for an SH2a-FPU in a way that the floating-point unit isn't used.-m2a-single-onlyโ generate code for the SH2a-FPU so that no double-precision floating-point operations are used.-m2a-singleโ generate code for the SH2a-FPU, assuming the floating-point unit is in single-precision mode by default.-m2aโ generate code for the SH2a-FPU, assuming the floating-point unit is in double-precision mode by default.-m3โ generate code for the SH3.-m3eโ generate code for the SH3e.-m4-nofpuโ generate code for the SH4 without a floating-point unit.-m4-single-onlyโ generate code for the SH4 with a floating-point unit that only supports single-precision arithmetic.-m4-singleโ generate code for the SH4, assuming the floating-point unit is in single-precision mode by default.-m4โ generate code for the SH4.-m4-100โ generate code for SH4-100.-m4-100-nofpuโ generate code for SH4-100 in a way that the floating-point unit isn't used.-m4-100-singleโ generate code for SH4-100, assuming the floating-point unit is in single-precision mode by default.-m4-100-single-onlyโ generate code for SH4-100 so that no double-precision floating-point operations are used.-m4-200โ generate code for SH4-200.-m4-200-nofpuโ generate code for SH4-200 without the floating-point unit being used.-m4-200-singleโ generate code for SH4-200, assuming the floating-point unit is in single-precision mode by default.-m4-200-single-onlyโ generate code for SH4-200 so that no double-precision floating-point operations are used.-m4-300โ generate code for SH4-300.-m4-300-nofpuโ generate code for SH4-300 without the floating-point unit being used.-m4-300-singleโ generate code for SH4-300 so that no double-precision floating-point operations are used.-m4-300-single-onlyโ generate code for SH4-300 so that no double-precision floating-point operations are used.-m4-340โ generate code for SH4-340 (no MMU, no FPU) ๐.-m4-500โ generate code for SH4-500 (no FPU). It passes-isa=sh4-nofputo the assembler ๐งฉ.-m4a-nofpuโ generate code for the SH4al-dsp, or for an SH4a in a way that the floating-point unit isn't used.-m4a-single-onlyโ generate code for the SH4a so that no double-precision floating-point operations are used.-m4a-singleโ generate code for the SH4a, assuming the floating-point unit is in single-precision mode by default.-m4aโ generate 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 ๐ซ .-mbโ compile code for the processor in big-endian mode ๐.-mlโ compile code for the processor in little-endian mode ๐.-mdalignโ align doubles at 64-bit boundaries. Heads up: this changes the calling conventions, so some functions from the standard C library won't work unless you recompile them first with-mdalign๐จ.-mrelaxโ shorten some address references at link time, when possible. It uses the linker option-relax๐.-mbigtableโ use 32-bit offsets in"switch"tables. The default is to use 16-bit offsets ๐.-mbitopsโ enables the use of bit manipulation instructions on SH2A ๐ง .-mfmovdโ enables the use of the instruction"fmovd". Check-mdalignfor alignment constraints ๐.-mrenesasโ comply with the calling conventions defined by Renesas ๐ท๏ธ.-mno-renesasโ comply with the calling conventions defined for GCC 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โ control the IEEE compliance of floating-point comparisons, which affects how cases with unordered comparison results are handled ๐งฎ. By default,-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled,-mno-ieeeis implicitly set, which gives you faster floating-point greater-equal and less-equal comparisons ๐๏ธ. The implicit settings can be overridden by specifying either-mieeeor-mno-ieeeexplicitly ๐ .-minline-ic_invalidateโ okay bestie, this one inlines code that invalidates instruction cache entries right after it sets up nested function trampolines ๐งโจ It does nothing if-musermodeis on and your code gen option (like-m4) doesn't allow theicbiinstruction ๐ If your code gen option doesn't allowicbiand-musermodeis not on, the inlined code pokes the instruction cache address array directly with an associative write.
๐ That write needs privileged mode at run time, AND it fails if the cache line got mapped via the TLB and then became unmapped. Be careful out there, babe!
-misizeโ dump instruction size and location in the assembly code ๐๐-mpadstructโ this one is deprecated, so let's not be doing it ๐ โโ๏ธ It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI.-matomic-model=modelโ this is where you set the model for atomic operations, plus any extra parameters, as a comma separated list ๐ For the full tea on atomic built-in functions, check __atomic Builtins. Here are the models and parameters that are supported:noneโ turns off 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 need extra help from the system's interrupt/exception handling code and are only suitable for SH3* and SH4* single-core systems. This is turned on by default when the target issh*-*-linux*and SH3* or SH4*. On SH4A, it also partially uses the hardware atomic instructionsmovli.landmovco.lfor more efficient code, 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 be used on SH1* and SH2* targets. It needs extra support from the interrupt/exception handling code and is only suitable for single-core systems. When you use this model, thegbr-offset=parameter has to be specified 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. You don't need extra support from the interrupt/exception handling code for this one. It's enabled 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 access to 8 or 16 bit variables gets emulated with 32 bit accesses. Code compiled with this option is also compatible with other software atomic model interrupt/exception handling systems if it runs on an SH4A system. No additional support from the interrupt/exception handling code is required for this model.gbr-offset=โ this parameter sets 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 gets 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๐ซ Notice that depending on your hardware and software setup, this can hurt overall performance because of the operand cache line flushes that thetas.binstruction implies.
โ ๏ธ On multi-core SH4A processors, the tas.b instruction has to be used with caution, since it can cause data corruption with certain cache configurations. Not the vibe!
-mprefergotโ when generating position-independent code, emits function calls using the Global Offset Table instead of the Procedure Linkage Table ๐ธ-musermode,-mno-usermodeโ-musermodemeans don't let the compiler generate privileged mode code ๐ โโ๏ธ-mno-usermodemeans go ahead and allow it ๐ Specifying-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*,-musermodehas no effect, since there's no user mode there ๐คทโโ๏ธ-multcost=numberโ sets the cost to assume for a multiply insn ๐งฎ-mdiv=strategyโ sets the division strategy used for integer division operations ๐ฐstrategycan be one of:call-div1โ calls a library function that uses the single-step division instructiondiv1to do the operation ๐ซถ Division by zero calculates an unspecified result and does not 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 ๐ฅ Division by zero causes a floating-point exception. This is the default for SHcompact with FPU. Specifying this for targets that don't have a double precision FPU defaults tocall-div1.call-tableโ calls a library function that uses a lookup table for small divisors and thediv1instruction with case distinction for larger divisors ๐ Division by zero calculates an unspecified result and does not trap. This is the default for SH4. Specifying this for targets that don't have dynamic shift instructions defaults tocall-div1.
When a division strategy hasn't been specified, the default gets picked based on the current target ๐ฏ For SH2A, the default strategy 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 generally beneficial 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, which means the register allocator can't use them ๐ This is useful when compiling kernel code. A register range is two registers separated by a dash, and you can specify multiple ranges separated by a comma.-mbranch-cost=numโ assumesnumis the cost for a branch instruction ๐ฟ Higher numbers make the compiler try to generate more branch-free code if possible. If you don't specify it, the value is picked based on the processor type being compiled for.-mzdcbranch,-mno-zdcbranchโ-mzdcbranchassumes that zero displacement conditional branch instructionsbtandbfare fast โก With it, the compiler prefers zero displacement branch code sequences. This is enabled by default when generating code for SH4 and SH4A. You can explicitly turn it off with-mno-zdcbranch๐ โโ๏ธ (-mno-zdcbranchmeans do not assume they're fast.)-mcbranch-force-delay-slotโ forces the use of delay slots for conditional branches, which stuffs the delay slot with anopif a suitable instruction can't be found ๐ด This is disabled by default. You can enable it 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 ๐ง-mno-fused-maddgenerates code that does not use them ๐ โโ๏ธ 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 (-mfsca) or disallows (-mno-fsca) the compiler from emitting thefscainstruction for sine and cosine approximations ๐ The option-mfscamust be used in combination with-funsafe-math-optimizations. It's enabled by default when generating code for SH4A. Using-mno-fscadisables sine and cosine approximations even if-funsafe-math-optimizationsis in effect.-mfsrra,-mno-fsrraโ allows (-mfsrra) or disallows (-mno-fsrra) the compiler from emitting thefsrrainstruction for reciprocal square root approximations ๐ The option-mfsrramust be used with-funsafe-math-optimizationsand-ffinite-math-only. It's enabled by default when generating code for SH4A. Using-mno-fsrradisables reciprocal square root approximations even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect.-mpretend-cmoveโ prefers zero-displacement conditional branches for conditional move instruction patterns ๐โโ๏ธ This can result in faster code 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 generated by the Solaris assembler ๐งน This is only necessary when object files use ISA extensions that the current machine doesn't support, but check at runtime whether or not to use them.-mimpure-textโ used in addition to-shared, this tells the compiler to not pass-z textto the linker when linking a shared object ๐ฆ With this option, you can link position-dependent code into a shared object. Iconic, honestly.
bestie, okay so -mimpure-text silences the "relocations remain against allocatable but non-writable sections" linker error ๐ but ngl it's a total trap ๐. The necessary relocations trigger copy-on-write, and the shared object is NOT actually shared across processes ๐ญ. So instead of reaching for -mimpure-text, compile all your source code with -fpic or -fPIC ๐ซถโจ.
On Solaris 2, you also get this one in addition to the above:
-pthreadsโ literally just a synonym for-pthread๐
๐ธ SPARC Options ๐ธ
These -m options are supported on the SPARC ๐ฆ
-mno-app-regs,-mapp-regsโ Okay,-mapp-regsmakes the output use global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐ Like global register 1, each of 2 through 4 is then treated as an allocable register that gets clobbered by function calls. This is the default โจ. If you want to be fully SVR4 ABI-compliant (with a bit of a performance hit, sadly ๐ฅฒ), use-mno-app-regs. You should compile libraries and system software with this one ๐ซถ.-mflat,-mno-flatโ With-mflat, the compiler skips the save/restore instructions and uses a "flat" or single register window model ๐ง This model is compatible with the regular register window model. The local registers and the input registers (0--5) are still treated as "call-saved" registers and get saved on the stack as needed. With-mno-flat(the default ๐), the compiler generates save/restore instructions, except for leaf functions. This is the normal operating mode.-mfpu,-mhard-floatโ Generates output with floating-point instructions. This is the default, obviously ๐.-mno-fpu,-msoft-floatโ Generates output with library calls for floating point instead ๐.
โ ๏ธ Warning: the requisite libraries are NOT available for all SPARC targets ๐. Normally the facilities of the machine's usual C compiler are used, but that can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation. The embedded targetssparc-*-aoutandsparclite-*-*DO provide software floating-point support ๐.
-msoft-float changes the calling convention in the output file, so it's only useful if you compile ALL of a program with this option ๐ญ. In particular, you need to compile libgcc.a (the library that comes with GCC) with -msoft-float for this to work.
-mhard-quad-floatโ Generates output with quad-word (long double) floating-point instructions ๐ฅ.-msoft-quad-floatโ Generates output with library calls for quad-word (long double) floating-point instructions. The functions called are the ones specified in the SPARC ABI. This is the default ๐ .
As of this writing, there are no SPARC implementations with hardware support for the quad-word floating-point instructions ๐ญ. They all invoke a trap handler for one of these instructions, and then the trap handler emulates the effect. Because of that trap handler overhead, it's MUCH slower than calling the ABI library routines. Which is exactly why -msoft-quad-float is the default ๐.
-mno-unaligned-doubles,-munaligned-doublesโ-mno-unaligned-doublesassumes doubles have 8-byte alignment. This is the default โจ.
With -munaligned-doubles, GCC only assumes doubles have 8-byte alignment if they're contained in another type, or if they have an absolute address. Otherwise, it assumes 4-byte alignment ๐ฆ. Using this option avoids some rare compatibility problems with code generated by other compilers. It's not the default though, because it costs performance, especially for floating-point code ๐ฅฒ.
-muser-mode,-mno-user-modeโ-mno-user-modeis the default ๐. It means no code that can only run in supervisor mode gets generated. This is only relevant for thecasainstruction emitted for the LEON3 processor ๐ง.-mfaster-structs,-mno-faster-structsโ With-mfaster-structs, the compiler assumes structures should have 8-byte alignment. That lets it use pairs oflddandstdinstructions for copies in structure assignment, instead of twice as manyldandstpairs ๐. BUT this changed alignment directly violates the SPARC ABI ๐. So it's only meant for targets where the developer acknowledges their code isn't directly in line with the ABI rules.-mstd-struct-return,-mno-std-struct-returnโ With-mstd-struct-return, the compiler generates checking code in functions that return structures or unions. It detects size mismatches between the two sides of function calls, as per the 32-bit ABI ๐. The default is-mno-std-struct-return. This option has no effect in 64-bit mode.-mlra,-mno-lraโ Enables Local Register Allocation ๐ธ. This has been the default for SPARC since GCC 7, so you need to pass-mno-lraif you want the old Reload.-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for machine type cpu_type ๐. 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 support the value native, which picks the best architecture option for the host processor โจ. -mcpu=native has no effect if GCC doesn't recognize the processor ๐.
Default instruction scheduling parameters get used for values that select an architecture rather than an implementation. Those are v7, v8, sparclite, sparclet, and v9 ๐ง.
Here's the lineup of each supported architecture and its implementations ๐:
v7:cypress,leon3v7v8:supersparc,hypersparc,leon,leon3,leon5sparclite:f930,f934,sparclite86xsparclet:tsc701v9:ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of SPARC ๐. With -mcpu=cypress, the compiler also optimizes for the Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series. This is also appropriate for the older SPARCStation 1, 2, IPX etc. ๐ฆ
With -mcpu=v8, GCC generates code for the V8 variant. The only difference from V7 code is that the compiler emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not in SPARC-V7 ๐
. With -mcpu=supersparc, it's additionally optimized for the SuperSPARC chip, as used in the SPARCStation 10, 1000 and 2000 series.
With -mcpu=sparclite, GCC generates code for the SPARClite variant. This adds the integer multiply, integer divide step, and scan ("ffs") instructions that exist in SPARClite but not in SPARC-V7 ๐ฅ. With -mcpu=f930, the compiler also optimizes for the Fujitsu MB86930 chip, which is the original SPARClite, with no FPU. With -mcpu=f934, it's optimized for the Fujitsu MB86934, the more recent SPARClite with FPU.
With -mcpu=sparclet, GCC generates code for the SPARClet variant. This adds the integer multiply, multiply/accumulate, integer divide step, and scan ("ffs") instructions that exist in SPARClet but not in SPARC-V7 ๐ง. With -mcpu=tsc701, it's additionally optimized for the TEMIC SPARClet chip.
With -mcpu=v9, GCC generates code for the V9 variant ๐. This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers, and conditional move instructions. Then the chip-specific extras stack up: -mcpu=ultrasparc optimizes for the Sun UltraSPARC I/II/IIi chips, -mcpu=ultrasparc3 for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips, -mcpu=niagara for Sun UltraSPARC T1 chips, -mcpu=niagara2 for Sun UltraSPARC T2 chips, -mcpu=niagara3 for Sun UltraSPARC T3 chips, and -mcpu=niagara4 for Sun UltraSPARC T4 chips ๐ญ. -mcpu=niagara7 optimizes for Oracle SPARC M7 chips, and -mcpu=m8 optimizes for Oracle M8 chips ๐.
-mtune=cpu_typeโ Sets the instruction scheduling parameters for machine type cpu_type, but does NOT set the instruction set or register set the way-mcpu=cpu_typedoes ๐.
The same values work for -mtune=cpu_type as for -mcpu=cpu_type, but the only useful ones are the values that select a particular CPU implementation ๐. Those are cypress, supersparc, hypersparc, leon, leon3, leon3v7, leon5, f930, f934, sparclite86x, tsc701, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7 and m8. With native Solaris and GNU/Linux toolchains, native can be used too โจ.
-mv8plus,-mno-v8plusโ With-mv8plus, GCC generates code for the SPARC-V8+ ABI ๐ฆ. The difference from the V8 ABI is that the global and out registers are considered 64 bits wide. This is enabled by default on Solaris in 32-bit mode for all SPARC-V9 processors ๐ .-mvis,-mno-visโ With-mvis, GCC generates code that takes advantage of the UltraSPARC Visual Instruction Set extensions ๐ฅ. The default is-mno-vis.-mvis2,-mno-vis2โ With-mvis2, GCC generates code that takes advantage of version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐. The default is-mvis2when targeting a CPU that supports such instructions, like UltraSPARC-III and later. Setting-mvis2also sets-mvis.-mvis3,-mno-vis3โ With-mvis3, GCC generates code that takes advantage of version 3.0 of the UltraSPARC Visual Instruction Set extensions ๐ง. The default is-mvis3when targeting a CPU that supports such instructions, like niagara-3 and later. Setting-mvis3also sets-mvis2and-mvis๐.-mvis4,-mno-vis4โ okay so-mvis4makes GCC write code that uses version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐ It's on by default when you target a cpu that has them, like niagara-7 and later โจ Turning on-mvis4also turns on-mvis3,-mvis2and-mvis๐ฆ-mvis4b,-mno-vis4bโ with-mvis4b, GCC uses version 4.0 of the UltraSPARC VIS extensions plus the extra VIS instructions added in the Oracle SPARC Architecture 2017 ๐ฅ The default is-mvis4bfor cpus that support them, like m8 and later ๐ Setting-mvis4balso sets-mvis4,-mvis3,-mvis2and-mvis๐ซถ-mcbcond,-mno-cbcondโ with-mcbcond, GCC uses the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ธ It's the default when targeting a CPU that has them, like Niagara-4 and later ๐-mfmaf,-mno-fmafโ with-mfmaf, GCC uses the UltraSPARC Fused Multiply-Add Floating-point instructions ๐ง Default when targeting a CPU that supports them, like Niagara-3 and later โญ-mfsmuld,-mno-fsmuldโ with-mfsmuld, GCC uses the Floating-point Multiply Single to Double (FsMULd) instruction ๐ฆ The default is-mfsmuldwhen targeting a CPU that supports the architecture versions V8 or V9 with FPU, except-mcpu=leon๐-mpopc,-mno-popcโ with-mpopc, GCC uses the UltraSPARC Population Count instruction ๐ Default when targeting a CPU that has it, like Niagara-2 and later ๐-msubxc,-mno-subxcโ with-msubxc, GCC uses the UltraSPARC Subtract-Extended-with-Carry instruction ๐ It's the default for a CPU that has it, like 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โ generate 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โ set 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 each 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 can be linked anywhere in memory ๐ The text and data segments must be less than 2GB in size, and the data segment must be located within 2GB of the text segment ๐embmedanyโ the Medium/Anywhere code model for embedded systems: 64-bit addresses, and the text and data segments must be less than 2GB in size ๐ง Both can start anywhere in memory, which gets decided 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โ set the memory model the processor runs with, to one of these ๐defaultโ the default memory model for the processor and operating system โจrmoโ Relaxed Memory Order ๐ฆpsoโ Partial Store Order ๐ฅtsoโ Total Store Order ๐scโ Sequential Consistency ๐ซถ
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, as set in the processor's PSTATE.MM field ๐ธ
-mstack-bias,-mno-stack-biasโ with-mstack-bias, GCC assumes the stack pointer (and the frame pointer, if there is one) is 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.identassembler directive in the output ๐-Qnโ refrains from adding.identdirectives to the output file (this 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โ does not optimize (or does optimize) basic blocks that use the same index pointer 4 or more times to copy the pointer into theepregister, and use the shortersldandsstinstructions โญ The-mepoption is on by default if you optimize ๐-mno-prolog-function,-mprolog-functionโ does not use (or does use) external functions to save and restore registers at the prologue and epilogue of a function ๐ 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 theepregister 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 thegpregister 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, no matter which processor variant is the target ๐ฅ
-mdisable-callt,-mno-disable-calltโ suppresses generation of theCALLTinstruction 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โ disables (or re-enables) the generation of PC-relative jump instructions ๐ฆ-msoft-float,-mhard-floatโ disables (or re-enables) the generation of hardware floating point instructions โญ This option only matters 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 ๐ง 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__ is defined ๐
-mgcc-abiโ okay so this one turns on the old GCC flavour of the V850 ABI ๐ With this version, the rules are:- Integer sized structures and unions get returned in register
r10๐ - Large structures and unions (more than 8 bytes in size) get passed by reference ๐ฆ
- Functions get aligned to 32-bit boundaries, unless you're optimizing for size ๐ธ
- The
-m8byte-aligncommand-line option is not supported ๐ - The
-mdisable-calltcommand-line option is supported, but it's not enabled by default ๐
- Integer sized structures and unions get returned in register
When this version of the ABI is on, the C preprocessor symbol __V850_GCC_ABI__ gets defined โจ
-m8byte-align,-mno-8byte-alignโ this letsdoubleandlong longget aligned on 8-byte boundaries ๐ By default, everything gets capped at 4-byte alignment, so this is the glow-up option. When-m8byte-alignis in effect, the C preprocessor symbol__V850_8BYTE_ALIGN__is defined ๐-mbig-switchโ generates code that's suitable for big switch tables ๐ง Only use this if the assembler or linker is yelling about out of range branches inside a switch table ๐ญ-mapp-regsโ this makes the compiler user2andr5in its generated code. This is the default, so you're already set ๐ซถ-mno-app-regsโ this one treatsr2andr5as fixed registers instead ๐
โจ VAX Options โจ
These -m options are defined for the VAX ๐ฆ
-munixโ don't output certain jump instructions (aobleqand 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 ๐-mgโ outputs code for G-format floating-point numbers instead of D-format ๐-mlra,-mno-lraโ these enable Local Register Allocation. It's still experimental for the VAX, so by default the compiler uses standard reload ๐งช
โจ Visium Options โจ
These -m options are defined for the Visium ๐ธ
-mdebugโ if your program does file I/O and is headed for an MCM target, link it 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โ if your program does file I/O and is destined for the simulator, link it with this option ๐ฅ๏ธ It 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 instead ๐งฎ
-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-floatin order for this to work.
-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for machine typecpu_type. The supported values forcpu_typearemcm,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 typecpu_type, but doesn't set the instruction set or register set that-mcpu=cpu_typewould ๐ฏ-msv-modeโ generates code for supervisor mode, where there are no restrictions on access to general registers. This is the default ๐-muser-modeโ generates code for user mode, where access to some general registers is forbidden. On the GR5, registersr24tor31can't be accessed in this mode. On the GR6, only registersr29tor31are affected ๐ซ
โจ VMS Options โจ
These -m options are defined for the VMS implementations ๐ป
-mvms-return-codesโ returns VMS condition codes frommain. The default is to return POSIX-style condition (e.g. error) codes ๐-mdebug-main=prefixโ flags the first routine whose name starts withprefixas the main routine for the debugger ๐-mmalloc64โ defaults to 64-bit memory allocation routines ๐ง-mpointer-size=sizeโ sets the default size of pointers. The possible options forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers. The latter option disablespragma pointer_size๐
โจ VxWorks Options โจ
The options in this section are defined for all VxWorks targets ๐ธ Options specific to the target hardware are listed with the other options for that target.
-mrtpโ 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. This isn't 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, and-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 it's 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 typecpu-type. Unlike-mtune=cpu-type, which merely tunes the generated code for the specifiedcpu-type,-march=cpu-typelets GCC 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 ๐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 that micro-architecture level ๐ Since thesecpu-typevalues don't have a corresponding-mtunesetting, using-marchwith them enables generic tuning. Specific tuning can be enabled using the-mtune=other-cpu-typeoption with an appropriateother-cpu-typevalue ๐๏ธ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 ๐i686โ when used with-march, the Pentium Pro instruction set is used, so the code runs on all i686 family chips ๐ When used 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. It's 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โ 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โ 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โ the Intel Ivy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND and F16C instruction set support ๐haswellโ the Intel Haswell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE and HLE instruction set support ๐
broadwell๐ธ: Intel Broadwell CPU is giving 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,MOVBE,HLE,RDSEED,ADCXandPREFETCHWinstruction set support ๐skylake๐ฆ: Intel Skylake CPU brings 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVESandSGXinstruction set support โจbonnell๐ง: Intel Bonnell CPU has 64-bit extensions plusMOVBE,MMX,SSE,SSE2,SSE3andSSSE3instruction set support, and that's the whole vibe ๐silvermont๐: Intel Silvermont CPU comes with 64-bit extensions plusMOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,CX16,SAHF,FXSR,PCLMUL,PREFETCHWandRDRNDinstruction set support ๐goldmont๐: Intel Goldmont CPU is so extra with 64-bit extensions plusMOVBE,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 keeps the glow up going with 64-bit extensions plusMOVBE,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 has 64-bit extensions plusMOVBE,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 is literally a whole forest of features, with 64-bit extensions plusMOVBE,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 has the exact same feature set as Sierra Forest, so 64-bit extensions plusMOVBE,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 is the newest glow up on this list, with 64-bit extensions plusMOVBE,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,ENQCMD,UINTR,AVXIFMA,AVXVNNIINT8,AVXNECONVERT,CMPCCXADD,AVXVNNIINT16,SHA512,SM3,SM4,USER_MSRandPREFETCHIinstruction set support ๐knl๐ธ: Intel Knight's Landing CPU brings 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AVX512PF,AVX512ER,AVX512F,AVX512CDandPREFETCHWT1instruction set support ๐ฅknm๐ฆ: Intel Knights Mill CPU has 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AVX512PF,AVX512ER,AVX512F,AVX512CDandPREFETCHWT1,AVX5124VNNIW,AVX5124FMAPSandAVX512VPOPCNTDQinstruction set support โจskylake-avx512๐ง: Intel Skylake Server CPU comes with 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVES,SGX,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQandAVX512CDinstruction set support ๐cannonlake๐: Intel Cannonlake Server CPU has 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVES,SGX,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,PKU,AVX512VBMI,AVX512IFMAandSHAinstruction set support ๐icelake-client๐: Intel Icelake Client CPU is serving 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,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,RDPIDandAVX512VPOPCNTDQinstruction set support ๐ซถicelake-server๐: Intel Icelake Server CPU has 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,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,WBNOINVDandCLWBinstruction set support ๐ธcascadelake๐: Intel Cascadelake CPU comes with 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVES,SGX,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CDandAVX512VNNIinstruction set support ๐cooperlake๐ฅ: Intel cooperlake CPU is serving 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVES,SGX,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VNNIandAVX512BF16instruction set support โญtigerlake๐ง: Intel Tigerlake CPU has 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,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,AVX512VP2INTERSECTandKEYLOCKERinstruction set support ๐sapphirerapids๐ : Intel sapphirerapids CPU is the main character with 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,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-FP16andAVX512BF16instruction set support ๐ซถalderlake๐: Intel Alderlake CPU has 64-bit extensions plusMOVBE,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,WIDEKLandAVX-VNNIinstruction set support ๐ฆrocketlake๐ธ: Intel Rocketlake CPU comes with 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,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,PKU,AVX512VBMI,AVX512IFMA,SHA,AVX512VNNI,GFNI,VAES,AVX512VBMI2,VPCLMULQDQ,AVX512BITALG,RDPIDandAVX512VPOPCNTDQinstruction set support โจgraniterapids๐: Intel graniterapids CPU is the newest queen on the list, with 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,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-FP16andPREFETCHIinstruction set support ๐graniterapids-dโ ๐ธ okay bestie, this is the Intel graniterapids D CPU and it is loaded. You get 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,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,PREFETCHIandAMX-COMPLEXinstruction set support. ๐ โจarrowlakeโ ๐ฆ the Intel Arrow Lake CPU, also giving main character energy. It has 64-bit extensions plusMOVBE,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,UINTR,AVXIFMA,AVXVNNIINT8,AVXNECONVERTandCMPCCXADDinstruction set support. ๐arrowlake-sโ ๐ the Intel Arrow Lake S CPU, which is basically arrowlake's glow-up. It has 64-bit extensions plusMOVBE,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,UINTR,AVXIFMA,AVXVNNIINT8,AVXNECONVERT,CMPCCXADD,AVXVNNIINT16,SHA512,SM3andSM4instruction set support. ๐งpantherlakeโ ๐ the Intel Panther Lake CPU, and it's giving a lot. It has 64-bit extensions plusMOVBE,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,UINTR,AVXIFMA,AVXVNNIINT8,AVXNECONVERT,CMPCCXADD,AVXVNNIINT16,SHA512,SM3,SM4andPREFETCHIinstruction set support. ๐ฅk6โ ๐ the AMD K6 CPU, a classic withMMXinstruction set support. Vintage queen. ๐k6-2,k6-3โ ๐ง improved versions of the AMD K6 CPU, withMMXand3DNow!instruction set support.athlon,athlon-tbirdโ โญ the AMD Athlon CPU withMMX,3dNOW!, enhanced3DNow!andSSEprefetch instructions support. Iconic.athlon-4,athlon-xp,athlon-mpโ ๐ฅ upgraded AMD Athlon CPUs withMMX,3DNow!, enhanced3DNow!and fullSSEinstruction set support. Level up, no cap.k8,opteron,athlon64,athlon-fxโ ๐ processors based on the AMD K8 core withx86-64instruction set support, including the AMD Opteron, Athlon 64, and Athlon 64 FX processors. (This one supersetsMMX,SSE,SSE2,3DNow!, enhanced3DNow!and 64-bit instruction set extensions.) ๐ซถk8-sse3,opteron-sse3,athlon64-sse3โ ๐ improved versions of the AMD K8 cores withSSE3instruction set support.amdfam10,barcelonaโ ๐ธ CPUs based 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 based 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 based 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 based 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โ ๐ง the IDT WinChip C6 CPU, which gets treated the same way as ani486but with extraMMXinstruction set support. ๐winchip2โ ๐ the IDT WinChip 2 CPU, also handled the same way as ani486, plus extraMMXand3DNow!instruction set support. ๐c3โ ๐ the VIA C3 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.) ๐ญc3-2โ ๐ฆ the VIA C3-2 (Nehemiah/C5XL) CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.) ๐ธc7โ โจ the VIA C7 (Esther) CPU withMMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) ๐ซถsamuel-2โ ๐ the VIA Eden Samuel 2 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.) ๐งnehemiahโ ๐ฅ the VIA Eden Nehemiah CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.) ๐estherโ ๐ the VIA Eden Esther CPU withMMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) ๐eden-x2โ ๐ธ the VIA Eden X2 CPU withx86-64,MMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) โจeden-x4โ ๐ the VIA Eden X4 CPU withx86-64,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,AVXandAVX2instruction set support. (No scheduling is implemented for this chip.) ๐ฅnanoโ ๐ the generic VIA Nano CPU withx86-64,MMX,SSE,SSE2,SSE3andSSSE3instruction set support. (No scheduling is implemented for this chip.) ๐nano-1000โ ๐ฆ the VIA Nano 1xxx CPU withx86-64,MMX,SSE,SSE2,SSE3andSSSE3instruction set support. (No scheduling is implemented for this chip.) ๐ซถnano-2000โ ๐ง the VIA Nano 2xxx CPU withx86-64,MMX,SSE,SSE2,SSE3andSSSE3instruction set support. (No scheduling is implemented for this chip.) ๐nano-3000โ โญ the VIA Nano 3xxx CPU withx86-64,MMX,SSE,SSE2,SSE3,SSSE3andSSE4.1instruction set support. (No scheduling is implemented for this chip.) ๐nano-x2โ ๐ธ the VIA Nano Dual Core CPU withx86-64,MMX,SSE,SSE2,SSE3,SSSE3andSSE4.1instruction set support. (No scheduling is implemented for this chip.) ๐nano-x4โ ๐ the VIA Nano Quad Core CPU withx86-64,MMX,SSE,SSE2,SSE3,SSSE3andSSE4.1instruction set support. (No scheduling is implemented for this chip.) ๐lujiazuiโ ๐ the ZHAOXIN lujiazui CPU withx86-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,RDSEEDinstruction set support. ๐ซถโจyongfengโ okay this one is a ZHAOXIN yongfeng CPU ๐ It supports thex86-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, LZCNTinstruction sets, so it's giving full loadout โจgeodeโ AMD Geode embedded processor withMMXand3DNow!instruction set support ๐ธ
๐ -mtune=cpu-type
-mtune=cpu-typeโ tune everything applicable in the generated code to cpu-type, but leave the ABI and the set of available instructions alone ๐ฆ Picking a specific cpu-type schedules things properly for that exact chip. The compiler still won't generate code 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=pentium4gives you code tuned for Pentium 4 that still runs on i686 machines. Slay ๐
The choices for cpu-type are the same as for -march. On top of that, -mtune has 2 extra choices:
genericโ produces code optimized for the most common IA32/AMD64/EM64T processors ๐ If you know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=generic. But if you have no idea what CPU your users will have, this is the one to pick.- As new processors hit the market, this option's behavior changes. So if you upgrade to a newer GCC, the code generation controlled by this option shifts to match whichever processors are most common when that GCC version gets released ๐
- There's no
-march=genericbecause-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 the processor (or, in this case, the collection 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 app to perform well on both Haswell and Silvermont, this is your option.- As new Intel processors get deployed, this option's behavior changes. So if you upgrade GCC, the code generation controlled by it will reflect the most current Intel processors at the time that GCC version is released ๐
- There's no
-march=inteloption because-marchis about the instruction set the compiler can use, and there's no common instruction set that works on all processors.-mtuneis about the processor (or collection of processors) the code is optimized for.
-mcpu=cpu-typeโ a deprecated synonym for-mtune๐ Old habit, new vibes, so maybe switch to-mtune.
๐ธ -mfpmath=unit
-mfpmath=unitโ generates floating-point arithmetic for the selected unit โจ The choices for unit are:387โ uses the standard 387 floating-point coprocessor, which is on the majority of chips and emulated on the rest ๐ซถ Code compiled this way runs almost everywhere. The temporary results are computed in 80-bit precision instead of the precision the type specifies, so you can get slightly different results compared to most other chips. Check-ffloat-storefor the more detailed rundown.- This is the default choice for non-Darwin x86-32 targets ๐
sseโ uses scalar floating-point instructions from the SSE instruction set ๐ฅ This set 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 the SSE instruction set only does single-precision arithmetic, so double and extended-precision arithmetic still go through 387. A later version, found only in Pentium 4 and AMD x86-64 chips, supports double-precision arithmetic too.- For the x86-32 compiler, you must use
-march=cpu-type,-msseor-msse2switches to enable SSE extensions and make this option work. For the x86-64 compiler, these extensions are enabled by default ๐ - The resulting code should be considerably faster in most cases and avoid the numerical instability problems of 387 code. Heads up though: it may break some existing code that expects temporaries to be 80 bits ๐ญ
- This is the default choice for the x86-64 compiler and Darwin x86-32 targets. It's also the default choice for x86-32 targets with the SSE2 instruction set when
-ffast-mathis enabled ๐
- For the x86-32 compiler, you must use
sse,387,sse+387,bothโ these try to use both instruction sets at once ๐ฆ That effectively doubles the amount of available registers and, on chips with separate execution units for 387 and SSE, the execution resources too. Use this one with care, because it's still experimental. The GCC register allocator doesn't model separate functional units well, which can lead to unstable performance ๐
๐ง Assembly, IEEE, and 80387 vibes
-masm=dialectโ outputs assembly instructions in the selected dialect, and also decides which dialect is used for basicasmand extendedasm๐ Supported choices (in dialect order) areattorintel. The default isatt. Darwin doesn't supportintel๐-mieee-fp,-mno-ieee-fpโ control whether or not the compiler uses IEEE floating-point comparisons ๐ These handle the case where the result of a comparison is unordered correctly.-m80387,-mhard-floatโ generate output containing 80387 instructions for floating point โญ-mno-80387,-msoft-floatโ generate output that uses library calls for floating point instead ๐ธ
Warning: the requisite libraries are NOT part of GCC, bestie ๐ญ Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation.
On machines where a function returns floating-point results in the 80387 register stack, some floating-point opcodes may still get emitted even if -msoft-float is used. Plot twist ๐
-mno-fp-ret-in-387โ don't use the FPU registers for return values of functions ๐ฆ The usual calling convention has functions returnfloatanddoublevalues in an FPU register, even when there's no FPU. The idea is that the operating system should emulate an FPU. Using-mno-fp-ret-in-387makes those values come back in ordinary CPU registers instead ๐ง-mno-fancy-math-387โ some 387 emulators don't support thesin,cosandsqrtinstructions for the 387, so this option tells GCC to avoid generating those instructions ๐ซถ It gets overridden when-marchsays the target CPU always has an FPU, since then the instruction doesn't need emulation. These instructions also aren't generated unless you use the-funsafe-math-optimizationsswitch too.
๐ Alignment and long double drama
-malign-double,-mno-align-doubleโ control whether GCC alignsdouble,long double, andlong longvariables on a two-word boundary or a one-word boundary ๐ Aligningdoublevariables on a two-word boundary gives code that runs somewhat faster on a Pentium, at the expense of more memory. On x86-64,-malign-doubleis enabled by default โจ
Warning: if you use -malign-double, structures containing the above types get aligned differently than the published application binary interface specs for x86-32. They won't be binary compatible with structures in code compiled without that switch ๐
-m96bit-long-double,-m128bit-long-doubleโ these control the size of thelong doubletype ๐ The x86-32 application binary interface specifies the size as 96 bits, so-m96bit-long-doubleis the default in 32-bit mode.- Modern architectures (Pentium and newer) prefer
long doubleto be aligned to an 8- or 16-byte boundary. In arrays or structures that conform to the ABI, that isn't possible. So-m128bit-long-doublealignslong doubleto a 16-byte boundary by padding it with an additional 32-bit zero ๐ - In the x86-64 compiler,
-m128bit-long-doubleis the default, since its ABI sayslong doubleis aligned on a 16-byte boundary ๐ - Heads up: neither of these options gives you any extra precision over the x87 standard of 80 bits for a
long double๐
- Modern architectures (Pentium and newer) prefer
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables. It also modifies the function calling convention for functions takinglong double. So they aren't binary-compatible with code compiled without that switch ๐ญ
-mlong-double-64,-mlong-double-80,-mlong-double-128โ these also control the size of thelong doubletype ๐ A size of 64 bits makeslong doubleequivalent todouble. That's the default for the 32-bit Bionic C library. A size of 128 bits makeslong doubleequivalent to__float128, which is the default for the 64-bit Bionic C library ๐ฅ
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables. It also modifies the function calling convention for functions takinglong double. So they aren't binary-compatible with code compiled without that switch ๐
-malign-data=typeโ controls how GCC aligns variables ๐ง The supported values for type are:compatโ uses an increased alignment value that's compatible with GCC 4.8 and earlier ๐ธ This is the default.abiโ uses the alignment value specified by the psABI ๐ฆcachelineโ uses an increased alignment value to match the cache line size โจ
-mlarge-data-threshold=thresholdโ when-mcmodel=mediumor-mcmodel=largeis specified, data objects larger than threshold get placed in large data sections ๐ซถ The default is65535๐-mrtdโ okay bestie, this one switches to a whole different function-calling convention ๐ Functions with a fixed number of arguments return using theret numinstruction, which pops their arguments on the way out โจ That saves the caller 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" ๐ And if -mrtd is on but you want a function to go back to normal, the function attribute "cdecl" overrides it ๐ซถ
โ ๏ธ Warning: this calling convention is incompatible with the one normally used on Unix, so don't use it if you need to call libraries compiled with the Unix compiler ๐
You also must provide function prototypes for all functions that take variable numbers of arguments (including printf), or incorrect code gets generated for calls to those functions ๐ญ
And honestly, seriously incorrect code results if you call a function with too many arguments ๐ Normally the extra arguments are just harmlessly ignored, but not here.
-mregparm=numโ controls how many registers get used to pass integer arguments ๐ By default no registers are used for this, and at most 3 registers can be used. You can control this for a specific function with the function attributeregparm๐ธ
Warning: if you use this switch and num is nonzero, then you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules too ๐ญ
-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 attributesseregparm.
Warning: same energy here. If you use this switch, you must build all modules with the same value, including any libraries, the system libraries and startup modules ๐ซ
-mvect8-ret-in-memโ returns 8-byte vectors in memory instead of MMX registers ๐ This is the default on VxWorks, so it matches the ABI of the Sun Studio compilers 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 ๐ฅ With-mpc32, the significands of floating-point results get rounded to 24 bits (single precision).-mpc64rounds them to 53 bits (double precision), and-mpc80rounds them to 64 bits (extended double precision), which is the default. When you use this option, higher-precision floating-point operations aren't available to the programmer unless you set the FPU control word explicitly.
Dropping the rounding below the default 80 bits can speed some programs up by 2% or more โก But ngl, some mathematical libraries assume extended-precision (80-bit) floating-point operations are enabled by default. Routines in those libraries could lose a ton of accuracy, typically through so-called "catastrophic cancellation" ๐ when this option sets the precision below extended precision.
-mdaz-ftzโ the flush-to-zero (FTZ) and denormals-are-zero (DAZ) flags in the MXCSR register control floating-point calculations ๐ SSE and AVX instructions, including scalar and vector ones, could benefit from turning on FTZ and DAZ when you specify-mdaz-ftz. Just know that FTZ/DAZ won't get set when-mno-daz-ftzor-sharedis specified, except that-mdaz-ftzwill set them even with-shared. Plot twist ๐-mstackrealignโ realigns the stack at entry ๐ง On the x86, this generates an alternate prologue and epilogue that realigns the run-time stack if necessary. It lets legacy code that keeps 4-byte stack alignment mix with modern code that keeps 16-byte stack alignment for SSE compatibility ๐ซถ See also the attributeforce_align_arg_pointer, which applies 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 is 4 (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 the x86-64 ABI requires 16 byte stack alignment, so this is ABI incompatible and only meant for a controlled environment 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. Variable arguments also get handled incorrectly for 16 byte aligned objects (including x87long doubleand__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.
-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-boundaryis used.
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double), or you'll take significant run time performance penalties ๐ On Pentium III, the SSE data type __m128 may not work properly if it isn't 16-byte aligned.
To make sure these values are aligned on the stack, the stack boundary has to be as aligned as whatever value needs the most alignment on the stack. Every function also has to be generated so it keeps the stack aligned. So calling a function compiled with a higher preferred stack boundary from a function compiled with a lower one most likely misaligns the stack ๐ตโ๐ซ It's recommended that libraries that use callbacks always use the default setting ๐
This extra alignment does eat extra stack space and generally increases code size. If your code is sensitive to stack usage, like embedded systems and operating system kernels, you may want to reduce the preferred alignment to -mpreferred-stack-boundary=2 ๐ง
-mmmx,-msse,-msse2,-msse3,-mssse3,-msse4,-msse4a,-msse4.1,-msse4.2,-mavx,-mavx2,-mavx512f,-mavx512pf,-mavx512er,-mavx512cd,-mavx512vl,-mavx512bw,-mavx512dq,-mavx512ifma,-mavx512vbmi,-msha,-maes,-mpclmul,-mclflushopt,-mclwb,-mfsgsbase,-mptwrite,-mrdrnd,-mf16c,-mfma,-mpconfig,-mwbnoinvd,-mfma4,-mprfchw,-mrdpid,-mprefetchwt1,-mrdseed,-msgx,-mxop,-mlwp,-m3dnow,-m3dnowa,-mpopcnt,-mabm,-madx,-mbmi,-mbmi2,-mlzcnt,-mfxsr,-mxsave,-mxsaveopt,-mxsavec,-mxsaves,-mrtm,-mhle,-mtbm,-mmwaitx,-mclzero,-mpku,-mavx512vbmi2,-mavx512bf16,-mavx512fp16,-mgfni,-mvaes,-mwaitpkg,-mvpclmulqdq,-mavx512bitalg,-mmovdiri,-mmovdir64b,-menqcmd,-muintr,-mtsxldtrk,-mavx512vpopcntdq,-mavx512vp2intersect,-mavx5124fmaps,-mavx512vnni,-mavxvnni,-mavx5124vnniw,-mcldemote,-mserialize,-mamx-tile,-mamx-int8,-mamx-bf16,-mhreset,-mkl,-mwidekl,-mavxifma,-mavxvnniint8,-mavxneconvert,-mcmpccxadd,-mamx-fp16,-mprefetchi,-mraoint,-mamx-complex,-mavxvnniint16,-msm3,-msha512,-msm4,-mapxf,-musermsr,-mavx10.1,-mavx10.1-256,-mavx10.1-512โ these switches turn on the instruction sets for MMX, SSE, AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA, AES, PCLMUL, CLFLUSHOPT, CLWB, FSGSBASE, PTWRITE, RDRND, F16C, FMA, PCONFIG, WBNOINVD, FMA4, PREFETCHW, RDPID, PREFETCHWT1, 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, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, 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 or CLDEMOTE extended instruction sets ๐ Each one has a matching-mno-option to turn that instruction 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 ๐งฉ
If you want SSE/SSE2 instructions generated automatically from floating-point code (instead of 387 instructions), look at -mfpmath=sse ๐
GCC basically ghosts the SSEx instructions when -mavx is used. Instead, it generates new AVX instructions, or AVX equivalents for all the SSEx instructions, when needed โจ
These options let GCC use these extended instructions in generated code, even without -mfpmath=sse. If your app does run-time CPU detection, you have to compile separate files for each supported architecture using the right flags ๐ซ In particular, the file with the CPU detection code should be compiled without these options.
-mdump-tune-featuresโ tells GCC to dump the names of the x86 performance tuning features and their default settings ๐ You can use those names in-mtune-ctrl=feature-list๐-mtune-ctrl=feature-listโ okay so this is the fine-grain dial for x86 code generation features ๐๏ธโจ You pass in a comma separated list of feature names. A feature gets turned on when it's written plainly, but if you put a^in front of it, it gets turned off ๐ โโ๏ธ Also check out-mdump-tune-featureswhile you're at it ๐
โ ๏ธ BESTIE, READ THIS โ ๏ธ -mtune-ctrl=feature-list is intended for GCC developers only ๐งโ๐ป Using it may lead to code paths that never got covered by testing, and it can potentially result in compiler ICEs or runtime errors ๐
-mno-defaultโ this one turns off ALL the tunable features in one go ๐งน See also-mtune-ctrl=feature-listand-mdump-tune-features.-mcldโ okay this one's a whole story ๐จ GCC emits acldinstruction in the prologue of functions that use string instructions. String instructions rely on the DF flag to decide between autoincrement and autodecrement mode. The ABI says DF gets cleared on function entry, but some operating systems don't clear it in their exception dispatchers ๐ญ So the exception handler can run with DF set, and then string instructions go in the wrong direction. This option can be turned on by default for 32-bit x86 targets by configuring GCC with the--enable-cldconfigure option ๐ In that case, you can suppress generation ofcldinstructions with the-mno-cldcompiler option.-mvzeroupperโ this instructs GCC to emit avzeroupperinstruction before control flow leaves the function ๐ฆ It's there to cut down the AVX to SSE transition penalty, and it also removes unnecessaryzeroupperintrinsics ๐งน-mprefer-avx128โ this tells the auto-vectorizer to use 128-bit AVX instructions instead of 256-bit AVX instructions ๐-mprefer-vector-width=optโ this one makes GCC useopt-bit vector width in instructions instead of the default for the selected platform ๐-mpartial-vector-fp-mathโ this lets GCC generate floating-point operations that might affect the floating-point status flags on partial vectors ๐ง (those are the ones where vector elements live in the low part of the 128-bit SSE register). Unless-fno-trapping-mathis specified, the compiler keeps things correct by sanitizing all input operands so there are zeroes in the unused upper part of the vector register โจ Heads up though: if you use built-in functions or inline assembly with partial vector arguments, NaNs, denormal or invalid values can leak into the upper part of the vector ๐ That can cause performance issues when-fno-trapping-mathis in effect. These issues can be mitigated 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 ๐ฆ tobits. The valid values are128,256and512.-mstore-max=bitsโ same energy, but for storing: this sets the maximum number of bits that can be stored to memory efficiently tobits๐พ The valid values are128,256and512.- Here's the rundown on the possible values ๐:
noneโ no extra limitations applied to GCC other than what's defined by the selected platform.128โ prefer 128-bit vector width for instructions.256โ prefer 256-bit vector width for instructions.512โ prefer 512-bit vector width for instructions.
-mnoreturn-no-callee-saved-registersโ this optimizes functions with thenoreturnattribute or the_Noreturnspecifier ๐ชฆ by not saving callee-saved registers in the function prologue, as long as the function uses them (except for theBPregister). Just know it can interfere with debugging the caller of thenoreturnfunction, or any function further up in the call stack ๐ so it is not enabled by default.-mcx16โ this lets GCC generateCMPXCHG16Binstructions in 64-bit code ๐ to implement compare-and-exchange operations on 16-byte aligned 128-bit objects. It's super useful for atomic updates of data structures that are bigger than one machine word ๐ซง GCC uses this instruction to implement__syncBuiltins. For__atomicBuiltins operating on 128-bit integers, though, a library call is always used ๐-msahfโ this enables generation ofSAHFinstructions in 64-bit code ๐งช History tea: early Intel Pentium 4 CPUs with Intel 64 support, before the Pentium 4 G1 step 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โ this one enables shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ก๏ธ-mcrc32โ this enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32siand__builtin_ia32_crc32dito generate thecrc32machine instruction ๐ข-mmwaitโ this enables the built-in functions__builtin_ia32_monitorand__builtin_ia32_mwaitto generate themonitorandmwaitmachine instructions โณ-mrecipโ this enablesRCPSSandRSQRTSS(plus their vectorized buddiesRCPPSandRSQRTPS) ๐งฎ with an extra Newton-Raphson step to boost precision. They get 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. Warning, bestie ๐ while the throughput of the sequence is higher than the non-reciprocal instruction, the precision can drop by up to 2 ulp (i.e. the inverse of 1.0 equals0.99999994).
๐ก Note that GCC implements 1.0f/sqrtf(x) in terms of RSQRTSS (or RSQRTPS) already with -ffast-math (or the above option combination), so it doesn't need -mrecip.
๐ก Also, GCC emits the above sequence with the additional Newton-Raphson step for vectorized single-float division and vectorized sqrtf(x) already with -ffast-math (or the above option combination), so it doesn't need -mrecip either.
-mrecip=optโ this controls which reciprocal estimate instructions are allowed to be used ๐ฏoptis a comma-separated list of options, and any option can be preceded by a!to invert it:allโ enable all estimate instructions.defaultโ enable the default instructions, equivalent to-mrecip.noneโ disable all estimate instructions, equivalent to-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.
So, for example, -mrecip=all,!sqrt enables all of the reciprocal approximations, except for square root โจ
-mveclibabi=typeโ this specifies the ABI type to use when vectorizing intrinsics with an external library ๐ Fortype, the supported values aresvmlfor the Intel short vector math library andacmlfor the AMD math core library. To use it, both-ftree-vectorizeand-funsafe-math-optimizationshave to be enabled, and an SVML or ACML ABI-compatible library must be specified at link time ๐
GCC currently emits calls to 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 for the corresponding function type when -mveclibabi=svml is used ๐ธ It also emits calls to __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 for the corresponding function type when -mveclibabi=acml is used ๐ฆ
-mabi=nameโ this generates code for the specified calling convention ๐ Permissible values aresysvfor the ABI used on GNU/Linux and other systems, andmsfor the Microsoft ABI. The default is the Microsoft ABI when targeting Microsoft Windows, and the SysV ABI on all other systems. You can control this for specific functions with the function attributesms_abiandsysv_abi๐-mforce-indirect-callโ this forces all calls to functions to be indirect ๐ It's handy when you're using Intel Processor Trace, since that gives more precise timing information for function calls โฑ๏ธ-mmanual-endbrโ this inserts anENDBRinstruction at function entry only via thecf_checkfunction attribute ๐ช It's useful when you pair it with-fcf-protection=branch, so you can controlENDBRinsertion at the function entry ๐ง-mcet-switchโ by default, CET instrumentation is turned off on switch statements that use a jump table, and indirect branch track is disabled ๐ Since jump tables live in read-only memory, this doesn't cause a direct loss of hardening. But if the jump table index is attacker-controlled, the indirect jump may not be constrained by CET ๐ฑ This option turns CET instrumentation on, so indirect branch track is enabled for switch statements with jump tables, which leads to the jump targets being reachable via any indirect jumps ๐ก๏ธ๐-mcall-ms2sysv-xloguesโ okay so 64-bit ABIs don't agree on everything, which means any Microsoft ABI function that calls a System V ABI function has to treatRSI,RDIandXMM6-15as clobbered ๐. By default the code that saves and restores those registers gets dumped inline, making prologues and epilogues pretty lengthy. Turn this on and they use stubs in the static portion oflibgccinstead, so your functions get smaller ๐ for the price of a few extra instructions โจ-mtls-dialect=typeโ generates thread-local storage access code using thegnuorgnu2conventions.gnuis the conservative default ๐ก๏ธ, whilegnu2is more efficient ๐ but may add compile- and run-time requirements that can't be satisfied on every system ๐ฌ-mpush-args,-mno-push-argsโ uses PUSH operations to store outgoing parameters ๐ฆ. It's shorter and usually just as fast as the SUB/MOV method, and it's on by default. Sometimes turning it off actually helps performance thanks to better scheduling and fewer dependencies ๐ง-maccumulate-outgoing-argsโ if enabled, the maximum space needed for outgoing arguments gets computed in the function prologue ๐งฎ. This is faster on most modern CPUs because of reduced dependencies, improved scheduling and reduced stack usage when the preferred stack boundary 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 it have to compile and link all their code with-mthreads. When compiling, it defines-D_MT, and when linking, it pulls in the special thread helper library-lmingwthrd, which cleans up per-thread exception-handling data ๐งน-mms-bitfields,-mno-ms-bitfieldsโ turns bit-field layout that's compatible with the native Microsoft Windows compiler on or off ๐
If packed is used on a structure, or if bit-fields are used, the Microsoft ABI might lay the structure out differently from how GCC normally does it ๐. This gets especially messy when you're moving packed data between GCC-compiled functions and the native Microsoft compiler, whether through a function call or as data in a file, so you may need to access either format ๐
This option is enabled by default for Microsoft Windows targets ๐ช. You can also control this locally with variable or type attributes. For more information, check out x86 Variable Attributes and x86 Type Attributes ๐ฆ
The Microsoft structure layout algorithm is pretty simple, except for the bit-field packing ๐ค. The padding and alignment of structure members, and whether a bit-field can straddle a storage-unit boundary, are determined by these rules:
- Structure members are stored sequentially in the order they're declared. The first member has the lowest memory address and the last member has the highest.
- Every data object has an alignment requirement. For everything except structures, unions, and arrays, that requirement is either the size of the object or the current packing size (set with the
alignedattribute or thepackpragma), 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 if the integral types are the same size, and the next bit-field fits into the current allocation unit without crossing the boundary set by the bit-fields' common alignment requirements ๐งฉ
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, thenbaris 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 instead of 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's important to note the following:
- If a zero-length bit-field follows a normal bit-field, the type of the zero-length bit-field may affect the alignment of the structure as a whole. For example,
t2has a size of 4 bytes, since the zero-length bit-field follows a normal bit-field and is of typeshort๐ฏ - Even if a zero-length bit-field isn't followed by a normal bit-field, it may still affect the alignment of the structure:
struct
{
char foo : 6;
long : 0;
} t4;
Here, t4 takes up 4 bytes ๐ง
- Zero-length bit-fields that follow non-bit-field members are ignored:
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes ๐ธ
-mno-align-stringopsโ doesn't align the destination of inlined string operations ๐ซง. This shrinks code size and speeds things up when the destination is already aligned but GCC doesn't know 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 allows more inlining ๐ฅ and increases code size, but it may boost performance for code that depends on fastmemcpyandmemseton short lengths. It also enables inline expansion ofstrlenfor all pointer alignments ๐-minline-stringops-dynamicallyโ for string operations of unknown size, it uses run-time checks with inline code for small blocks and a library call for large blocks ๐งโโ๏ธ-mstringop-strategy=algโ overrides GCC's internal decision heuristic for which algorithm gets used to inline string operations ๐๏ธ. The allowed values foralgare: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 internal heuristic that decides whether__builtin_memcpyshould be inlined and which inline algorithm to use when the expected size of the copy is known ๐ช.strategyis a comma-separated list ofalg:max_size:dest_aligntriplets.algis specified in-mstringop-strategy, andmax_sizeis the max byte size that the inline algorithmalgis allowed to handle. For the last triplet,max_sizemust be-1. Themax_sizevalues in the list must be given in increasing order. The minimal byte size foralgis 0 for the first triplet, andmax_size + 1of the preceding range for every triplet after that ๐-mmemset-strategy=strategyโ pretty much the same as-mmemcpy-strategy=except it controls__builtin_memsetexpansion ๐งธ-momit-leaf-frame-pointerโ stops keeping the frame pointer in a register for leaf functions ๐. This skips the instructions for saving, setting up and restoring frame pointers, and frees up an extra register in leaf functions. The option-fomit-leaf-frame-pointerdrops the frame pointer for leaf functions too, 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 to cover the entire TLS area ๐บ๏ธ. For systems that use the GNU C Library, the default is on โ-msse2avx,-mno-sse2avxโ tells the assembler to encode SSE instructions with a VEX prefix ๐. The option-mavxturns this on by default ๐ซ-mfentry,-mno-fentryโ if profiling is active (-pg), puts the profiling counter call before the prologue ๐. Heads up: on x86 architectures the attribute"ms_hook_prologue"isn't possible at the moment for-mfentryand-pgโ ๏ธ-mrecord-mcount,-mno-record-mcountโ if profiling is active (-pg), generates a__mcount_locsection that holds pointers to each profiling call ๐๏ธ. This is handy for automatically patching calls in and out ๐ฉน-mnop-mcount,-mno-nop-mcountโ if profiling is active (-pg), generates the calls to the profiling functions as NOPs ๐ด. This is useful when they should be patched in later, dynamically. It's likely only useful together with-mrecord-mcount๐ซถ-minstrument-return=typeโ instruments function exit in-pg -mfentryinstrumented functions by calling the specified function ๐ช. This 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 ๐
okay so this part is a whole buffet of -m switches, and we're going through every single one ๐
๐
-mrecord-return,-mno-record-returnโ this one makes a__return_locsection that points at all the return instrumentation code ๐ง-mfentry-name=nameโ picks the name of the__fentry__symbol that gets called at function entry for-pg-mfentryfunctions โจ-mfentry-section=nameโ sets the section name where-mrecord-mcountcalls get recorded. The default is__mcount_loc๐ธ-mskip-rax-setup,-mno-skip-rax-setupโ bestie, this is for x86-64 code with SSE extensions turned off.-mskip-rax-setuplets you 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 for no reason when passing variable arguments, so the impacts here are that callees may waste some stack space, misbehave, or jump to a random location. GCC 4.4 or newer don't have those issues, regardless of the RAX register value ๐
-m8bit-idiv,-mno-8bit-idivโ on some processors like Intel Atom, 8-bit unsigned integer divide is way faster than 32-bit or 64-bit integer divide. This option adds a run-time check. If both the dividend and divisor are within 0 to 255, it uses 8-bit unsigned integer divide instead of 32-bit/64-bit integer divide ๐ฅ-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ splits 32-byte AVX unaligned loads and stores into smaller pieces ๐ซถ-mstack-protector-guard=guardโ generates stack protection code using a canary at the guard location. The supported locations areglobalfor a global canary ortlsfor a per-thread canary in the TLS block, andtlsis the default. This option only does something when-fstack-protectoror-fstack-protector-allis specified ๐-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ with the latter choice of guard, these two decide which segment register (%fsor%gs) gets used as the base register for reading the canary, and what offset from that base it reads from. Their defaults are whatever the relevant ABI says ๐-mgeneral-regs-onlyโ only generates code that uses general-purpose registers. The compiler is blocked from touching floating-point, vector, mask, and bound registers ๐-mrelax-cmpxchg-loopโ when making a compare-and-swap loop for__syncBuiltins and__atomicBuiltins that don't have a native instruction, this optimizes for the super contended case. It issues an atomic load before the"CMPXCHG"instruction, and uses the"PAUSE"instruction to save CPU power when restarting the loop ๐-mindirect-branch=choiceโ converts indirect calls and jumps based on the choice. The default iskeep, which leaves indirect calls and jumps alone.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 that live in a separate object file. You can control this for a specific function with the function attribute"indirect_branch"๐ฆ
Note:-mcmodel=largeis incompatible with-mindirect-branch=thunkand-mindirect-branch=thunk-extern, since the thunk function may not be reachable in the large code model ๐
Note:-mindirect-branch=thunk-externis compatible with-fcf-protection=branch, since the external thunk can be made to enable control-flow check โจ
-mfunction-return=choiceโ converts function returns based on the choice. The default iskeep, which leaves function returns 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 in a separate object file. You can control this for a specific function with the function attribute"function_return"๐ธ
Note:-mindirect-return=thunk-externis compatible with-fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐ซถ
Note:-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 through a register ๐ง-mharden-sls=choiceโ generates code to mitigate straight line speculation (SLS) based on the choice. The default isnone, which disables all SLS hardening.returnenables it for function returns,indirect-jmpenables it for indirect jumps, andallturns on all SLS hardening ๐ฅ-mindirect-branch-cs-prefixโ adds a CS prefix to call and jmp instructions going to an indirect thunk, where the branch target is in ther8-r15registers. This makes the call and jmp instruction length 6 bytes, 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 to prevent a possible illegal instruction from EGPR showing up. To turn on EGPR usage in inline asm, use this option, and you need to make sure the instruction actually supports EGPR ๐-mevex512,-mno-evex512โ enables or disables 512-bit vectors. It's on by default if AVX512F is enabled ๐
These -m switches are supported in addition to the above on x86-64 processors in 64-bit environments.
-m32,-m64,-mx32,-m16,-miamcuโ generates code for a 16-bit, 32-bit, or 64-bit environment.-m32sets"int","long", and pointer types to 32 bits, and generates code that runs in 32-bit mode ๐-m64sets"int"to 32 bits and"long"and pointer types to 64 bits, and generates code for the x86-64 architecture. For Darwin only,-m64also turns off the-fno-picand-mdynamic-no-picoptions ๐-mx32sets"int","long", and pointer types to 32 bits, and generates code for the x86-64 architecture ๐ฆ-m16is the same as-m32, except it outputs the".code16gcc"assembly directive at the start of the assembly output so the binary can run in 16-bit mode ๐-miamcugenerates code that conforms to the Intel MCU psABI. It requires-m32to be turned on โจ-mno-red-zoneโ don't use a so-called "red zone" for x86-64 code. The red zone is mandated by the x86-64 ABI. It's a 128-byte area beyond the stack pointer that signal or interrupt handlers don't modify, so it can be used for temporary data without adjusting the stack pointer. This flag disables that red zone ๐ธ-mcmodel=smallโ generates code for the small code model, where the program and its symbols must be linked in the lower 2 GB of the address space. Pointers are 64 bits. Programs can be statically or dynamically linked. This is the default code model ๐-mcmodel=kernelโ generates code for the kernel code model. The kernel runs in the negative 2 GB of the address space. This model has to be used for Linux kernel code ๐ง-mcmodel=mediumโ generates code for the medium model, where the program is linked in the lower 2 GB of the address space. 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โ generates code for the large model, which makes no assumptions about addresses and sizes of sections ๐-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 ๐-mneeded,-mno-neededโ emits theGNU_PROPERTY_X86_ISA_1_NEEDEDGNU property for Linux targets. This tells you the micro-architecture ISA level needed to run the binary ๐-mno-direct-extern-accessโ without-fpicor-fPIC, always uses the GOT pointer to access external symbols. With-fpicor-fPIC, access to protected symbols is treated as local symbols. The default is-mdirect-extern-access๐
Warning: shared libraries compiled with-mno-direct-extern-accessand executables compiled with-mdirect-extern-accessmay not be binary compatible if protected symbols are used in shared libraries and executables ๐ญ
-munroll-only-small-loopsโ controls conservative small loop unrolling. It's enabled by default withO2, and unrolls loops with fewer than 4 insns by 1 time. Explicitly using-f[no-]unroll-[all-]loopsturns this flag off, so you don't get any unrolling you didn't ask for ๐ฆ-mlam=choiceโ LAM (linear-address masking) lets special bits in the pointer be used for metadata. The default isnone. Withu48, pointer bits in positions 62:48 can be used for metadata. Withu57, pointer bits in positions 62:57 can be used for metadata ๐
โจ x86 Windows Options โจ
These additional options are available for Microsoft Windows targets:
-mconsoleโ this option makes a console application, by telling the linker to set the PE header subsystem type that console applications need. It's available for Cygwin and MinGW targets and is enabled by default on those targets ๐-mcrtdll=library: okay bestie, this one is a whole vibe ๐ It lets you preprocess, compile, or link with the C RunTime DLL library you pick. It adjusts the predefined macros__CRTDLL__,__MSVCRT__and__MSVCRT_VERSION__for that CRT, chooses its start file, and links it in ๐. The names the preprocessor recognizes are"crtdll","msvcrt10","msvcrt20","msvcrt40","msvcrt-os","msvcr70","msvcr80","msvcr90","msvcr100","msvcr110","msvcr120"and"ucrt"โจ. If you skip this flag, the default MinGW import librarymsvcrtgets linked and the preprocessor isn't touched at all ๐. Thatmsvcrtimport library is just a symlink to (or a copy of) whichever MinGW CRT import library was picked when MinGW got compiled.msvcrt-osis the one for the Windows system CRT DLLmsvcrt.dll, and in most cases it's the default MinGW import library ๐.
Heads up, bestie: switching the CRT DLL usually means recompiling the entire MinGW CRT ๐. This option is strictly for experimental and testing purposes. It's available for MinGW targets.
-mdll: this one's for Cygwin and MinGW targets ๐ฆ. It tells GCC to generate a DLL (a dynamic link library), which lets you pick the runtime startup object and entry point you need.-mnop-fun-dllimport: also for Cygwin and MinGW ๐ธ. It tells GCC to ignore thedllimportattribute. Bye, attribute ๐.-mthreads: MinGW only ๐งต. It switches on MinGW-specific thread support.-municode: MinGW-w64 only ๐. It predefines theUNICODEpreprocessor macro and picks Unicode-capable runtime startup code, so your strings are giving full Unicode energy ๐.-mwin32: Cygwin and MinGW ๐. It sets up the typical Microsoft Windows predefined macros in the preprocessor, but it does not change which runtime library or startup code gets chosen.-mwindows: Cygwin and MinGW again ๐ช. It makes a GUI application by telling the linker to set the PE header subsystem type to match.-fno-set-stack-executable: MinGW only ๐. The executable flag doesn't get set on the stack that nested functions use. This is needed for binaries running in kernel mode of Microsoft Windows, since the User32 API (the thing used to set executable privileges) isn't available there.-fwritable-relocated-rdata: MinGW and Cygwin ๐ง. Relocated data in a read-only section gets put into the".data"section. This is necessary for older runtimes that don't support modifying".rdata"sections for pseudo-relocation.-mpe-aligned-commons: Cygwin and MinGW ๐. It uses the GNU extension to the PE file format that lets COMMON variables be aligned correctly when code is generated. This is enabled by default if GCC detects that the target assembler found during configuration supports the feature.
See also under x86 Options for standard options. That's where the regular stuff lives, bestie ๐ซถ.
โจ Xstormy16 Options โจ
These options are defined for Xstormy16 ๐.
-msim: pick startup files and a linker script that suit the simulator ๐ฎ.
โจ Xtensa Options โจ
These options are supported for Xtensa targets ๐ฆ.
-mconst16,-mno-const16: turn the use ofCONST16instructions for loading constant values on or off ๐.CONST16isn't a standard Tensilica option right now. When it's enabled,CONST16instructions are always used in place of the standardL32Rinstructions. It's only on by default whenL32Risn't available ๐.-mfused-madd,-mno-fused-madd: enable or disable fused multiply/add and multiply/subtract instructions in the floating-point option ๐ฅ. This does nothing if the floating-point option isn't also on. Turning fused ops off makes the compiler use separate instructions for the multiply and the add/subtract. That can be the move when you need strict IEEE 754-compliant results ๐ , since fused multiply add/subtract doesn't round the intermediate result, so it ends up with more bits of precision than the IEEE standard specifies. Turning them off also means your program output isn't affected by how well the compiler can combine multiply and add/subtract operations ๐ง .-mserialize-volatile,-mno-serialize-volatile: when this is enabled, GCC insertsMEMWinstructions beforevolatilememory references to guarantee sequential consistency ๐. 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 disables PIC when compiling kernel code.-mtext-section-literals,-mno-text-section-literals: these control how literal pools are treated ๐๏ธ. The default is-mno-text-section-literals, which puts literals in a separate section of the output file. That lets the literal pool live 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 are interspersed in the text section so they sit as close as possible to where they're referenced ๐. This might be necessary for large assembly files. Literals for each function get placed right before that function.-mauto-litpools,-mno-auto-litpools: also about literal pools, bestie ๐. The default is-mno-auto-litpools, which puts literals in a separate section of the output file unless-mtext-section-literalsis used. With-mauto-litpools, the assembler interweaves the literals into the text section itself. The compiler doesn't emit explicit.literaldirectives and loads literals into registers withMOVIinstead ofL32R, so the assembler can do relaxation and place literals wherever they need to go ๐ช. This lets the assembler make several literal pools per function and assemble very big functions, which 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 down on branch penalties, even though you lose a bit of code density ๐ฏ. The assembler tries to widen density instructions so branch targets and the instructions right after call instructions get aligned. If there aren't enough safe density instructions before a target to line it up, no widening happens. The default is-mtarget-align. These options don't change how auto-aligned instructions likeLOOPget 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 tell the target of the direct call is within range of 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 possibly be out of range ๐. Fun fact, this option is implemented in the assembler, not the compiler, so the assembly GCC generates still shows direct call instructions. If you want to see what's actually running, look at the disassembled object code ๐. The assembler uses an indirect call for every cross-file call, not just the ones that are really out of range.-mabi=name: generate code for the ABI you specify ๐. The permissible values arecall0andwindowed. The default ABI is chosen by the Xtensa core configuration.-mabi=call0: when this is enabled, function parameters get passed in registersa2througha7, registersa12througha15are caller-saved, and registera15may be used as a frame pointer ๐ท. When this version of the ABI is on, the C preprocessor symbol"__XTENSA_CALL0_ABI__"is defined.-mabi=windowed: when this is enabled, 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 upon return. When this version of the ABI is on, the C preprocessor symbol"__XTENSA_WINDOWED_ABI__"is defined.-mextra-l32r-costs=n: specify 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 usingL32Ror built from a small one with a couple of arithmetic instructions. The default value is0.-mstrict-align,-mno-strict-align: this controls whether GCC avoids or allows generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification ๐. The default is-mno-strict-alignfor cores that support both unaligned loads and stores in hardware, and-mstrict-alignfor all other cores.
โจ zSeries Options โจ
These are listed under
โจ ENVIRONMENT โจ
okay so this section is all about environment variables that change how GCC behaves ๐ Some of them point it at directories or prefixes to search for files, and others tweak the compilation setup itself ๐ธ
Note that you can also specify places to search using options such as -B, -I and -L ๐ง These take precedence over places set with environment variables, which in turn beat whatever GCC's configuration says ๐
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL ๐
These environment variables control the localization info that lets GCC work with different national conventions ๐ GCC looks at the locale categories LC_CTYPE and LC_MESSAGES if it's been configured to do so. These categories can be set to any value your installation supports. A typical value is en_GB.UTF-8, which means English in the United Kingdom, encoded in UTF-8 ๐ฌ๐ง
LC_CTYPE is the character classification one ๐ฆ GCC uses it to figure out where character boundaries are in a string. This matters for some multibyte encodings that have quote and escape characters which would otherwise be read as the end of a string or as an escape ๐ญ
LC_MESSAGES decides which language is used in diagnostic messages ๐ฌ
If the LC_ALL variable is set, it overrides LC_CTYPE and LC_MESSAGES ๐ Otherwise, LC_CTYPE and LC_MESSAGES default to whatever LANG says. If none of these are set, GCC defaults to traditional C English behavior ๐
TMPDIR ๐๏ธ
If TMPDIR is set, it tells GCC which directory to use for temporary files ๐ธ GCC uses temp files to hold the output of one stage of compilation so the next stage can use it as input. 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 docs for that option if you want the full tea โ
GCC_EXEC_PREFIX ๐ง
If GCC_EXEC_PREFIX is set, it gives a prefix to use in the names of the subprograms the compiler runs ๐ No slash gets added when the prefix is combined with a subprogram name, so if you want that slash, end your prefix with one yourself ๐ฆ
If GCC_EXEC_PREFIX isn't 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 prefix you gave it, it goes looking in the usual places instead ๐โโ๏ธ
The default value of GCC_EXEC_PREFIX is prefix/lib/gcc/, where prefix is the prefix of the installed compiler ๐
In a lot of cases, prefix is whatever "prefix" was set to when you ran the configure script ๐ท
Prefixes given with -B take precedence over this one ๐
This prefix is also used to find files like crt0.o, which are used for linking ๐
The prefix also gets used in a pretty unusual way when hunting for header file directories ๐คฏ For each standard directory whose name normally starts with /usr/local/lib/gcc (or, more precisely, with the value of GCC_INCLUDE_DIR), GCC tries swapping that beginning out for your 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 starts with the configured prefix, then that prefix gets replaced by GCC_EXEC_PREFIX when GCC looks for header files ๐ง
COMPILER_PATH ๐ค๏ธ
The value of COMPILER_PATH is a colon-separated list of directories, very much like PATH ๐ GCC tries these directories when searching for subprograms, but only if it can't find them using GCC_EXEC_PREFIX first ๐ซถ
LIBRARY_PATH ๐
The value of LIBRARY_PATH is also a colon-separated list of directories, just like PATH โจ When GCC is configured as a native compiler, it tries these directories when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX ๐ง Linking with GCC also searches these directories for ordinary libraries when you use the -l option. The directories given with -L come first though ๐
LANG (again, but for the compiler) ๐ฏ๐ต
This variable passes locale info to the compiler ๐ One thing it's used for is deciding which character set to use when parsing character literals, string literals and comments in C and C++ ๐
When the compiler is configured to allow multibyte characters, these values for LANG are recognized:
C-JISโ Recognize JIS characters.C-SJISโ Recognize SJIS characters.C-EUCJPโ Recognize EUCJP characters.
If LANG isn't defined, or it has some other value, the compiler uses "mblen" and "mbtowc" as defined by the default locale to recognize and translate multibyte characters ๐ธ
GCC_EXTRA_DIAGNOSTIC_OUTPUT ๐ฉน
If GCC_EXTRA_DIAGNOSTIC_OUTPUT is set to one of these values, extra text gets printed to stderr whenever fix-it hints are emitted ๐ฌ Just know that -fdiagnostics-parseable-fixits and -fno-diagnostics-parseable-fixits take precedence over this env var ๐
fixits-v1โ Emits parseable fix-it hints, the same as-fdiagnostics-parseable-fixits. Columns are counted in bytes, starting at byte 1 for the first column ๐งฎfixits-v2โ Same asfixits-v1, except the columns are expressed as display columns, like-fdiagnostics-column-unit=displaydoes ๐
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), where GCC looks for header files ๐ฆ That special character, PATH_SEPARATOR, depends on the target and gets set 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 directories to search as if you'd used -I, but they come after any paths given with -I on the command line ๐ This variable gets used no matter which language is being preprocessed ๐
The other three only apply when preprocessing the particular language they name ๐ฏ Each one lists directories to search as if you'd used -isystem, again placed after any -isystem paths on the command line ๐ง
In all of these variables, an empty element tells the compiler to search its current working directory ๐ Empty elements can show up at the beginning or end of a path. For instance, if the value of CPATH is :/special/include, that's the same as -I. -I/special/include ๐ซถ
DEPENDENCIES_OUTPUT ๐ธ๏ธ
If this variable is set, its value says how to output Make dependencies based on the non-system header files the compiler processes ๐จ System header files get ignored in the dependency output ๐ โโ๏ธ
The value of DEPENDENCIES_OUTPUT can just be a file name, in which case the Make rules get written to that file, with the target name guessed from the source file name ๐ Or the value can look like file target, in which case the rules are written to file using target as the target name ๐ฏ
Put simply, this env var is equivalent to combining the options -MM and -MF, with an optional -MT switch too โจ
SUNPRO_DEPENDENCIES โ๏ธ
This one is the same as DEPENDENCIES_OUTPUT (see above), except system header files are not ignored ๐ค So it implies -M rather than -MM ๐ The dependence on the main input file is left out though ๐
SOURCE_DATE_EPOCH โฐ
If this variable is set, its value is a UNIX timestamp used in place of the current date and time in the "__DATE__" and "__TIME__" macros ๐ฐ๏ธ That way embedded timestamps stay reproducible ๐
The value of SOURCE_DATE_EPOCH has to be a UNIX timestamp, which means the number of seconds (not counting leap seconds) since 01 Jan 1970 00:00:00, written in ASCII ๐ข It's the same output you'd get from date +%s on GNU/Linux and other systems that support the %s extension in the date command ๐ง
The value should be a known timestamp, like the last modification time of the source or package, and the build process should set it ๐ ๏ธ
๐ BUGS ๐
For instructions on reporting bugs, see <file:///usr/share/doc/gcc-14/README.Bugs> ๐
๐งพ FOOTNOTES ๐งพ
- On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work ๐งฑ On multi-libbed systems,gcc -sharedhas to select the correct support libraries to link against ๐
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 ๐ซถ The whole squad that made this happen deserves a standing ovation ๐
โ๏ธ COPYRIGHT โ๏ธ
Copyright (c) 1988-2024 Free Software Foundation, Inc. ๐ท
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation ๐ with the Invariant Sections being "GNU General Public License" and "Funding Free Software", the Front-Cover texts being (a) (see below), and with the Back-Cover Texts being (b) (see below). A copy of the license is included in the gfdl(7) man page ๐
(a) The FSF's Front-Cover Text is:
A GNU Manual
(b) The FSF's Back-Cover Text is:
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development. ๐
And that's the whole page, bestie ๐ GCC 14, dated April 12, 2024, and we are DONE with this one โจ๐ ๐ฆ
๐ฆ where this page comes from
- ubuntu noble: gcc-14-i686-linux-gnu 14-20240412-0ubuntu1cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms