GCC(1)
Bestie, this is the GCC(1) manual page from the GNU crew ๐ Let's get into it ๐
๐ NAME
gcc - 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 made the cut up here, so check below for the rest ๐ Also, g++ accepts mostly the same options as gcc โจ
๐ DESCRIPTION
Okay so when you run GCC, it normally goes through the whole pipeline: preprocessing, compilation, assembly, and linking ๐ฅ The "overall options" let you stop the party early at an intermediate stage. For example, -c tells it not to run the linker, so what you get back is object files from the assembler ๐ง
Other options get passed along to one or more stages of processing. Some of them boss around the preprocessor, some of them boss around the compiler itself ๐ And yet other options control the assembler and linker. Most of those aren't documented here, since you rarely need to touch 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, then you can use that option with all supported languages โจ
The usual move is to run the executable called gcc, or machine-gcc when you're cross-compiling, or machine-gcc-version if you want one specific version of GCC ๐ฆ When you compile C++ programs, you should invoke GCC as g++ instead, no cap ๐ซถ
The gcc program takes options and file names as operands. A lot of options have multi-letter names, so you can't squish single-letter options together. -dv is very different from -d -v, so don't be a menace about it ๐ญ
You can mix options and other arguments. For the most part, the order doesn't matter ๐ Order does matter when you use several options of the same kind. For example, if you specify -L more than once, the directories get searched in the order you specified them. Also, where you put the -l option is significant ๐
Lots of options have long names that start with -f or with -W---for example, -fmove-loop-invariants, -Wformat, and so on ๐ธ Most of these come in 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. Main character energy for the default ๐
Some options take one or more arguments, usually separated from the option name either by a space or by the equals sign (=). Unless it says otherwise, an argument can be either numeric or a string ๐ง Numeric arguments usually need to be small unsigned decimal or hexadecimal integers. Hexadecimal arguments must begin with the 0x prefix ๐
Arguments to options that set some sort of size threshold can be arbitrarily large decimal or hexadecimal integers, followed by a byte size suffix that designates a multiple of bytes. The suffixes are kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, GB and GiB for gigabyte and gigibyte, and so on ๐ In the rest of this page these are called byte-size. If you want the full list and the real explanation of the binary and decimal byte size prefixes, go check the NIST, IEC, and other relevant national and international standards ๐ค
โจ OPTIONS โจ
๐ฆ Option Summary
Here's the whole options lineup, grouped by type ๐ The explanations live 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 -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
-fallow-parameterless-variadic-functions -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
-fpermitted-flt-eval-methods=standard -fplan9-extensions
-fsigned-bitfields -funsigned-bitfields -fsigned-char
-funsigned-char -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-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 -fpermissive -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 -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-exceptions
-Wextra-semi -Wno-inaccessible-base -Wno-inherited-variadic-ctor
-Wno-init-list-lifetime -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 -Wsign-promo -Wsized-deallocation
-Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override
-Wno-terminate -Wuseless-cast -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|json] -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-labels
-fno-diagnostics-show-line-numbers -fno-diagnostics-show-cwe
-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]
โจ Warning Options โจ
okay bestie, this is the warning buffet ๐ GCC has so many flags for complaining about your code that I'm not even kidding. Here's the whole menu, every single one, no cuts ๐ซถ
-fsyntax-only -fmax-errors=n -Wpedantic -pedantic-errors -w
-Wextra -Wall -Wabi=n -Waddress -Wno-address-of-packed-member
-Waggregate-return -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 -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-c2x-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 -Wcast-align -Wcast-align=strict
-Wcast-function-type -Wcast-qual -Wchar-subscripts -Wclobbered
-Wcomment -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 -Werror -Werror=* -Wexpansion-to-defined
-Wfatal-errors -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 -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 -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-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
-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
-Wtsan -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 -Wno-varargs
-Wvariadic-macros -Wvector-operation-performance -Wvla
-Wvla-larger-than=byte-size -Wno-vla-larger-than
-Wvolatile-register-var -Wwrite-strings -Wzero-length-bounds
โจ Static Analyzer Options โจ
the analyzer squad ๐ฎ These are the static analyzer flags, all lined up and ready to go ๐ฆ
-fanalyzer -fanalyzer-call-summaries -fanalyzer-checker=name
-fno-analyzer-feasibility -fanalyzer-fine-grained
-fanalyzer-state-merge -fanalyzer-state-purge
-fanalyzer-transitivity -fanalyzer-verbose-edges
-fanalyzer-verbose-state-changes -fanalyzer-verbosity=level
-fdump-analyzer -fdump-analyzer-stderr -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-json -fdump-analyzer-state-purge
-fdump-analyzer-supergraph -Wno-analyzer-double-fclose
-Wno-analyzer-double-free -Wno-analyzer-exposure-through-output-file
-Wno-analyzer-file-leak -Wno-analyzer-free-of-non-heap
-Wno-analyzer-malloc-leak -Wno-analyzer-mismatching-deallocation
-Wno-analyzer-null-argument -Wno-analyzer-null-dereference
-Wno-analyzer-possible-null-argument
-Wno-analyzer-possible-null-dereference
-Wno-analyzer-shift-count-negative
-Wno-analyzer-shift-count-overflow -Wno-analyzer-stale-setjmp-buffer
-Wno-analyzer-tainted-allocation-size
-Wno-analyzer-tainted-array-index -Wno-analyzer-tainted-divisor
-Wno-analyzer-tainted-offset -Wno-analyzer-tainted-size
-Wanalyzer-too-complex
-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-write-to-const -Wno-analyzer-write-to-string-literal
โจ C and Objective-C-only Warning Options โจ
these ones are strictly for C and Objective-C, so keep them in your C/ObjC bag ๐
-Wbad-function-cast -Wmissing-declarations -Wmissing-parameter-type
-Wmissing-prototypes -Wnested-externs -Wold-style-declaration
-Wold-style-definition -Wstrict-prototypes -Wtraditional
-Wtraditional-conversion -Wdeclaration-after-statement
-Wpointer-sign
โจ Debugging Options โจ
last stop on the tour, and it's a big one ๐ Here's the full debugging lineup, every flag included ๐ซถ
-g -glevel -gdwarf -gdwarf-version -gbtf -gctf -gctflevel -ggdb
-grecord-gcc-switches -gno-record-gcc-switches -gstabs -gstabs+
-gstrict-dwarf -gno-strict-dwarf -gas-loc-support
-gno-as-loc-support -gas-locview-support -gno-as-locview-support
-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 -gxcoff -gxcoff+
-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 optimizer control panel ๐ and it's a LOT. Every single one is listed below, 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]]]]โจ-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๐ฆ-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-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 ๐ธ
Okay now the instrumentation crew ๐ง profiling, coverage, and sanitizers, all in one place, no cap.
-p๐ธ-pg๐-fprofile-arcsโจ--coverage๐-ftest-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๐ฆ-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โจ-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๐ธ-fvtable-verify=[std|preinit|none]๐ฅ-fvtv-counts๐-fvtv-debugโจ-finstrument-functions๐-finstrument-functions-exclude-function-list=sym,sym,...๐-finstrument-functions-exclude-file-list=file,file,...๐-fprofile-prefix-map=old=new๐
๐ฆ Preprocessor Options ๐ฆ
Time for the preprocessor, where macros and includes get sorted out ๐
-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 ๐ง
Just two of these, but they're giving assembler energy ๐
-Wa,option๐ง-Xassembler option๐
๐ Linker Options ๐
Linker time, bestie. Libraries, entry points, and static-vs-shared drama ๐ฅ
object-file-name๐-fuse-ld=linker๐-llibraryโจ-nostartfiles๐-nodefaultlibs๐-nolibc๐-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 should the compiler look? These flags tell it the whole vibe ๐บ๏ธ
-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 ๐
Now we're in the codegen zone, where the actual machine code gets shaped โจ
-fcall-saved-reg๐-fcall-used-reg๐-ffixed-reg๐-fexceptions๐ฆ-fnon-call-exceptions๐-fdelete-dead-exceptionsโญ-funwind-tables๐ซถ-fasynchronous-unwind-tables๐ธ-fno-gnu-unique๐ฅ-finhibit-size-directiveโจ-fcommon๐-fno-ident๐-fpcc-struct-return๐-fpic๐-fPIC๐ฆ-fpie๐-fPIEโญ-fno-plt๐ซถ-fno-jump-tables๐ธ-fno-bit-tests๐ฅ-frecord-gcc-switches๐-freg-struct-returnโจ-fshort-enums๐-fshort-wchar๐-fverbose-asm๐-fpack-struct[=n]๐-fleading-underscore๐ฆ-ftls-model=model๐-fstack-reuse=reuse_levelโญ-ftrampolines๐ซถ-ftrapv๐ธ-fwrapv๐ฅ-fvisibility=[default|internal|hidden|protected]๐-fstrict-volatile-bitfieldsโจ-fsync-libcalls๐
๐ Developer Options ๐
Developer mode, bestie ๐ ๏ธ dumps, reports, and debug knobs for the people who really want to see under the hood ๐
-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]๐-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 ๐
Last stop, the target-specific flags ๐ฏ Here's the AArch64 crew, fully listed.
AArch64 Options
-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๐
๐ Adapteva Epiphany Options ๐
okay so the Epiphany chip gets its own little flag wardrobe ๐ง here's everything it's got:
-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 ๐ฅ
the GCN one is short and sweet, no notes ๐
-march=gpu -mtune=gpu -mstack-size=bytes
๐ธ ARC Options ๐ธ
the ARC list is literally huge, bestie ๐ญ it's giving whole buffet energy ๐
-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 an entire universe of flags, so grab a snack first ๐ฟ
-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
๐ AVR Options ๐
-mmcu=mcu -mabsdata -maccumulate-args
-mbranch-cost=cost -mcall-prologues -mgas-isr-prologues -mint8
-mdouble=bits -mlong-double=bits -mn_flash=size -mno-interrupts
-mmain-is-OS_task -mrelax -mrmw -mstrict-X -mtiny-stack
-mfract-convert-truncate -mshort-calls -nodevicelib -nodevicespecs
-Waddr-space-convert -Wmisspelled-isr
๐ง Blackfin Options ๐ง
-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 ๐
-mbig-endian -mlittle-endian -march=cpu -msim
-msdata=sdata-type
๐ CRIS Options ๐
-mcpu=cpu -march=cpu -mtune=cpu -mmax-stack-frame=n
-melinux-stacksize=n -metrax4 -metrax100 -mpdebug -mcc-init
-mno-side-effects -mstack-align -mdata-align -mconst-align
-m32-bit -m16-bit -m8-bit -mno-prologue-epilogue -mno-gotplt
-melf -maout -melinux -mlinux -sim -sim2 -mmul-bug-workaround
-mno-mul-bug-workaround
โญ CR16 Options โญ
-mmac -mcr16cplus -mcr16c -msim -mint32 -mbit-ops
-mdata-model=model
๐ซถ C-SKY Options ๐ซถ
-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 has a lot of linker-y flags, so this one is extra long, bestie ๐
-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 -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 ๐ธ
-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 ๐ฎ
-mbig-endian -mlittle-endian -mkernel=version
-mframe-limit=bytes -mxbpf -mco-re -mno-co-re -mjmpext -mjmp32
-malu32 -mcpu=version
๐ FR30 Options ๐
-msmall-model -mno-lsim
๐ฆ FT32 Options ๐ฆ
-msim -mlra -mnodiv -mft32b -mcompress -mnopm
๐ FRV Options ๐
FRV has a lot of flags too, so take a breath ๐ฎโ๐จ
-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 ๐ง
-mglibc -muclibc -mmusl -mbionic -mandroid
-tno-android-cc -tno-android-ld
๐ท H8/300 Options ๐ท
-mrelax -mh -ms -mn -mexr -mno-exr -mint32
-malign-300
๐ช HPPA Options ๐ช
-march=architecture-type -mcaller-copies
-mdisable-fpregs -mdisable-indexing -mfast-indirect-calls -mgas
-mgnu-ld -mhp-ld -mfixed-range=register-range -mjump-in-delay
-mlinker-opt -mlong-calls -mlong-load-store -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 -msio -mwsio -munix=unix-std -nolibdld -static
-threads
๐ง IA-64 Options ๐ง
the IA-64 list is massive, so pace yourself ๐โโ๏ธ
-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 ๐
-mbarrel-shift-enabled -mdivide-enabled
-mmultiply-enabled -msign-extend-enabled -muser-enabled
๐ M32R/D Options ๐
-m32r2 -m32rx -m32r -mdebug -malign-loops
-mno-align-loops -missue-rate=number -mbranch-cost=number
-mmodel=code-size-model-type -msdata=sdata-type -mno-flush-func
-mflush-func=name -mno-flush-trap -mflush-trap=number -G num
๐ซง M32C Options ๐ซง
-mcpu=cpu -msim -memregs=number
๐ M680x0 Options ๐
this is the M680x0 bunch, and they are a lot ๐ฅน
-march=arch -mcpu=cpu -mtune=tune -m68000 -m68020
-m68020-40 -m68020-60 -m68030 -m68040 -m68060 -mcpu32 -m5200
-m5206e -m528x -m5307 -m5407 -mcfv4e -mbitfield -mno-bitfield
-mc68000 -mc68020 -mnobitfield -mrtd -mno-rtd -mdiv -mno-div
-mshort -mno-short -mhard-float -m68881 -msoft-float -mpcrel
-malign-int -mstrict-align -msep-data -mno-sep-data
-mshared-library-id=n -mid-shared-library -mno-id-shared-library
-mxgot -mno-xgot -mlong-jump-table-offsets
๐ MCore Options ๐
-mhardlit -mno-hardlit -mdiv -mno-div
-mrelax-immediates -mno-relax-immediates -mwide-bitfields
-mno-wide-bitfields -m4byte-functions -mno-4byte-functions
-mcallgraph-data -mno-callgraph-data -mslow-bytes -mno-slow-bytes
-mno-lsim -mlittle-endian -mbig-endian -m210 -m340
-mstack-increment
๐ญ MeP Options ๐ญ
the last one in this batch, bestie, we're almost through the buffet โจ
-mabsdiff -mall-opts -maverage -mbased=n -mbitops
-mc=n -mclip -mconfig=name -mcop -mcop32 -mcop64 -mivc2 -mdc
-mdiv -meb -mel -mio-volatile -ml -mleadz -mm -mminmax -mmult
-mno-opts -mrepeat -ms -msatur -msdram -msim -msimnovec -mtf
-mtiny=n
๐ธ MicroBlaze Options ๐ธ
okay bestie, the MicroBlaze flags are up first and they're a whole lineup ๐
-msoft-float-mhard-float-msmall-divides-mcpu=cpu-mmemcpy-mxl-soft-mul-mxl-soft-div-mxl-barrel-shift-mxl-pattern-compare-mxl-stack-check-mxl-gp-opt-mno-clearbss-mxl-multiply-high-mxl-float-convert-mxl-float-sqrt-mbig-endian-mlittle-endian-mxl-reorder-mxl-mode-app-model-mpic-data-is-text-relative
๐ฆ MIPS Options ๐ฆ
the MIPS list is giant and iconic, so grab a snack ๐
-EL-EB-march=arch-mtune=arch-mips1-mips2-mips3-mips4-mips32-mips32r2-mips32r3-mips32r5-mips32r6-mips64-mips64r2-mips64r3-mips64r5-mips64r6-mips16-mno-mips16-mflip-mips16-minterlink-compressed-mno-interlink-compressed-minterlink-mips16-mno-interlink-mips16-mabi=abi-mabicalls-mno-abicalls-mshared-mno-shared-mplt-mno-plt-mxgot-mno-xgot-mgp32-mgp64-mfp32-mfpxx-mfp64-mhard-float-msoft-float-mno-float-msingle-float-mdouble-float-modd-spreg-mno-odd-spreg-mabs=mode-mnan=encoding-mdsp-mno-dsp-mdspr2-mno-dspr2-mmcu-mmno-mcu-meva-mno-eva-mvirt-mno-virt-mxpa-mno-xpa-mcrc-mno-crc-mginv-mno-ginv-mmicromips-mno-micromips-mmsa-mno-msa-mloongson-mmi-mno-loongson-mmi-mloongson-ext-mno-loongson-ext-mloongson-ext2-mno-loongson-ext2-mfpu=fpu-type-msmartmips-mno-smartmips-mpaired-single-mno-paired-single-mdmx-mno-mdmx-mips3d-mno-mips3d-mmt-mno-mt-mllsc-mno-llsc-mlong64-mlong32-msym32-mno-sym32-Gnum-mlocal-sdata-mno-local-sdata-mextern-sdata-mno-extern-sdata-mgpopt-mno-gopt-membedded-data-mno-embedded-data-muninit-const-in-rodata-mno-uninit-const-in-rodata-mcode-readable=setting-msplit-addresses-mno-split-addresses-mexplicit-relocs-mno-explicit-relocs-mcheck-zero-division-mno-check-zero-division-mdivide-traps-mdivide-breaks-mload-store-pairs-mno-load-store-pairs-munaligned-access-mno-unaligned-access-mmemcpy-mno-memcpy-mlong-calls-mno-long-calls-mmad-mno-mad-mimadd-mno-imadd-mfused-madd-mno-fused-madd-nocpp-mfix-24k-mno-fix-24k-mfix-r4000-mno-fix-r4000-mfix-r4400-mno-fix-r4400-mfix-r5900-mno-fix-r5900-mfix-r10000-mno-fix-r10000-mfix-rm7000-mno-fix-rm7000-mfix-vr4120-mno-fix-vr4120-mfix-vr4130-mno-fix-vr4130-mfix-sb1-mno-fix-sb1-mflush-func=func-mno-flush-func-mbranch-cost=num-mbranch-likely-mno-branch-likely-mcompact-branches=policy-mfp-exceptions-mno-fp-exceptions-mvr4130-align-mno-vr4130-align-msynci-mno-synci-mlxc1-sxc1-mno-lxc1-sxc1-mmadd4-mno-madd4-mrelax-pic-calls-mno-relax-pic-calls-mmcount-ra-address-mframe-header-opt-mno-frame-header-opt
๐ MMIX Options ๐
-mlibfuncs-mno-libfuncs-mepsilon-mno-epsilon-mabi=gnu-mabi=mmixware-mzero-extend-mknuthdiv-mtoplevel-symbols-melf-mbranch-predict-mno-branch-predict-mbase-addresses-mno-base-addresses-msingle-exit-mno-single-exit
๐ง MN10300 Options ๐ง
-mmult-bug-mno-mult-bug-mno-am33-mam33-mam33-2-mam34-mtune=cpu-type-mreturn-pointer-on-d0-mno-crt0-mrelax-mliw-msetlb
๐ Moxie Options ๐
-meb-mel-mmul.x-mno-crt0
๐ MSP430 Options ๐
-msim-masm-hex-mmcu=-mcpu=-mlarge-msmall-mrelax-mwarn-mcu-mcode-region=-mdata-region=-msilicon-errata=-msilicon-errata-warn=-mhwmult=-minrt-mtiny-printf-mmax-inline-shift=
โญ NDS32 Options โญ
-mbig-endian-mlittle-endian-mreduced-regs-mfull-regs-mcmov-mno-cmov-mext-perf-mno-ext-perf-mext-perf2-mno-ext-perf2-mext-string-mno-ext-string-mv3push-mno-v3push-m16bit-mno-16bit-misr-vector-size=num-mcache-block-size=num-march=arch-mcmodel=code-model-mctor-dtor-mrelax
๐ Nios II Options ๐
-G num-mgpopt=option-mgpopt-mno-gpopt-mgprel-sec=regexp-mr0rel-sec=regexp-mel-meb-mno-bypass-cache-mbypass-cache-mno-cache-volatile-mcache-volatile-mno-fast-sw-div-mfast-sw-div-mhw-mul-mno-hw-mul-mhw-mulx-mno-hw-mulx-mno-hw-div-mhw-div-mcustom-insn=N-mno-custom-insn-mcustom-fpu-cfg=name-mhal-msmallc-msys-crt0=name-msys-lib=name-march=arch-mbmx-mno-bmx-mcdx-mno-cdx
๐ Nvidia PTX Options ๐
-m64-mmainkernel-moptimize
๐ซถ OpenRISC Options ๐ซถ
-mboard=name-mnewlib-mhard-mul-mhard-div-msoft-mul-msoft-div-msoft-float-mhard-float-mdouble-float-munordered-float-mcmov-mror-mrori-msext-msfimm-mshftimm-mcmodel=code-model
๐ฅ PDP-11 Options ๐ฅ
-mfpu-msoft-float-mac0-mno-ac0-m40-m45-m10-mint32-mno-int16-mint16-mno-int32-msplit-munix-asm-mdec-asm-mgnu-asm-mlra
๐ picoChip Options ๐
-mae=ae_type-mvliw-lookahead=N-msymbol-as-address-mno-inefficient-warnings
๐ธ PowerPC Options ๐ธ
PowerPC Options are a little plot twist, bestie. Look at the RS/6000 and PowerPC Options section instead โจ
๐ฆ PRU Options ๐ฆ
-mmcu=mcu-minrt-mno-relax-mloop-mabi=variant
๐ RISC-V Options ๐
the RISC-V list is loooong, but every single one is here ๐ซถ
-mbranch-cost=N-instruction-mplt-mno-plt-mabi=ABI-string-mfdiv-mno-fdiv-mdiv-mno-div-misa-spec=ISA-spec-string-march=ISA-string-mtune=processor-string-mpreferred-stack-boundary=num-msmall-data-limit=N-bytes-msave-restore-mno-save-restore-mshorten-memrefs-mno-shorten-memrefs-mstrict-align-mno-strict-align-mcmodel=medlow-mcmodel=medany-mexplicit-relocs-mno-explicit-relocs-mrelax-mno-relax-mriscv-attribute-mmo-riscv-attribute-malign-data=type-mbig-endian-mlittle-endian-mstack-protector-guard=guard-mstack-protector-guard-reg=reg-mstack-protector-guard-offset=offset
โจ RL78 Options โจ
-msim-mmul=none-mmul=g13-mmul=g14-mallregs-mcpu=g10-mcpu=g13-mcpu=g14-mg10-mg13-mg14-m64bit-doubles-m32bit-doubles-msave-mduc-in-interrupts
๐ธ RS/6000 and PowerPC Options ๐ธ
this one is absolutely massive, so we're going full send ๐
-mcpu=cpu-type-mtune=cpu-type-mcmodel=code-model-mpowerpc64-maltivec-mno-altivec-mpowerpc-gpopt-mno-powerpc-gpopt-mpowerpc-gfxopt-mno-powerpc-gfxopt-mmfcrf-mno-mfcrf-mpopcntb-mno-popcntb-mpopcntd-mno-popcntd-mfprnd-mno-fprnd-mcmpb-mno-cmpb-mhard-dfp-mno-hard-dfp-mfull-toc-mminimal-toc-mno-fp-in-toc-mno-sum-in-toc-m64-m32-mxl-compat-mno-xl-compat-mpe-malign-power-malign-natural-msoft-float-mhard-float-mmultiple-mno-multiple-mupdate-mno-update-mavoid-indexed-addresses-mno-avoid-indexed-addresses-mfused-madd-mno-fused-madd-mbit-align-mno-bit-align-mstrict-align-mno-strict-align-mrelocatable-mno-relocatable-mrelocatable-lib-mno-relocatable-lib-mtoc-mno-toc-mlittle-mlittle-endian-mbig-mbig-endian-mdynamic-no-pic-mswdiv-msingle-pic-base-mprioritize-restricted-insns=priority-msched-costly-dep=dependence_type-minsert-sched-nops=scheme-mcall-aixdesc-mcall-eabi-mcall-freebsd-mcall-linux-mcall-netbsd-mcall-openbsd-mcall-sysv-mcall-sysv-eabi-mcall-sysv-noeabi-mtraceback=traceback_type-maix-struct-return-msvr4-struct-return-mabi=abi-type-msecure-plt-mbss-plt-mlongcall-mno-longcall-mpltseq-mno-pltseq-mblock-move-inline-limit=num-mblock-compare-inline-limit=num-mblock-compare-inline-loop-limit=num-mno-block-ops-unaligned-vsx-mstring-compare-inline-limit=num-misel-mno-isel-mvrsave-mno-vrsave-mmulhw-mno-mulhw-mdlmzb-mno-dlmzb-mprototype-mno-prototype-msim-mmvme-mads-myellowknife-memb-msdata-msdata=opt-mreadonly-in-sdata-mvxworks-G num-mrecip-mrecip=opt-mno-recip-mrecip-precision-mno-recip-precision-mveclibabi=type-mfriz-mno-friz-mpointers-to-nested-functions-mno-pointers-to-nested-functions-msave-toc-indirect-mno-save-toc-indirect-mpower8-fusion-mno-mpower8-fusion-mpower8-vector-mno-power8-vector-mcrypto-mno-crypto-mhtm-mno-htm-mquad-memory-mno-quad-memory-mquad-memory-atomic-mno-quad-memory-atomic-mcompat-align-parm-mno-compat-align-parm-mfloat128-mno-float128-mfloat128-hardware-mno-float128-hardware-mgnu-attribute-mno-gnu-attribute-mstack-protector-guard=guard-mstack-protector-guard-reg=reg-mstack-protector-guard-offset=offset-mprefixed-mno-prefixed-mpcrel-mno-pcrel-mmma-mno-mmma-mrop-protect-mno-rop-protect-mprivileged-mno-privileged
๐ฆ RX Options ๐ฆ
-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 ๐
-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
๐ Score Options ๐
-meb-mel-mnhwloop-muls-mmac-mscore5-mscore5u-mscore7-mscore7d
โญ SH Options โญ
-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 ๐ฅ
-mclear-hwcap-mno-clear-hwcap-mimpure-text-mno-impure-text-pthreads
๐ธ SPARC Options ๐ธ
Okay bestie, SPARC gets its own squad of flags ๐ฆ. These are the ones you can throw at it:
-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 vibes, no cap:
-Qy -Qn -YP,paths -Ym,dir
๐ TILE-Gx Options ๐
Tile-Gx has its own little set too โจ:
-mcpu=CPU -m32 -m64 -mbig-endian -mlittle-endian
-mcmodel=code-model
๐ง TILEPro Options ๐ง
TILEPro keeps it short and sweet ๐:
-mcpu=cpu -m32
๐ฆ V850 Options ๐ฆ
V850 has a whole lot going on, so buckle up ๐ซถ:
-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 ๐
Quick and classic:
-mg -mgnu -munix -mlra
๐ท Visium Options ๐ท
Visium's crew ๐:
-mdebug -msim -mfpu -mno-fpu -mhard-float
-msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
๐ธ VMS Options ๐ธ
VMS brings its own flags to the party ๐:
-mvms-return-codes -mdebug-main=prefix -mmalloc64
-mpointer-size=size
๐ VxWorks Options ๐
VxWorks, your flags are here ๐ซถ:
-mrtp -non-static -Bstatic -Bdynamic -Xbind-lazy
-Xbind-now
๐ x86 Options ๐
This is the big one bestie, the x86 list is absolutely massive ๐ญ. Take a breath and scroll ๐ธ:
-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
-mmove-max=bits -mstore-max=bits -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 -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 -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 -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
๐ช x86 Windows Options ๐ช
Windows folks, this one's for you ๐:
-mconsole -mcygwin -mno-cygwin -mdll
-mnop-fun-dllimport -mthread -municode -mwin32 -mwindows
-fno-set-stack-executable
โญ Xstormy16 Options โญ
Just one flag here, simple as that โจ:
-msim
๐ฅ Xtensa Options ๐ฅ
Xtensa is giving main character energy ๐ :
-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
๐ง zSeries Options ๐ง
zSeries doesn't have its own list here, it just points you over to the S/390 section ๐:
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. They always happen in that order, no skipping the line! GCC can preprocess and compile several files into several assembler input files, or into just one assembler input file โจ. Then each assembler input file makes an object file, and linking smooshes all the object files together (the ones you just compiled AND the ones you handed it) into one executable file ๐ง.
For any given input file, the file name suffix (the bit after the dot) 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 capital M ๐ .file.miiโ Objective-C++ source code that should not be preprocessed.file.hโ C, C++, Objective-C or Objective-C++ header file to be turned into a precompiled header (default), or C, C++ header file to be turned into an Ada spec (via the-fdump-ada-specswitch) ๐ธ.file.cc,file.cp,file.cxx,file.cpp,file.CPP,file.c++,file.Cโ C++ source code that must be preprocessed. Note that in.cxx, the last two letters must both be literallyx. Likewise,.Crefers to a literal capital C ๐.file.mm,file.Mโ Objective-C++ source code that must be preprocessed.file.miiโ Objective-C++ source code that should not be preprocessed.file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ header file to be turned into a precompiled header or Ada spec.file.f,file.for,file.ftnโ 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โ 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 that gets fed straight into linking. Any file name with no recognized suffix is treated this way ๐ซถ.
You can also name the input language yourself with the -x option ๐:
-x languageโ Specify explicitly the language for the following input files (rather than letting the compiler pick a default based on the file name suffix). This option applies to all following input files until the next-xoption. Possible values for language are:
c c-header cpp-output
c++ c++-header c++-system-header c++-user-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
ada
d
f77 f77-cpp-input f95 f95-cpp-input
go
-x noneโ Turn off any language specification, so subsequent files get handled by their file name suffixes (same as if-xhad never been used at all) ๐.
If you only want some stages of compilation, use -x (or filename suffixes) to tell gcc where to start, and one of the options -c, -S, or -E to say where gcc should stop. Heads up though: some combinations (for example, -x cpp-output -E) instruct gcc to do absolutely nothing ๐.
-cโ Compile or assemble the source files, but do not link. The linking stage just doesn't happen. The ultimate output is an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.
Unrecognized input files, which don't need compiling or assembling, are ignored.
-Sโ Stop after the stage of compilation proper; do not assemble. The output is an assembler code file for each non-assembler input file specified.
By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s.
Input files that don't require compilation are ignored.
-Eโ Stop after the preprocessing stage; do not run the compiler proper. The output is preprocessed source code, which gets sent to the standard output โจ.
Input files that don't require preprocessing are ignored.
-o file
Okay bestie, this is the main output boss ๐. -o file tells GCC where to put the primary output ๐, and it doesn't care what kind of output that is. Executable, object file, assembler file, preprocessed C code, it's all the same to -o โจ.
If you skip -o, GCC picks its own defaults ๐ธ. An executable goes in a.out, the object file for source.suffix goes in source.o, its assembler file goes in source.s, a precompiled header file goes in source.suffix.gch, and all preprocessed C source gets printed to standard output.
Okay, so -o only names the primary output, but it also affects what the aux and dump outputs get called ๐ฆ. Unless you override it, those land in the same directory as the primary output. For auxiliary outputs, the input file's suffix gets swapped for the suffix of the aux 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 aux and dump outputs is the primary output's base name. In compile and link commands, the primary output name (minus the executable suffix) gets combined with the input file name. If both share the same base name (ignoring the suffix), the result is just that base name. Otherwise they get concatenated with a dash between them ๐ง
Here are the examples, iykyk ๐
gcc -c foo.c ...
This will use foo.o as the primary output, and put aux outputs and dumps right next to it, e.g., aux file foo.dwo for -gsplit-dwarf, and dump file foo.c.???r.final for -fdump-rtl-final.
If a non-linker output file is explicitly specified, aux and dump files take the same base name by default ๐
gcc -c foo.c -o dir/foobar.o ...
This will name aux outputs dir/foobar.* and dump outputs dir/foobar.c.*.
A linker output instead prefixes the aux and dump outputs ๐
gcc foo.c bar.c -o dir/foobar ...
This will generally name aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and dump outputs dir/foobar-foo.c.* and dir/foobar-bar.c.*.
The one exception is when the executable shares the base name with the single input ๐
gcc foo.c -o dir/foo ...
In this case aux outputs are named dir/foo.* and dump outputs are named dir/foo.c.*.
The location and names of aux and dump outputs can be adjusted with the options -dumpbase, -dumpbase-ext, -dumpdir, -save-temps=cwd, and -save-temps=obj โจ
-dumpbase dumpbase
This option sets the base name for aux and dump output files ๐. It does not change the name of the primary output file. Intermediate outputs, when preserved, aren't treated as primary outputs. They count as auxiliary outputs instead.
gcc -save-temps -S foo.c
This saves the (no longer) temporary preprocessed file in foo.i, and then compiles to the (implied) output file foo.s.
gcc -save-temps -dumpbase save-foo -c foo.c
This preprocesses to save-foo.i, compiles to save-foo.s (now an intermediate, so it's an auxiliary output), and then assembles to the (implied) output file foo.o ๐
Without this option, dump and aux files take their names from the input file, or from the (non-linker) output file if one is explicitly given. Dump output files (like the ones requested by -fdump-* options) keep the input name suffix. Aux output files (the ones requested by other non-dump options, like "-save-temps", "-gsplit-dwarf", and "-fcallgraph-info") drop it.
You can get similar suffix differentiation between dump and aux outputs for an explicit -dumpbase basename.suf by also specifying -dumpbase-ext .suf ๐ฆ
If dumpbase is explicitly given with any directory component, then any dumppfx setting (like -dumpdir or -save-temps=*) gets ignored. Instead of appending to it, dumpbase fully overrides it ๐
gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
-dumpdir pfx- -save-temps=cwd ...
This creates aux and dump outputs named alt/foo.*, disregarding dir/ in -o, the ./ prefix implied by -save-temps=cwd, and pfx- in -dumpdir ๐
When -dumpbase shows up in a command that compiles multiple inputs, or that compiles and then links, it can get combined with dumppfx, same as under -dumpdir. Then each input file gets compiled using the combined dumppfx, and default values for dumpbase and auxdropsuf get computed for each input file ๐ง
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs, and it avoids overwriting the aux and dump outputs by using the dumpbase as a prefix. The aux and dump outputs end up named main-foo.* and main-bar.*.
An empty string given as dumpbase keeps the output basename from influencing how aux and dump outputs get named during compilation. Default values get computed instead ๐ซถ
gcc -c foo.c -o dir/foobar.o -dumpbase " ...
This will name aux outputs dir/foo.* and dump outputs dir/foo.c.*. Their basenames come from the input name, but the directory still defaults to the one from the output.
An empty-string dumpbase does not stop the output basename from being used during linking ๐ธ
gcc foo.c bar.c -o dir/foobar -dumpbase " -flto ...
The compilation of the source files will name aux outputs dir/foo.* and dir/bar.*, and dump outputs dir/foo.c.* and dir/bar.c.*. LTO recompilation during linking will use dir/foobar. as the prefix for dumps and aux files.
-dumpbase-ext auxdropsuf
When forming the name of an auxiliary output file (but not a dump output), this drops the trailing auxdropsuf from dumpbase before any suffixes get appended โจ. If you don't specify it, it defaults to the suffix of a default dumpbase. That means the suffix of the input file when -dumpbase isn't on the command line, or when dumpbase gets combined with dumppfx.
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.*, taking the location of the primary output and dropping the .c suffix from the dumpbase. Dump outputs keep the suffix: 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 the linker output base name gets appended to dumppfx, as described below ๐
gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
This creates main.out as the primary output, and avoids overwriting the aux and dump outputs by using the executable name minus auxdropsuf as a prefix. It creates aux outputs main-foo.* and main-bar.*, and dump outputs main-foo.c.* and main-bar.c.* ๐ฆ
-dumpdir dumppfx
When forming the name of an auxiliary or dump output file, this uses dumppfx as a prefix ๐
gcc -dumpdir pfx- -c foo.c ...
This creates foo.o as the primary output, and aux outputs named pfx-foo.*. It combines the given dumppfx with the default dumpbase, which comes from the default primary output and, in turn, from the input name. Dump outputs also take the input name suffix: pfx-foo.c.*.
If you want dumppfx to work 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 aux outputs named dir/bar.*. It combines the given dumppfx with the default dumpbase derived from the primary output name. Dump outputs also take the input name suffix: dir/bar.c.*.
By default, dumppfx is the location of the output file, unless the output file is a special file like "/dev/null". The options -save-temps=cwd and -save-temps=obj override that default, just like an explicit -dumpdir does. If you give several of these, the last one wins ๐
gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
This outputs foo.o, with aux 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. Dump outputs are named foo.c.* ๐
When you compile from multiple input files and specify -dumpbase, the dumpbase (minus an auxdropsuf suffix) plus a dash gets appended to the explicit or defaulted dumppfx. If the dumpbase contains any directory components, it overrides dumppfx instead. This way each of the multiple compilations gets differently named aux and dump outputs ๐ง
gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
This outputs aux dumps to dir/pfx-main-foo.* and dir/pfx-main-bar.*, appending dumpbase- to dumppfx. Dump outputs keep the input file suffix: dir/pfx-main-foo.c.* and dir/pfx-main-bar.c.*, respectively. Compare that with the single-input compilation:
gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
Applying -dumpbase to a single source does not compute and append a separate dumpbase per input file. Its aux and dump outputs go in dir/pfx-main.* ๐ซถ
When you compile and then link from multiple input files, an explicit or defaulted dumppfx also goes through the dumpbase- transformation above. That's the compilation of foo.c and bar.c from before, just without -c. If neither -dumpdir nor -dumpbase is given, the linker output base name (minus auxdropsuf if specified, or the executable suffix otherwise) plus a dash gets appended to the default dumppfx instead. Heads up though, unlike the earlier linking cases ๐
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
This does not append the output name main to dumppfx, because -dumpdir was explicitly specified. The goal is that an explicitly specified dumppfx can include the output name as part of its prefix, if you want that. Only an explicitly specified -dumpbase would get combined with it, so a meaningful option doesn't get discarded ๐ธ
When you compile and then link from a single input file, the linker output base name only gets appended to the default dumppfx (as above) if it doesn't share the base name with the single input file name. This was covered in the single-input linking cases above, but not with an explicit -dumpdir that stops the combination, even if -save-temps=* overrides it later ๐
gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
Auxiliary outputs get named foo.*, and dump outputs get named foo.c.*, and they land in the current working directory when you ask for it with -save-temps=cwd ๐โจ
Okay, here's the whole data flow, which is intuitive (though slightly imprecise, ngl) ๐ง ๐ 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 part, unless -dumpbase overrides it. If there are multiple inputs or you're linking, that dumpbase can get combined with dumppfx and taken from each input file ๐ธ Auxiliary output names for each input are formed by combining dumppfx, dumpbase minus its suffix, and the auxiliary output suffix. Dump output names are only different in that they keep the suffix from dumpbase ๐
When it comes to auxiliary and dump outputs made during LTO recompilation ๐ฅ, a combo of dumppfx and dumpbase gets passed down to lto-wrapper as a -dumpdir option. That combo can be the one you gave, or one derived from the linker output name (but not from inputs), even in cases where it wouldn't normally get used that way. The trailing period replaces the compiler-added dash, if there is one ๐
Since this program is involved in linking, it doesn't normally get any -dumpbase or -dumpbase-ext, and it ignores them ๐
When lto-wrapper runs sub-compilers, it tacks the LTO stage names onto the dumppfx it received ๐ง, makes sure that has a directory component so it overrides any -dumpdir, and passes the result along as -dumpbase to the sub-compilers ๐
-vโ Prints (on standard error) the commands that get run for each stage of compilation ๐ข It also prints the version number of the compiler driver, plus the preprocessor and the compiler proper ๐-###โ Basically-v, but nothing actually runs ๐ โโ๏ธ Arguments get quoted unless they only contain alphanumeric characters or./-_. This is perfect for shell scripts that want to snag the command lines the driver generates ๐--helpโ Prints (on stdout) a rundown of the command-line optionsgccunderstands ๐ If-vis also on,--helpgets passed along to all the processesgccinvokes, so they can show the options they accept too ๐ซถ If-Wextrawas specified as well (before--help), then options with no documentation also get displayed ๐ฆ--target-helpโ Prints (on stdout) a description of the target-specific options for each tool ๐ฏ For some targets, extra target-specific info might get printed too โจ--help={class|[^]qualifier}[,...]โ Prints (on stdout) a description of the options the compiler understands that fit into all the classes and qualifiers you specify ๐ Here are the classes:optimizersโ Shows every optimization option the compiler supports โกwarningsโ Shows every option that controls the warning messages the compiler produces ๐จtargetโ Shows target-specific options. Unlike--target-help, the target-specific options of the linker and assembler are not shown, because those tools don't support the extended--help=syntax yet ๐paramsโ Shows the values--paramrecognizes ๐งชlanguageโ Shows the options supported for language, where language is one of the languages this GCC version supports ๐ If an option is supported by all languages, you need to pick thecommonclass insteadcommonโ Shows the options that are common to all languages ๐ซง
And here are the qualifiers:
undocumentedโ Shows only the options that are undocumented ๐joinedโ Shows options that take an argument appearing after an equal sign, in the same continuous piece of text, like--help=target๐separateโ Shows options that take an argument appearing as a separate word right after the original option, like-o output-fileโ๏ธ
So if you want every undocumented target-specific switch the compiler supports, use:
--help=target,undocumented
You can flip a qualifier by prefixing it with the ^ character ๐ For example, to show all binary warning options (the ones that are either on or off and don't take an argument) that do have a description, use:
--help=warnings,^joined,^undocumented
The argument to --help= should not consist solely of inverted qualifiers ๐ซ
You can combine several classes, but that usually narrows the output so much there's nothing left to show ๐ญ One case where it does work is when one of the classes is target. To show all the target-specific optimization options, use:
--help=target,optimizers
The --help= option can be repeated on the command line ๐ Each use displays its requested class of options, skipping anything already shown. If --help is also specified anywhere on the command line, it takes precedence over any --help= option ๐
If -Q appears on the command line before --help=, the descriptive text changes ๐ Instead of describing the options, it tells you whether each option is enabled, disabled, or set to a specific value (assuming the compiler knows that at the point where --help= is used) ๐
Here's a truncated example from the ARM port of gcc:
% gcc -Q -mabi=2 --help=target -c
The following options are target specific:
-mabi= 2
-mabort-on-noreturn [disabled]
-mapcs [disabled]
The output is sensitive to the effects of previous command-line options ๐งฉ So, for example, you can find out which optimizations are enabled at -O2 by using:
-Q -O2 --help=optimizers
Or 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โ Normallygccexits with the code of1if any phase of the compiler returns a non-success return code ๐ญ If you specify-pass-exit-codes,gccinstead returns the numerically highest error produced by any phase that returned an error indication ๐ The C, C++, and Fortran front ends return4if they hit an internal compiler error ๐-pipeโ Uses pipes rather than temporary files for communication between the various stages of compilation ๐ฆ
This fails to work on some systems where the assembler can't read from a pipe, but the GNU assembler has no trouble with it โ ๏ธ
-specs=fileโ Processes file after the compiler reads in the standard specs file ๐ This overrides the defaults thegccdriver uses when deciding which switches to pass tocc1,cc1plus,as,ld, etc. ๐งพ You can specify more than one-specs=fileon the command line, and they 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, like this:
gcc -c t.c -wrapper gdb,--args
This invokes all subprograms of gcc under gdb --args, so the invocation of cc1 is gdb --args cc1 .... ๐
-ffile-prefix-map=old=newโ When compiling files living in directory old, any references to them in the compilation result get recorded as if the files lived in directory new instead ๐บ๏ธ Specifying this is equivalent to specifying all the individual-f*-prefix-mapoptions ๐ง It's handy for reproducible builds that don't depend on location ๐ See also-fmacro-prefix-map,-fdebug-prefix-mapand-fprofile-prefix-map๐-fplugin=name.soโ Loads the plugin code in name.so, which is assumed to be a shared object the compiler willdlopen๐ The base name of the shared object file is used to identify the plugin for argument parsing (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 called key with a value of value for the plugin called name ๐-fdump-ada-spec[-slim]โ For C and C++ source and include files, generates the corresponding Ada specs ๐-fada-spec-parent=unitโ Used together with-fdump-ada-spec[-slim]above, this generates Ada specs as child units of the parent unit ๐ถ-fdump-go-spec=fileโ For input files in any language, generates the corresponding Go declarations in file ๐น This makes Goconst,type,var, andfuncdeclarations, which can be a super useful way to start writing a Go interface to code written in some other language ๐ซถ@fileโ Reads command-line options from file ๐ The options read are inserted in place of the original@fileoption ๐ If file doesn't exist or can't be read, then the option gets treated literally and is not removed ๐
Options in file are separated by whitespace. A whitespace character can be included in an option by surrounding the entire option in either single or double quotes โจ Any character (including a backslash) can be included by prefixing it with a backslash ๐ฆ The file can contain additional @file options too, 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) ๐ no cap, that's iconic ๐ฅ
However, here's the tea, bestie ๐ญ using gcc does not add the C++ library. That's where g++ slides in ๐
. It's basically gcc with a glow-up: it calls GCC and automatically specifies linking against the C++ library โจ. It also treats .c, .h and .i files as C++ source files instead of C source files, unless you use -x ๐ฆ. It's handy for precompiling a C header file with a .h extension for use in C++ compilations ๐ง. On lots of systems, g++ is also installed as c++ ๐ธ.
When you're compiling C++ ๐, you can use a bunch of the same command-line options you'd use for any language, or options meaningful for C and its relatives, or options that only matter for C++ programs. Mix and match, queen ๐.
๐ Options Controlling C Dialect
These options decide which flavour of C (or C-derived languages like C++, Objective-C and Objective-C++) the compiler is willing to accept ๐:
๐
-ansi
In C mode, it's basically the same as -std=c90 ๐. In C++ mode, it's the same as -std=c++98.
This one is a lot ๐. It switches off GCC features that clash with ISO C90 (for C code) or standard C++ (for C++ code). That means no asm and typeof keywords, and no predefined macros like unix and vax that tell you what kind of system you're on ๐. It also switches on the undesirable, rarely used ISO trigraph feature (nobody asked for that, bestie ๐ญ). For the C compiler, it also disables // comments (the C++ style ones) and the inline keyword.
The alternate keywords __asm__, __extension__, __inline__ and __typeof__ keep working even with -ansi ๐ฆ. You wouldn't use them in a strict ISO C program, obviously, but they're super handy in header files that might get included in -ansi builds ๐ง. The alternate predefined macros __unix__ and __vax__ are around too, with or without -ansi โจ.
-ansi won't go around rejecting non-ISO programs for no reason ๐
. If you want that, you need -Wpedantic on top of -ansi, periodt.
When -ansi is on, the macro __STRICT_ANSI__ is predefined ๐ฅ. Some header files might notice it and skip declaring certain functions or defining macros the ISO standard doesn't ask for, so they don't mess with programs that use those names for other stuff ๐ซถ.
Functions that are usually built in but don't have ISO C semantics (like alloca and ffs) stop being built-in functions under -ansi ๐.
โจ -std=
This one picks the language standard ๐. Right now it only works when compiling C or C++.
The compiler can accept several base standards, like c90 or c++98, plus GNU dialects of those, like gnu90 or gnu++98. When you specify a base standard, the compiler accepts every program following that standard, plus any GNU extensions that don't contradict it. For example, -std=c90 turns off GCC features that clash with ISO C90, like the asm and typeof keywords, but it keeps other GNU extensions that don't mean anything in ISO C90, like leaving out the middle term of a ?: expression.
Now here's the twist ๐. When you pick a GNU dialect, every feature the compiler supports gets enabled, even if those features change the meaning of the base standard. So some strictly conforming programs might get rejected. The chosen standard is what -Wpedantic uses to figure out which features are GNU extensions for that version. For example, -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic doesn't.
You have to give this option a value ๐จ. The possible values are:
c90,c89,iso9899:1990โ Supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code.iso9899:199409โ ISO C90 as modified by amendment 1.c99,c9x,iso9899:1999,iso9899:199xโ ISO C99 ๐. It's substantially, like, completely supported, minus bugs and floating-point drama (mostly with optional C99 features from Annexes F and G). Peephttps://gcc.gnu.org/c99status.htmlfor more info ๐. Heads up,c9xandiso9899:199xare deprecated ๐.c11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard. It's substantially completely supported, minus bugs, floating-point issues (mainly but not entirely about optional C11 features from Annexes F and G), and the optional Annexes K (Bounds-checking interfaces) and L (Analyzability). The namec1xis deprecated.c17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision of the ISO C standard (published in 2018). It's 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.c2xโ The next version of the ISO C standard, still under development ๐งช. Support is experimental and incomplete.gnu90,gnu89โ GNU dialect of ISO C90 (including some C99 features) ๐ธ.gnu99,gnu9xโ GNU dialect of ISO C99. The namegnu9xis deprecated.gnu11,gnu1xโ GNU dialect of ISO C11. The namegnu1xis deprecated.gnu17,gnu18โ GNU dialect of ISO C17. This is the default for C code ๐.gnu2xโ The next version of the ISO C standard, still under development, plus GNU extensions ๐งช. Support is experimental and incomplete.c++98,c++03โ The 1998 ISO C++ standard plus the 2003 technical corrigendum and some extra 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โ 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โ GNU dialect of-std=c++2b. Support is highly experimental and will almost certainly change in incompatible ways in future releases ๐.
๐ -aux-info filename
This one dumps prototyped declarations for every function declared and/or defined in a translation unit (header files included ๐ง) into the file you name. It's silently ignored in any language that isn't C ๐คซ.
The file also has extra info tucked into comments ๐. It tells you where each declaration came from (source file and line), and whether it was implicit, prototyped or unprototyped (I, N for new or O for old, respectively, in the first character after the line number and the colon). It also tells you whether the declaration came from a declaration or a definition (C or F, respectively, in the following character). For function definitions, you also get a K&R-style list of arguments followed by their declarations, also in comments, right after the declaration.
-fallow-parameterless-variadic-functionsโ Lets you accept variadic functions with no named parameters ๐ฆ. You can define one, but it's not super useful since you can't read the arguments ๐คท. This is only supported for C, because C++ already allows this construct.
๐
-fno-asm
This stops GCC from treating asm, inline or typeof as keywords ๐, so your code can use those words as identifiers. Use __asm__, __inline__ and __typeof__ instead. In C, -ansi implies -fno-asm.
In C++, inline is a standard keyword, so this switch doesn't touch it ๐. You might want -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.
๐ -fno-builtin, -fno-builtin-function
This tells GCC to not recognize built-in functions that don't start with the __builtin_ prefix ๐
.
Normally GCC has special tricks for certain built-in functions ๐ง . For instance, alloca calls might become single instructions that adjust the stack directly, and memcpy calls might turn into inline copy loops. The code is often smaller and faster ๐๏ธ. But since those calls no longer show up as calls, you can't set a breakpoint on them, and you can't change what the functions do by linking against a different library ๐.
Also, once something's recognized as a built-in, GCC may use what it knows about it to warn about bad calls, or to generate more efficient code, even if the result still contains calls to that function. For example, you get -Wformat warnings for bad calls to printf when printf is built in and strlen is known not to modify global memory ๐ซถ.
With -fno-builtin-function, only the built-in version of function gets switched off ๐
. function can't begin with __builtin_ (that one's a hard rule ๐
โโ๏ธ). If the function you name isn't a built-in in your GCC version, the option just gets ignored, no drama โจ. There's no -fbuiltin-function buddy to flip it back on, BUT if you want to pick and choose built-ins while using -fno-builtin or -ffreestanding, you can define your own macros, like:
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fcond-mismatchโ Lets conditional expressions have mismatched types in the second and third arguments ๐ฆ. When that happens, the value of the expression isvoid. This one isn't supported for C++, so keep it in C land, bestie ๐.-ffreestandingโ Tells GCC your compilation targets a freestanding environment ๐ง. This implies-fno-builtin. In a freestanding environment, the standard library might not exist, and program startup might not necessarily be atmain. The most obvious example is an OS kernel ๐. This is equivalent to-fno-hosted.-fgimpleโ Enables parsing of function definitions marked with__GIMPLEโจ. It's experimental and lets you unit test GIMPLE passes ๐งช.-fgnu-tmโ Makes the compiler generate code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009) ๐ฅ. It's experimental, so the interface might change in future GCC versions as the official spec changes. Not every architecture is supported, so check before you commit to the vibe ๐ซถ.
For more info on GCC's support for transactional memory,
Note: the transactional memory feature is not supported with non-call exceptions (-fnon-call-exceptions). ๐
-fgnu89-inlineโ Tells GCC to use the traditional GNU semantics forinlinefunctions when you're in C99 mode ๐. Using it is roughly the same as adding thegnu_inlinefunction attribute to every inline function.-fno-gnu89-inlineโ Explicitly tells GCC to use C99 semantics forinlinewhen you're in C99 orgnu99mode (aka the default behavior ๐ธ). This option isn't supported in-std=c90or-std=gnu90mode.
Wanna check which inline semantics are active? The preprocessor macros __GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__ can help you check ๐.
-fhostedโ Asserts that compilation targets a hosted environment, which implies-fbuiltin๐. A hosted environment has the entire standard library available, andmainreturns anint. Basically everything except a kernel. This is equivalent to-fno-freestanding.-flax-vector-conversionsโ Allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types ๐. This option should not be used for new code, bestie, I mean it ๐ญ.-fms-extensionsโ Accepts some non-standard constructs used in Microsoft header files ๐ช. In C++ code, this allows member names in structures to be similar to previous type declarations:
typedef int UOW;
struct ABC {
UOW UOW;
};
Some cases of unnamed fields in structures and unions are only accepted with this option. Also, this option is off for all targets except x86 targets using ms-abi โ ๏ธ.
-foffload=disable,-foffload=default,-foffload=target-listโ Picks which OpenMP and OpenACC offload targets get code generated ๐ฏ. The default behavior, same as-foffload=default, is to generate code for all supported offload targets.-foffload=disablegenerates code only for the host fallback, and-foffload=target-listgenerates code only for the comma-separated list of offload targets you specify.
Offload targets are written in GCC's internal target-triplet format. Run the compiler with -v to see the list of configured offload targets under "OFFLOAD_TARGET_NAMES" ๐.
-foffload-options=options,-foffload-options=target-triplet-list=optionsโ With-foffload-options=options, GCC passes your options to the compilers for all enabled offloading targets ๐. For options that only apply to a specific target or targets, use the-foffload-options=target-list=optionsform. The target-list is a comma-separated list in the same format as the-foffload=option.
Typical command lines are:
-foffload-options=-lgfortran -foffload-options=-lm
-foffload-options="-lgfortran -lm" -foffload-options=nvptx-none=-latomic
-foffload-options=amdgcn-amdhsa=-march=gfx906 -foffload-options=-lm
-fopenaccโ Turns on handling of OpenACC directives:#pragma accin C/C++ and!$accin Fortran ๐. When you use it, 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โ Sets default compute dimensions for parallel offload regions that don't explicitly specify their own ๐. Thegeomvalue is a triple of:-separated sizes, in the ordergang,worker, andvector. You can leave a size out to use a target-specific default value.-fopenmpโ Turns on handling of OpenMP directives:#pragma ompin C/C++ and!$ompin Fortran โจ. When you use it, 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 with-pthreadsupport.-fopenmpalso implies-fopenmp-simd๐ซถ.-fopenmp-simdโ Turns on handling of OpenMP's SIMD directives written with#pragma ompin C/C++ and!$ompin Fortran ๐ฆ. Other OpenMP directives are ignored.-fpermitted-flt-eval-methods=styleโ Big brain energy ๐ง . ISO/IEC TS 18661-3 defines new permissible values forFLT_EVAL_METHODthat say operations and constants with a semantic type that's an interchange or extended format should be evaluated at the precision and range of that type. These new values are a superset of the ones allowed under C99/C11, which doesn't specify what other positive values mean. So code that conforms to C11 may not have been written expecting the new values ๐ค.
-fpermitted-flt-eval-methods controls whether the compiler allows only the C99/C11 values, or the extended set from ISO/IEC TS 18661-3. style is either c11 or ts-18661-3, as appropriate.
The default in a standards-compliant mode (-std=c11 or similar) is -fpermitted-flt-eval-methods=c11. The default in a GNU dialect (-std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3.
-fplan9-extensionsโ Accepts some non-standard constructs used in Plan 9 code ๐. This enables-fms-extensions, permits passing pointers to structures with anonymous fields to functions that expect pointers to elements of the type of the field, and permits referring to anonymous fields declared using a typedef. It's only supported for C, not C++, sorry C++ girlies ๐ญ.-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 eithersignedorunsigned๐. By default, such a bit-field is signed, because that's consistent: basic integer types likeintare signed types.-fsigned-charโ Lets the typecharbe signed, likesigned char๐. This is equivalent to-fno-unsigned-char, which is the negative form of-funsigned-char. Likewise,-fno-signed-charis equivalent to-funsigned-char.-funsigned-charโ Lets the typecharbe unsigned, likeunsigned char๐. Each kind of machine has a default for whatcharshould be: it's either likeunsigned charby default, or likesigned charby default.
Ideally, a portable program should always use 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 each of signed char or unsigned char, even though its behavior is always just like one of those two ๐ง.
-fsso-struct=endiannessโ Sets the default scalar storage order of structures and unions to the endianness you specify ๐งฒ. The accepted values arebig-endian,little-endian, andnative(the native endianness of the target, which is the default). This option is not supported for C++.
Warning: the -fsso-struct switch causes GCC to generate code that is not binary compatible with code generated without it if the specified endianness is not the native endianness of the target. ๐ฌ
โจ Options Controlling C++ Dialect โจ
This section covers the command-line options that are only meaningful for C++ programs ๐. You can still use most of the 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 this 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 versionnof the C++ ABI ๐. The default is version0.- Version
0refers to the version conforming most closely to the C++ ABI specification. Therefore, the ABI obtained using version0will change in different versions of G++ as ABI bugs are fixed. - Version
1is the version of the C++ ABI that first appeared in G++ 3.2. - Version
2is the version of the C++ ABI that first appeared in G++ 3.4, and was the default through G++ 4.9. - Version
3corrects an error in mangling a constant address as a template argument.
- Version
Version 4 first showed up in G++ 4.5 and gave vector types a standard mangling ๐
Version 5, first in G++ 4.6, fixed the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and using a function parameter in the declaration of another parameter ๐ธ
Version 6, first in G++ 4.7, fixed 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 in G++ 4.8, treats nullptr_t as a builtin type and fixes the mangling of lambdas in default argument scope โจ
Version 8, first in G++ 4.9, fixed the substitution behavior of function types with function-cv-qualifiers ๐
Version 9, first in G++ 5.2, fixed the alignment of "nullptr_t" ๐
Version 10, first in G++ 6.1, added mangling for attributes that affect type identity, like ia32 calling convention attributes (e.g. stdcall) ๐ง
Version 11, first in G++ 7, fixed 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 changes starting with the twelfth occurrence. It also implies -fnew-inheriting-ctors ๐
Version 12, first in G++ 8, fixed the calling conventions for empty classes on the x86_64 target and for classes with only deleted copy/move constructors ๐ But it accidentally changed the calling convention for classes with a deleted copy constructor and a trivial move constructor ๐ญ
Version 13, first in G++ 8.2, fixes that accidental change from version 12 ๐ซถ
Version 14, first in G++ 10, fixed the mangling of the nullptr expression ๐
Version 15, first in G++ 11, changes the mangling of __alignof__ so it's distinct from alignof, plus dependent operator names ๐ฆ
See also -Wabi ๐
-fabi-compat-version=nโ On targets that support strong aliases, G++ works around mangling changes by making an alias with the correct mangled name whenever it defines a symbol with an incorrect mangled name. This switch picks which ABI version that alias uses ๐
With -fabi-version=0 (the default), this defaults to 11 (GCC 7 compatibility). If you explicitly pick another ABI version, it defaults to 0. For compatibility with GCC versions 3.2 through 4.9, use -fabi-compat-version=2 ๐งธ
If this option isn't given but -Wabi=n is, that version gets used for the compatibility aliases. If this option is given along with -Wabi (without the version), the version from this option is used for the warning ๐
-fno-access-controlโ Turns off all access checking ๐ It's mainly useful for working around bugs in the access control code ๐ ๏ธ-faligned-newโ Enables support for C++17newof types that need more alignment thanvoid* ::operator new(std::size_t)provides โจ You can pass a number like-faligned-new=32to say how much alignment (in bytes) that function provides, but few users will need to override the default ofalignof(std::max_align_t)๐ธ
This flag is enabled by default for -std=c++17 ๐
-fchar8_t,-fno-char8_tโ Enables support forchar8_t, as adopted for C++20 ๐ This adds a newchar8_tfundamental type, changes the types of UTF-8 string and character literals, gives user-defined literals new signatures, comes with associated standard library updates, and adds the new__cpp_char8_tand__cpp_lib_char8_tfeature 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, though ๐ฌ The change to the types of UTF-8 string and character literals introduces incompatibilities with ISO C++11 and later standards. For example, the following code is well-formed under ISO C++11, but is ill-formed when -fchar8_t is specified:
char ca[] = u8"xx"; // error: char-array initialized from wide
// string
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โ Checks that the pointer returned byoperator newis non-null before it tries to modify the storage allocated ๐ You usually don't need this, because the C++ standard saysoperator newonly returns 0 if it's declaredthrow(). In that case the compiler always checks the return value, even without this option ๐ง In all other cases, whenoperator newhas a non-empty exception specification, memory exhaustion is signalled by throwingstd::bad_alloc. See alsonew (nothrow)๐ซง-fconcepts,-fconcepts-tsโ Below-std=c++20,-fconceptsenables support for the C++ Extensions for Concepts Technical Specification, ISO 19217 (2015) ๐งฉ
With -std=c++20 and above, Concepts are part of the language standard, so -fconcepts defaults to on. But the standard specification of Concepts differs significantly from the TS, so some constructs that were allowed in the TS but didn't make it into the standard can still be enabled with -fconcepts-ts ๐ฆ
-fconstexpr-depth=nโ Sets the maximum nested evaluation depth for C++11constexprfunctions ton๐ A limit is needed so endless recursion can be detected during constant expression evaluation. The minimum the standard specifies is512๐-fconstexpr-cache-depth=nโ Sets the maximum level of nested evaluation depth for C++11constexprfunctions that will be cached ton๐๏ธ This is a heuristic that trades compilation speed (when the cache avoids repeated calculations) against memory consumption (when the cache grows very large from highly recursive evaluations). The default is8๐ธ
Very few users are likely to want to adjust it, but if your code does heavy constexpr calculations, you might want to experiment to find which value works best for you ๐
-fconstexpr-fp-exceptโ Annex F of the C standard specifies that IEC559 floating point exceptions encountered at compile time should not stop compilation ๐ค C++ compilers have historically not followed that guidance, instead treating 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 that a particular operation is undefined:
constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
-fconstexpr-loop-limit=nโ Sets the maximum number of iterations for a loop in C++14constexprfunctions ton๐ A limit is needed to detect infinite loops during constant expression evaluation. The default is262144(1<<18) ๐ฏ-fconstexpr-ops-limit=nโ Sets the maximum number of operations during a singleconstexprevaluation ๐งฎ Even when the iterations of a single loop are limited by the limit above, you can still get a too-longconstexprevaluation if there are several nested loops that each have lots of iterations (but are still under that limit), or if too many expressions need evaluating in the body of some loop or even outside of a loop. The default is33554432(1<<25) ๐ซ-fcoroutinesโ Enables support for the C++ coroutines extension (experimental) ๐งต-fno-elide-constructorsโ The C++ standard lets an implementation skip creating a temporary that's only used to initialize another object of the same type โ๏ธ This 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 be expanded inline ๐
In C++17, the compiler is required to omit these temporaries, but this option still affects trivial member functions ๐ง
-fno-enforce-eh-specsโ Don't generate code that checks for violations of exception specifications at run time ๐ This option violates the C++ standard, but it may be useful for reducing code size in production builds, much like definingNDEBUG๐
๐ Heads up, bestie: This does not give user code permission to throw exceptions in violation of the exception specifications. The compiler still optimizes based on the specifications, so throwing an unexpected exception results in undefined behavior at run time.
-fextern-tls-init,-fno-extern-tls-initโ โจ okay so 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 the setup. When the use and the definition are in the same translation unit (TU), the overhead can get optimized away ๐ . But if the use is in a different TU, there's a lot of 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 a use in the defining TU always runs first), 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 do not support symbol aliases, the default is -fno-extern-tls-init ๐ธ.
-fno-gnu-keywordsโ ๐ Stopstypeoffrom being treated as a keyword, so you can totally use it as a normal identifier. If you still want the keyword, use__typeof__instead ๐. This is already implied by the strict ISO C++ dialects, like-ansi,-std=c++98,-std=c++11, and so on.-fimplicit-constexprโ ๐ฆ Makes inline functions implicitlyconstexprwhenever they meet the requirements for aconstexprfunction. This only works in C++14 mode or later. It can flip initialization from dynamic to static, plus a few other optimizations pop off โจ.-fno-implicit-templatesโ ๐ Never emits code for non-inline templates that get instantiated implicitly (aka just by using them). Only explicit instantiations get code.
โ ๏ธ If you use this option, you have to structure your code so it includes all the explicit instantiations you need, or you'll get undefined symbols at link time. Be careful, bestie ๐ญ.
-fno-implicit-inline-templatesโ ๐ Doesn'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, this skips emitting out-of-line copies of inline functions controlled by#pragma implementation.
๐ This causes linker errors if those functions aren't inlined everywhere they're called. Not it.
-fmodules-ts,-fno-modules-tsโ ๐ Enables support for C++20 modules. You usually don't need-fno-modules-ts, because that's already the default. Even though modules are a C++20 feature, selecting that standard version doesn't implicitly turn this on right now ๐.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ ๐ง Compiles a header file into an importable header unit.-fmodule-implicit-inlineโ ๐ฅ Member functions defined inside their class definitions are not implicitly inline for modular code. This is different from traditional C++ behavior, and there are good reasons for it. It can cause a bit of trouble when porting code, though. This option makes those function definitions implicitly inline.
๐จ It does generate an ABI incompatibility, so you have to use it everywhere or nowhere. (Definitions outside of a named module stay implicitly inline no matter what.)
-fno-module-lazyโ ๐ฆ Disables lazy module importing and module mapper creation.-fmodule-mapper=[hostname]:port[?ident],-fmodule-mapper=|program[?ident] args...,-fmodule-mapper==socket[?ident],-fmodule-mapper=<>[inout][?ident],-fmodule-mapper=<in>out[?ident],-fmodule-mapper=file[?ident]โ ๐ฎ This is an oracle that answers questions about module name to filename mappings. If you don't specify one, theCXX_MODULE_MAPPERenvironment variable gets used. If that's unset too, you get an in-process default โจ.-fmodule-onlyโ ๐ธ Only emits the Compiled Module Interface, and blocks any object file from being made ๐ โโ๏ธ.-fms-extensionsโ ๐ Turns offWpedanticwarnings about constructs used in MFC, like implicitintand grabbing a pointer to a member function with non-standard syntax. It's giving legacy codebase energy ๐ .-fnew-inheriting-ctorsโ ๐ Enables the P0136 adjustment to the semantics of C++11 constructor inheritance. It's part of C++17, but it's also considered a Defect Report against C++11 and C++14. This flag is on by default, unless you specify-fabi-version=10or lower ๐.-fnew-ttp-matchingโ ๐ Enables the P0522 resolution to Core issue 150. This covers template template parameters and default arguments, and it lets a template with default template arguments be used as an argument for a template template parameter that has fewer template parameters. This flag is on by default for-std=c++17โจ.-fno-nonansi-builtinsโ ๐งน Disables built-in declarations of functions that aren't mandated by ANSI/ISO C. That includesffs,alloca,_exit,index,bzero,conjf, and other related functions ๐.-fnothrow-optโ ๐ญ Treats athrow()exception specification as if it were anoexceptspecification. This can reduce or eliminate the text size overhead compared to a function with no exception specification. If the function has local variables with non-trivial destructors, the exception specification can actually make the function smaller, because the EH cleanups for those variables can be optimized away ๐ง .
The semantic effect is that an exception thrown out of a function with this exception specification results in a call to terminate instead of unexpected ๐ญ.
-fno-operator-namesโ ๐ฆ Stops the operator name keywordsand,bitand,bitor,compl,not,or, andxorfrom being treated as synonyms for keywords. Bye-bye, operator name vibes ๐.-fno-optional-diagsโ ๐ท Disables diagnostics that the standard says a compiler doesn't need to issue. Right now, the only one G++ issues like that is the one for a name that has multiple meanings within a class ๐คทโโ๏ธ.-fpermissiveโ ๐ Downgrades some diagnostics about nonconformant code from errors to warnings. So using-fpermissivelets some nonconforming code compile. Bold choice, but it's your call ๐ .-fno-pretty-templatesโ ๐ When an error message refers to a specialization of a function template, the compiler normally prints the template's signature, followed by the template arguments and any typedefs or typenames in the signature. For example, you'd seevoid f(T) [with T = int]instead ofvoid f(int), so it's clear which template is involved ๐. When an error message refers to 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 those behaviors makes the error harder to read instead of easier, you can use-fno-pretty-templatesto turn them off ๐ซถ.-fno-rttiโ ๐ง Disables generation of information about every class with virtual functions. That info is used by the C++ run-time type identification features (dynamic_castandtypeid). If you don't use those parts of the language, you can save some space with this flag โจ. Exception handling uses the same information, but G++ generates it only as needed. Thedynamic_castoperator can still be used for casts that don't require run-time type information, like casts tovoid *or to unambiguous base classes ๐.
โ ๏ธ Mixing code compiled with-frttiand code compiled with-fno-rttimay not work. For example, programs may fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti๐.
-fsized-deallocationโ ๐ฅ Enables the built-in global declarations below, as 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, say, 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 you 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 enumeration's values. (As the C++ standard defines it, 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 turn an arbitrary integer value into the enumerated type, so be careful with casts ๐ซฃ.
-fstrong-eval-orderโ ๐ง Evaluates member access, array subscripting, and shift expressions in left-to-right order, and evaluates assignment in right-to-left order, as adopted for C++17. It's enabled by default with-std=c++17.-fstrong-eval-order=someonly enables the ordering of member access and shift expressions, and it's the default without-std=c++17๐ฆ.-ftemplate-backtrace-limit=nโ ๐ธ Sets the maximum number of template instantiation notes shown for a single warning or error ton. The default is10๐.-ftemplate-depth=nโ ๐ Sets the maximum instantiation depth for template classes ton. You need a limit like this to catch endless recursions during template class instantiation ๐. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than17(which changed to1024in C++11). The default is900, because the compiler can run out of stack space before it hits1024in some situations ๐ญ.-fno-threadsafe-staticsโ ๐งต Doesn't emit the extra code that uses the C++ ABI routines for thread-safe initialization of local statics. If your code doesn't need to be thread-safe, this option can shave off a bit of code size ๐.-fuse-cxa-atexitโ ๐ Registers destructors for objects with static storage duration with the__cxa_atexitfunction, instead of theatexitfunction. This option is required for fully standards-compliant handling of static destructors.
๐ฅบ It only works if your C library supports __cxa_atexit.
-fno-use-cxa-get-exception-ptrโ ๐ โโ๏ธ Doesn'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โ ๐ Declares that the user doesn't try to compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects.
๐ซฃ This is a promise you're making to the compiler, so make sure it's true!
The effect of all this is that GCC can, effectively, mark inline methods with __attribute__ ((visibility ("hidden"))) ๐ซถ So they stay out of the export table of a DSO and don't need a PLT indirection when they're used inside that DSO ๐ฆ Turning this on can have a dramatic effect on load and link times of a DSO, because it massively shrinks the dynamic export table when the library leans hard on templates ๐ญโจ
This switch doesn't behave exactly like marking the methods as hidden directly ๐ It doesn't affect static variables local to the function, and it doesn't make the compiler deduce that the function is defined in only one shared object.
You can give a method an explicit visibility to negate the effect of the switch for that method ๐ For example, if you do want to compare pointers to a particular inline method, you might mark it as having default visibility. Marking the enclosing class with explicit visibility has no effect ๐
Explicitly instantiated inline methods are unaffected by this option, since their linkage might otherwise cross a shared library boundary ๐ธ
-fvisibility-ms-compatโ This flag tries to use visibility settings to make GCC's C++ linkage model match Microsoft Visual Studio's ๐
The flag 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 are permitted when this option is not used.
In new code it's better to use -fvisibility=hidden and export only the classes that are meant to be externally visible ๐ง Unfortunately, code can end up relying on the Visual Studio behavior, perhaps accidentally ๐ญ
Among the consequences of these changes: static data members of the same type, with the same name, but 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, it's a violation of the ODR (the One Definition Rule) to define types with the same name differently โ ๏ธ
-fno-weakโ Skip weak symbol support, even if the linker provides it. By default, G++ uses weak symbols if 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. This option may be removed in a future release of G++ ๐-fext-numeric-literals(C++ and Objective-C++ only) โ Accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions. When this option is turned off, these 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โ Informs you of include translation events ๐ The first one notes accepted include translations, and the second notes declined include translations. The=headerform informs you of include translations relating to that specific header. If header is of the form"user"or"<system>", it gets resolved to a specific user or system header using the include path.-flang-info-module-cmi,-flang-info-module-cmi=moduleโ Informs you of Compiled Module Interface pathnames ๐ The first one notes all read CMI pathnames. The=moduleform will not reading a specific module's CMI. module may be a named module or a header-unit. The latter 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 alternate C++ runtime libraries ๐ There are two options: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). The option 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.
On top of that, these warning options only mean something 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 ๐ฌ However, 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 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.
-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 warning points out cases where CTAD only succeeded because the compiler synthesized the implicit deduction guides, which might not be what the programmer intended. Certain style guides only allow CTAD on types that specifically "opt-in" (that is, 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) { }
};
S(allow_ctad_t) -> S<void>; // guide with incomplete parameter type will never be considered
-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.-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ Warns whendeleteis used to destroy an instance of a class that has virtual functions and a non-virtual destructor ๐ฅ It's unsafe to delete an instance of a derived class through a pointer to a base class if the base class doesn't have a virtual destructor. This warning is enabled by-Wall.-Wdeprecated-copy(C++ and Objective-C++ only) โ Warns that the implicit declaration of a copy constructor or copy assignment operator is deprecated, if the class has a user-provided copy constructor or copy assignment operator, in C++11 and up ๐ This warning is enabled by-Wextra. With-Wdeprecated-copy-dtor, it also flags the implicit declaration as deprecated if the class has a user-provided destructor.-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only) โ Disables the warning about the case when the usual arithmetic conversions are applied to operands where one is an enumeration type and the other is a different enumeration type ๐ This conversion was deprecated in C++20. For example:
enum E1 { e };
enum E2 { f };
int k = f - e;
-Wdeprecated-enum-enum-conversion is enabled by default with -std=c++20. In pre-C++20 dialects, this warning can be enabled by -Wenum-conversion.
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only) โ Disables the warning about the case when the usual arithmetic conversions are applied to operands where one is an enumeration type and the other is a floating-point type ๐ This conversion was deprecated in C++20. For example:
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7;
-Wdeprecated-enum-float-conversion is enabled by default with -std=c++20. In pre-C++20 dialects, this warning can be enabled by -Wenum-conversion.
-Wno-init-list-lifetime(C++ and Objective-C++ only) โ Don't warn about uses ofstd::initializer_listthat are likely to result in dangling pointers ๐ซ The underlying array for aninitializer_listis handled like a normal C++ temporary object, so it's super easy to accidentally keep a pointer to the array past the end of its lifetime. For example:- If a function returns a temporary
initializer_list, or a localinitializer_listvariable, the array's lifetime ends at the end of the return statement, so the returned value has a dangling pointer. - If a new-expression creates an
initializer_list, the array only lives until the end of the enclosing full-expression, so theinitializer_liston the heap has a dangling pointer. - When an
initializer_listvariable is assigned from a brace-enclosed initializer list, the temporary array created for the right side of the assignment only lives until the end of the full-expression. So at the next statement, theinitializer_listvariable has a dangling pointer.
// 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
Undefined behavior alert, bestie ๐ Don't let your code hit that last line!
- When a list constructor stores the "begin" pointer from the "initializer_list" argument, this doesn't extend the lifetime of the array, so if a class variable is constructed from a temporary "initializer_list", the pointer is left dangling by the end of the variable declaration statement. ๐
-Winvalid-imported-macrosโ okay so this one double-checks that all imported macro definitions are still valid once compilation wraps up โจ It's not on by default because figuring that out takes extra processing ๐ But it's super handy when you're putting together sets of header-units and need your macros to stay consistent ๐-Wno-literal-suffix(C++ and Objective-C++ only) โ don't warn when a string or character literal is followed by a ud-suffix that doesn't begin with an underscore ๐ GCC is being nice here. As a conforming extension, it treats those suffixes as separate preprocessing tokens so older code using the formatting macros from<inttypes.h>keeps working ๐ง Like this:
#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 gets treated as its own separate preprocessing token. Iconic behavior, honestly ๐
This option also controls warnings when a user-defined literal operator is declared with a literal suffix identifier that doesn't begin with an underscore. Literal suffix identifiers that don't begin with an underscore are reserved for future standardization, so GCC is watching out for that ๐
These warnings are enabled by default โ
-Wno-narrowing(C++ and Objective-C++ only) โ for C++11 and later, narrowing conversions get diagnosed by default, just like the standard requires ๐ A narrowing conversion from a constant gives an error, and a narrowing conversion from a non-constant gives a warning. This flag suppresses that diagnostic ๐ โโ๏ธ Just know it doesn't change the meaning of well-formed code, and narrowing conversions are still ill-formed in SFINAE contexts, so don't get too comfy ๐ค
With -Wnarrowing in C++98, GCC warns when a narrowing conversion that C++11 prohibits happens inside { }, for example:
int i = { 2.2 }; // error: narrowing from double to int
This flag is included in -Wall and -Wc++11-compat ๐ธ
-Wnoexcept(C++ and Objective-C++ only) โ warns when a noexcept-expression evaluates to false because of a call to a function that doesn't have a non-throwing exception specification (throw()ornoexcept), even though the compiler knows it never actually throws an exception ๐ฆ-Wnoexcept-type(C++ and Objective-C++ only) โ warns if the C++17 feature that makesnoexceptpart of a function type changes the mangled name of a symbol compared to C++14 ๐ฅ It's enabled by-Wabiand-Wc++17-compat. Here's the plot twist:
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>. The noexcept sneaks right into the type ๐ซฃ
-Wclass-memaccess(C++ and Objective-C++ only) โ warns when the destination of a call to a raw memory function such asmemsetormemcpyis an object of class type, and writing into that object might bypass a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers ๐ Messing with the representation of these objects can break invariants that the class's member functions rely on. For example, thismemsetis 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 is to initialize or clear these objects using the appropriate constructor or assignment operator, if one is available ๐ซถ The -Wclass-memaccess option is enabled by -Wall. And if you explicitly cast the pointer to the class object to void *, or to a type that the raw memory function can safely access, the warning goes quiet ๐คซ
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ warns when a class has virtual functions and an accessible non-virtual destructor, either on itself or in an accessible polymorphic base class ๐ฅด That makes it possible but unsafe to delete a derived class instance through a pointer to the class itself or its base class. This warning is automatically enabled if-Weffc++is specified ๐-Wregister(C++ and Objective-C++ only) โ warns on uses of theregisterstorage class specifier, except when it's part of the GNU Explicit Register Variables extension ๐ Theregisterkeyword as a storage class specifier was deprecated in C++11 and removed in C++17. It's enabled by default with-std=c++17๐๏ธ-Wreorder(C++ and Objective-C++ only) โ warns when the order of member initializers in the code doesn't match the order they must actually run in ๐ For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler rearranges the member initializers for i and j to match the declaration order of the members, and emits a warning about it. This warning is enabled by -Wall โจ
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this one warns when a call tostd::moveprevents copy elision ๐ โโ๏ธ A typical scenario where copy elision can happen is returning from a function with a class return type, when the expression being returned is the name of a non-volatile automatic object, that object is not a function parameter, and it has the same type as the function's return type. Like this:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
But in this example, the std::move call is what blocks copy elision, so the vibe is off ๐ฆ This warning is enabled by -Wall.
-Wno-redundant-move(C++ and Objective-C++ only) โ warns about redundant calls tostd::move, which means a move operation would have happened even without thestd::movecall ๐ง That happens because the compiler is forced to treat the object as an rvalue in certain situations, like returning a local variable where copy elision isn't applicable. Consider:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant, no cap ๐
โโ๏ธ Because G++ implements Core Issue 1579, here's another example:
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's return type differ. Even so, G++ treats the return value as if it were designated by an rvalue anyway ๐
This warning is enabled by -Wextra ๐งก
-Wrange-loop-construct(C++ and Objective-C++ only) โ warns when a C++ range-based for-loop is making an unnecessary copy ๐๏ธ This can happen 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 ๐ธ
This warning also goes off when a loop variable in a range-based for-loop is initialized with a value of a different type, resulting in a copy. For example:
void fn() {
int arr[10];
for (const double &x : arr) { ... }
}
In the example above, every iteration creates and destroys a temporary value of type double, and the reference const double & gets bound to that temporary ๐
This warning is enabled by -Wall ๐
-Wredundant-tags(C++ and Objective-C++ only) โ warns about redundant class-key and enum-key in references to class types and enumerated types, in contexts where the key can be dropped without causing an ambiguity ๐งผ For example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
On the other hand, there's no warning in this example:
struct foo;
void foo (); // "hides" struct foo
void bar (struct foo&); // no warning, keyword struct is necessary
Here the function foo hides the struct, so the struct keyword is actually needed ๐ง
-Wno-subobject-linkage(C++ and Objective-C++ only) โ don't warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐ If a type A depends on a type B with no linkage 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 too. GCC doesn't warn 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) โ warns about violations of the following style guidelines from Scott Meyers' Effective C++ series of books ๐โจ- Define a copy constructor and an assignment operator for classes with dynamically-allocated memory.
- Prefer initialization to assignment in constructors.
- Have
operator=return a reference to*this. - Don't try to return a reference when you must return an object.
- Distinguish between prefix and postfix forms of increment and decrement operators.
- Never overload
&&,||, or,.
This option also enables -Wnon-virtual-dtor, which is also one of the effective C++ recommendations. However, the check is extended to warn about the lack of a virtual destructor in accessible non-polymorphic base classes too ๐
Okay so when you turn this one on, bestie, heads up ๐
: the standard library headers don't follow all of these guidelines, so they'll throw warnings too. Use grep -v to filter those out ๐ซถ
-Wno-exceptions(C++ and Objective-C++ only) โ Silences the warning for when one exception handler is shadowed by another one ๐. It can be a sign that your exception handlers are in the wrong order.-Wstrict-null-sentinel(C++ and Objective-C++ only) โ Warns you about using an uncastedNULLas a sentinel ๐. If you're only compiling with GCC, it actually works, sinceNULLis defined as__null. It's a null pointer constant rather than a null pointer, but it's guaranteed to be the same size as a pointer. Just know this isn't portable across different compilers, so it's not it ๐.-Wno-non-template-friend(C++ and Objective-C++ only) โ Turns off warnings for non-template friend functions declared inside a template ๐ฆ. Super old GCC versions, from before the ISO standard existed, could read something likefriend int foo(int)as a specific template specialization, when the name of the friend is an unqualified-id. This warning exists to catch those compatibility problems, and it's on by default.-Wold-style-cast(C++ and Objective-C++ only) โ Warns you when a C-style cast to a non-void type shows up 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 they're the move โจ.-Woverloaded-virtual(C++ and Objective-C++ only) โ Warns when a function declaration hides virtual functions from a base class ๐ญ. Check out this drama:
struct A {
virtual void f();
};
struct B: public A {
void f(int);
};
The A class version of f gets hidden in B, so code like this:
B* b;
b->f();
fails to compile ๐.
-Wno-pmf-conversions(C++ and Objective-C++ only) โ Disables the diagnostic for converting a bound pointer to member function into a plain pointer ๐ธ.-Wsign-promo(C++ and Objective-C++ only) โ Warns when overload resolution picks a promotion from an unsigned or enumerated type to a signed type, instead of a conversion to an unsigned type of the same size ๐ง. Older G++ versions tried to keep the unsignedness, but the standard requires the current behavior, so this is just how it is.-Wtemplates(C++ and Objective-C++ only) โ Warns when a primary template declaration shows up ๐. Some coding rules ban templates, and this option can help enforce that rule. It's inactive inside system header files, like the STL, so you can still use the STL ๐. You're also still allowed to instantiate or specialize templates.-Wmismatched-new-delete(C++ and Objective-C++ only) โ Warns about mismatches between calls tooperator neworoperator deleteand the matching allocation or deallocation function ๐ฅ. That covers C++operator deletebeing called on pointers that came from mismatched forms ofoperator new, or from other functions that allocate objects whereoperator deleteisn't a suitable deallocator. It also covers other deallocation functions being called on pointers fromoperator newwhen that deallocation function isn't suitable.
In the function below, the delete expression gets flagged because it doesn't match the array form of the new expression that the pointer came from. The call to free gets flagged too ๐:
void f ()
{
int *a = new int[n];
delete a; // warning: mismatch in array forms of expressions
char *p = new char[n];
free (p); // warning: mismatch between new and free
}
The related option -Wmismatched-dealloc handles mismatches involving allocation and deallocation functions other than operator new and operator delete ๐. -Wmismatched-new-delete is included in -Wall.
-Wmismatched-tags(C++ and Objective-C++ only) โ Warns when you declare structs, classes, or class templates (and their specializations) with a class-key that doesn't match the definition, or the first declaration if there's no definition ๐. In the example below, thestruct Objectin the argument list ofdrawtriggers the warning. To avoid it, either drop the redundantstructclass-key or swap it forclassto match the definition:
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
Using the struct class-key here isn't wrong, and this option is really about keeping your class declarations stylistically consistent ๐ซถ. If you're writing code that's meant to be portable to Windows-based compilers, the warning helps stop unresolved references, since symbols declared with different class-keys get mangled differently. You can use this option on its own or alongside -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, and this can enforce that. It's inactive inside system header files, like the STL, so the STL is still good to go. You can also define classes that indirectly use multiple inheritance.-Wvirtual-inheritanceโ Warns when a class is defined with a virtual direct base class ๐ฆ. Some coding rules ban multiple inheritance, and this can help enforce that rule. It's inactive inside system header files, like the STL, so you can still use the STL. You can also define classes that indirectly use virtual inheritance.-Wno-virtual-move-assignโ Suppresses warnings about inheriting from a virtual base that has a non-trivial C++11 move assignment operator ๐. This one is dangerous ๐จ. If the virtual base can be reached 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 an already moved-from object, you can safely disable this warning.-Wnamespacesโ Warns when a namespace definition is opened ๐ธ. Some coding rules ban namespaces, and this helps enforce that. It's inactive inside system header files, like the STL, so the STL is still fair game. You can also use using directives and qualified names.-Wno-terminate(C++ and Objective-C++ only) โ Turns off 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, which is a syntactic ambiguity in C++ ๐. 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, for example, removing the parentheses or using braces instead โจ. This warning is enabled by default.
-Wno-class-conversion(C++ and Objective-C++ only) โ Stops the warning for when a conversion function converts an object to the same type, to a base class of that type, or tovoid๐ง. These conversion functions will never be called, so the warning doesn't really help you here.-Wvolatile(C++ and Objective-C++ only) โ Warns about deprecated uses of thevolatilequalifier ๐ญ. That includes postfix and prefix++and--expressions onvolatile-qualified types, simple assignments where the left operand is avolatile-qualified non-class type (for their value), and compound assignments where the left operand is avolatile-qualified non-class type. It also coversvolatile-qualified function return types,volatile-qualified parameter types, and structured bindings of avolatile-qualified type. This usage was deprecated in C++20.
This is enabled by default with -std=c++20 ๐.
-Wzero-as-null-pointer-constant(C++ and Objective-C++ only) โ Warns when a literal0is used as a null pointer constant ๐ . This can be super useful for making the switch 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 this only warns about global allocation functions, but -Waligned-new=all also warns about class member allocation functions ๐.
-Wno-placement-new,-Wplacement-new=nโ Warns about placement new expressions with undefined behavior ๐ณ. One example is constructing an object in a buffer that's smaller than the object's type. The placement new expression below gets diagnosed, because it tries to construct an array of 64 integers in a buffer that's only 64 bytes large:
char buf [64];
new (buf) int[64];
This warning is enabled by default โญ.
-Wplacement-new=1โ This is the default warning level for-Wplacement-new๐ฆ. At this level, the warning isn't issued for some strictly undefined constructs that GCC allows as extensions for compatibility with legacy code. For example, thenewexpression below isn't diagnosed at this level, even though it has undefined behavior according to the C++ standard, because it writes past the end of the one-element array ๐:
struct S { int n, a[1]; };
S *s = (S *)malloc (sizeof *s + 31 * sizeof s->a[0]);
new (s->a)int [32]();
Okay so, level 2 of -Wplacement-new=2 is where it gets spicy ๐ถ๏ธ On top of everything level 1 catches, GCC also flags placement new expressions that build an object in the last member of a struct whose array has just one element, when that member's size is smaller than the object being built ๐ญ The previous example would get flagged, but the flexible array member extension lets you dodge the warning at level 2 ๐ฆ
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ Bestie, this one warns you when a catch handler doesn't catch by reference ๐ซถ With-Wcatch-value=1(or just-Wcatch-value), you get warned about polymorphic class types that get caught by value.-Wcatch-value=2extends that to every class type caught by value, and-Wcatch-value=3goes further and warns about all types that aren't caught by reference ๐-Wcatch-valueis turned on by-Wall, so you're already covered ๐-Wconditionally-supported(C++ and Objective-C++ only) โ Warns you about conditionally-supported constructs, as defined by C++11[intro.defs]๐ง-Wno-delete-incomplete(C++ and Objective-C++ only) โ Turns off the warning for deleting a pointer to an incomplete type. That can cause undefined behavior at runtime ๐ This warning is on by default, so this flag is how you silence it ๐-Wextra-semi(C++, Objective-C++ only) โ Catches redundant semicolons after in-class function definitions ๐-Wno-inaccessible-base(C++, Objective-C++ only) โ Controls the warning for when a base class can't be reached from a derived class because of ambiguity. It's on by default โจ The warning for ambiguous virtual bases is actually turned on by-Wextra, not by this one ๐ Check out this drama:
struct A { int a; };
struct B : A { };
struct C : B, A { };
-Wno-inherited-variadic-ctorโ Hushes the warnings about C++11 inheriting constructors when the base class has a C variadic constructor. This warning is on by default because the ellipsis doesn't get inherited ๐ธ-Wno-invalid-offsetof(C++ and Objective-C++ only) โ Mutes warnings for using theoffsetofmacro on a non-POD type. The 2014 ISO C++ standard says that's undefined when the type isn't standard-layout ๐ฌ In real C++ implementations,offsetofusually still gives you meaningful results, so this flag is for people who know their code isn't portable and have decided to ignore the warning on purpose ๐ The rules aroundoffsetofmight get relaxed in a future version of the C++ standard, so keep an eye out โญ-Wsized-deallocation(C++ and Objective-C++ only) โ Warns when you define an unsized deallocation function without the matching sized one, or the other way around. Here's the unsized pair:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
And here's the sized pair:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
This is turned on by -Wextra along with -fsized-deallocation ๐ฅ
-Wsuggest-final-typesโ Warns about types with virtual methods where the code would be better if the type were declaredfinalin C++11, or, if that's possible, declared inside an anonymous namespace ๐ That lets GCC devirtualize polymorphic calls more aggressively. It works best with link-time optimization, since that gives the compiler a more complete picture of the class hierarchy ๐ฆ-Wsuggest-final-methodsโ Warns about virtual methods that would benefit from the C++11finalspecifier, or, if possible, from having their type declared in an anonymous namespace or withfinal๐ Like the one above, this is more useful with link-time optimization, when the class hierarchy graph is more complete. The recommended move is to look at the-Wsuggest-final-typessuggestions first, then rebuild with the new annotations ๐ซถ-Wsuggest-overrideโ Warns when you override virtual functions without marking them with theoverridekeyword ๐-Wuse-after-free,-Wuse-after-free=nโ Warns about uses of pointers to dynamically allocated objects that a deallocation function has made indeterminate ๐ญ It's enabled at every optimization level, but the results can differ between optimized and unoptimized builds ๐-Wuse-after-free=1โ At level 1, the warning only tries to catch unconditional uses of pointers that a deallocation call or a successfulreallochas made indeterminate. That's true whether or not the call actually moved the memory ๐ง It includes doublefreecalls and uses in arithmetic and relational expressions. Uses of indeterminate pointers in equality (or inequality) expressions aren't diagnosed at this level, even though they're still undefined ๐-Wuse-after-free=2โ At level 2, the warning also catches conditional uses of pointers made indeterminate by a deallocation call, on top of the unconditional ones. Equality (or inequality) expressions still aren't diagnosed here either ๐ In this function, the secondfreeis the one that gets flagged at this level:
struct A { int refcount; void *data; };
void release (struct A *p)
{
int refcount = --p->refcount;
free (p);
if (refcount == 0)
free (p->data); // warning: p may be used after free
}
-Wuse-after-free=3โ At level 3, the warning also catches uses of indeterminate pointers in equality expressions ๐ Every use of an indeterminate pointer is undefined, but equality tests sometimes show up afterrealloccalls, as a way to check whether the object got moved to a new address ๐ Those get their own level so legacy code can move over to safe alternatives gradually. In the function below, the equality test is the one flagged at this level:
void adjust_pointers (int**, int);
void grow (int **p, int n)
{
int **q = (int**)realloc (p, n *= 2);
if (q == p)
return;
adjust_pointers ((int**)q, n);
}
To dodge the warning at this level, store offsets into the allocated memory instead of raw pointers. That way you never have to fix up stored pointers after a reallocation โจ
-Wuse-after-free=2 is included in -Wall ๐
-Wuseless-cast(C++ and Objective-C++ only) โ Warns when an expression gets cast to its own type. Totally pointless, honestly ๐-Wno-conversion-null(C++ and Objective-C++ only) โ Doesn't warn about conversions betweenNULLand non-pointer types.-Wconversion-nullis on by default ๐ธ
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
NOTE: This manual doesn't cover the Objective-C and Objective-C++ languages themselves ๐
This section is all about the command-line options that only matter for Objective-C and Objective-C++ programs ๐ง You can still use most of the language-independent GNU compiler options too. For example, you might compile a file called some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
Here, -fgnu-runtime only applies to Objective-C and Objective-C++ programs. You can use the other options with any language GCC supports ๐
Since Objective-C is an extension of C, Objective-C compilations can also use options specific to the C front end (like -Wtraditional). Likewise, Objective-C++ compilations can use C++-specific options (like -Wabi) ๐
Here's the list of options that are only for compiling Objective-C and Objective-C++ programs ๐
-fconstant-string-class=class-nameโ Usesclass-nameas the class to instantiate for each literal string written as@"...". The default class name isNXConstantStringwhen the GNU runtime is in use, andNSConstantStringwhen the NeXT runtime is in use (see below) ๐ If-fconstant-cfstringsis also present, it overrides-fconstant-string-classand makes@"..."literals get laid out as constant CoreFoundation strings โจ-fgnu-runtimeโ Generates object code that's compatible with the standard GNU Objective-C runtime. This is the default on most systems ๐ฆ-fnext-runtimeโ Generates output compatible with the NeXT runtime. This is the default on NeXT-based systems, including Darwin and Mac OS X ๐ When this option is used, the macro__NEXT_RUNTIME__is predefined, and only then ๐ซถ-fno-nil-receiversโ Assumes that every Objective-C message dispatch ([receiver message:arg]) in this translation unit makes sure the receiver isn'tnil. That lets the runtime use more efficient entry points ๐ฅ This option only works together 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 ๐ธ In that case, version 0 is the traditional (32-bit) ABI without support for properties or other Objective-C 2.0 additions. Version 1 is the traditional (32-bit) ABI with support for properties and other Objective-C 2.0 additions. Version 2 is the modern (64-bit) ABI ๐ If you don't specify anything, the default is version 0 on 32-bit target machines and version 2 on 64-bit target machines ๐-fobjc-call-cxx-cdtorsโ okay so this one is giving main character energy ๐ For every Objective-C class, GCC 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 on the instance variables, in order, then returnsself. It does the same check for destructors. If an instance variable is a C++ object with a non-trivial destructor, it synthesizes- (void) .cxx_destruct, which runs all those default destructors in reverse order ๐ฅ- The
- (id) .cxx_constructand- (void) .cxx_destructmethods it generates only handle instance variables declared in the current Objective-C class. Anything inherited from superclasses is not included ๐ โโ๏ธ - It's the Objective-C runtime's job to call all of these methods throughout an object's inheritance hierarchy.
- The runtime invokes
- (id) .cxx_constructimmediately after a new object instance is allocated, and it invokes- (void) .cxx_destructimmediately before it deallocates an object instance. - As of this writing, only the NeXT runtime on Mac OS X 10.4 and later can actually invoke
- (id) .cxx_constructand- (void) .cxx_destruct๐
- The
-fobjc-direct-dispatchโ lowkey a speed boost โจ It lets the compiler take fast jumps straight to the message dispatcher. On Darwin, this is handled through the comm page ๐ฆ-fobjc-exceptionsโ bestie, this one unlocks structured exception handling in Objective-C, kind of like what C++ has ๐ You need it 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โ this turns on garbage collection (GC) for Objective-C and Objective-C++ programs ๐งน It's only available with the NeXT runtime. The GNU runtime has its own, different garbage collection setup that doesn't need any special compiler flags, so no cap, you don't need this one there ๐-fobjc-nilcheckโ for the NeXT runtime with version 2 of the ABI, this checks for a nil receiver in method invocations before the actual method call happens โจ It's the default, and you can turn it off with-fno-objc-nilcheck. Class methods and super calls are never checked for nil this way, no matter what this flag is set to ๐ โโ๏ธ Right now this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is in use.-fobjc-std=objc1โ this makes you conform to the syntax of Objective-C 1.0, the language GCC 4.0 understood ๐ It only affects the Objective-C additions to C/C++. It doesn't touch conformance to C/C++ standards, which is handled by the separate C/C++ dialect option flags. With the Objective-C or Objective-C++ compiler, any Objective-C syntax GCC 4.0 wouldn't recognize gets rejected. This is super useful if you need to be sure your Objective-C code still compiles with older versions of GCC ๐-freplace-objc-classesโ this emits a special marker that tellsld(1)not to statically link the resulting object file in, and letsdyld(1)load it at run time instead ๐ง It's paired with the Fix-and-Continue debugging mode, where the object file might get recompiled and dynamically reloaded while the program is running, so you don't have to restart the whole thing ๐ Right 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, GCC normally swaps calls toobjc_getClass("...")(when the class name is known at compile time) for static class references that get set up at load time, which is faster โก This flag stops that and keeps theobjc_getClass("...")calls around. It's useful in Zero-Link debugging mode, since it lets you modify individual class implementations while the program runs ๐ซถ The GNU runtime always keeps calls toobjc_get_class("...")no matter which command-line options you use ๐คทโโ๏ธ-fno-local-ivarsโ by default, instance variables in Objective-C can be accessed as if they were local variables inside the methods of the class they're declared in. That can cause shadowing between instance variables and other variables, whether they're declared locally in a class method or globally with the same name ๐ญ Using-fno-local-ivarsturns that behavior off, so you avoid the shadowing drama ๐ซ-fivar-visibility=[public|protected|private|package]โ this sets the default instance variable visibility to whichever option you pick ๐ธ Instance variables declared outside the scope of any access modifier directive then default to that visibility.-gen-declsโ this dumps interface declarations for every class seen in the source file into a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ warns you whenever an Objective-C assignment is getting intercepted by the garbage collector ๐จ-Wno-property-assign-default(Objective-C and Objective-C++ only) โ this stops the warning you'd get when a property for an Objective-C object has no assign semantics specified ๐-Wno-protocol(Objective-C and Objective-C++ only) โ okay so if a class says it implements a protocol, you normally get a warning for every method in that protocol the class doesn't implement. By default, you also get a warning for methods that aren't explicitly implemented in the class, even when the implementation is inherited from the superclass. With-Wno-protocol, inherited methods count as implemented, and no warning is issued for them ๐ซถ-Wobjc-root-class(Objective-C and Objective-C++ only) โ warns if a class interface doesn't have a superclass. Most classes inherit fromNSObject(orObject), for example ๐ณ If you're making a class that's meant to be a root class, you can silence the warning by marking its interface with__attribute__((objc_root_class))๐-Wselector(Objective-C and Objective-C++ only) โ warns if multiple methods of different types for the same selector show up during compilation ๐ It also checks each selector that appears in a@selector(...)expression, and warns if a matching method for that selector was found during compilation. These checks scan the method table only at the very end of compilation, so the warnings won't show up if the final stage never gets reached. That happens if an error stops compilation partway, or if you're using-fsyntax-only๐ฅฒ-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if multiple methods with different argument and/or return types exist for a selector when you're sending a message with it to a receiver of typeidorClass๐ This flag is off by default. With it off, the compiler skips these warnings when the differences are confined to types that have the same size and alignment ๐-Wundeclared-selector(Objective-C and Objective-C++ only) โ warns if a@selector(...)expression refers to an undeclared selector. A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, either explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection ๐ This option checks as soon as it finds a@selector(...)expression, while-Wselectoronly checks in the final stage of compilation. It also enforces the coding style rule that methods and selectors must be declared before they're used ๐-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, this section is all about how your error messages look ๐ Traditionally, diagnostic messages were formatted without caring about the output device (its width and stuff). With the options below, you can control the formatting algorithm, like how many characters go on a line or how often source location info gets reported. Heads up that some language front ends might not honor these options ๐ซฃ
-fmessage-length=nโ tries to format error messages so they fit on lines aboutncharacters wide ๐ Ifnis zero, no line-wrapping happens and every error message stays on one line. This is the default for all front ends.
Note: this option also affects how#errorand#warningpre-processor directives display, plus 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 runningdejagnuor other utilities that parse diagnostics output and need it to stay more stable over time. Right now,-fdiagnostics-plain-outputis equivalent to:-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never -fdiagnostics-urls=never -fdiagnostics-path-format=separate-events. If GCC ever changes the default look of its diagnostics, the matching option to turn off that new behavior will get added to this list ๐ฎ-fdiagnostics-show-location=onceโ only matters in line-wrapping mode ๐ It tells the diagnostic reporter to emit source location info once. So if a message is too long for one physical line and gets wrapped, the source location isn't 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 diagnostic reporter to emit the same source location info as a prefix on every physical line that results from breaking up a message that's too long to fit on a single line ๐ซถ-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ okay bestie, this one is all about color ๐WHENcan benever,always, orauto. The default depends on how your compiler was set up ๐ . It can be any of thoseWHENoptions, orneverif theGCC_COLORSenvironment variable isn't present in the environment, andautootherwise.autoonly lets GCC get colorful when standard error is a terminal and it's not running in an emacs shell ๐.-fdiagnostics-colorand-fno-diagnostics-colorare just shortcuts for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively โจ.
The colors are controlled by the environment variable GCC_COLORS ๐. Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings. The terminal or terminal emulator is the one that actually interprets SGR commands (check the section in your text terminal's docs for the permitted values and what they mean as character attributes ๐). These substring values are decimal integers that can be concatenated with semicolons. Common values to concatenate 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 modes foreground colors49for default background color40to47for background colors100to107for 16-color mode background colors48;5;0to48;5;255for 88-color and 256-color modes background colors
The default GCC_COLORS is:
error=01;31:warning=01;35:note=01;36:range1=32:range2=34:locus=01:\
quote=01:path=01;36:fixit-insert=32:fixit-delete=31:\
diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
type-diff=01;32
Where 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 disables colors ๐
โโ๏ธ. 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."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.-fdiagnostics-urls[=WHEN]โ okay this one is so cute ๐ฆ. It uses escape sequences to embed URLs in diagnostics. For example, when-fdiagnostics-show-optionprints the text showing the command-line option that controls a diagnostic, it can embed a URL pointing to the docs for that option ๐.
WHEN is never, always, or auto. auto makes GCC use URL escape sequences only when standard error is a terminal, and when it's not running in an emacs shell or in 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 above WHEN options.
GCC can also be configured (via the --with-diagnostics-urls=auto-if-env configure-time option) so the default is affected by environment variables. Under that setup, GCC defaults to auto if either the GCC_URLS or TERM_URLS environment variables are present and non-empty in the compiler's environment, or to 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 are not embedded in diagnostics. - If it's set to
st, URLs use ST escape sequences. - If it's set to
bel, which is the default, URLs use BEL escape sequences. - Any other non-empty value enables the feature.
If GCC_URLS is not set, TERM_URLS is used as a fallback. Note: ST is an ANSI escape sequence with the string terminator ESC \, and BEL is an ASCII character, CTRL-G, that usually sounds like a beep ๐.
GCC tries to detect a few terminals that are known to not implement the URL feature, and that have bugs (or at least had bugs in some versions still in use) where URL escapes are likely to misbehave, i.e., print garbage on the screen ๐. That list is currently xfce4-terminal, certain known buggy gnome-terminal versions, the linux console, and mingw. This check can be skipped with -fdiagnostics-urls=always.
-fno-diagnostics-show-optionโ by default, each diagnostic emitted includes text indicating the command-line option that directly controls it (if that option is known to the diagnostic machinery) ๐. Specifying-fno-diagnostics-show-optionsuppresses that behavior.-fno-diagnostics-show-caretโ by default, each diagnostic includes the original source line and a caret^pointing at the column ๐ฏ. This option suppresses that info. If-fmessage-length=nis given, the source line is truncated toncharacters. When the output goes to the terminal, the width is limited to the width given by theCOLUMNSenvironment variable or, if it's not set, to the terminal width ๐.-fno-diagnostics-show-labelsโ by default, when printing source code (via-fdiagnostics-show-caret), diagnostics can label ranges of source code with pertinent info, like the types of expressions ๐ท๏ธ:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses the printing of these labels (in the example above, that's the vertical bars and the "char *" and "long int" text).
-fno-diagnostics-show-cweโ diagnostic messages can optionally have an associated CWE identifier (https://cwe.mitre.org/index.html) ๐งพ. GCC itself only provides this metadata for some of the-fanalyzerdiagnostics. GCC plugins may also provide diagnostics with this metadata. By default, if this info is present, it gets printed with the diagnostic. This option suppresses the printing of this metadata.-fno-diagnostics-show-line-numbersโ 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โ this one controls the minimum width of the left margin printed by-fdiagnostics-show-line-numbers๐. It defaults to6.-fdiagnostics-parseable-fixitsโ emits fix-it hints in a machine-parseable format, perfect for IDEs ๐ค. 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 written as 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" are 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 (e.g. vertical tab as "\013").
An empty replacement string means the given range gets removed ๐๏ธ. An empty range (e.g. "45:3-45:3") means the string gets inserted at the given position โ๏ธ.
-fdiagnostics-generate-patchโ 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โ in the C++ frontend, when printing diagnostics that show mismatching template types, like this ๐ณ:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
the -fdiagnostics-show-template-tree flag enables printing a tree-like structure showing 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โ by default, when the C++ frontend prints diagnostics showing mismatching template types, the common parts of the types are printed as"[...]"to simplify the error message ๐งน. For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying the -fno-elide-type flag suppresses that behavior ๐
โโ๏ธ. This flag also affects the output of the -fdiagnostics-show-template-tree flag ๐
.
-fdiagnostics-path-format=KINDโ okay so this one decides how the control-flow paths for diagnostics get shown ๐ค๏ธ (only for diagnostics that actually have a path attached, obvi) โจ
KIND can be none, separate-events, or inline-events, and inline-events is the default ๐
none means no diagnostic paths get printed at all, bestie ๐
separate-events gives every event its own "note" diagnostic. It looks like this ๐:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-events prints the events right inside the source code ๐ง. It tries to squish together events that are close enough to each other into runs and shows them as labelled ranges. Same events as above, but served inline:
'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
|
When the path hops between functions (that's interprocedural control flow ๐ง ), the events get grouped by stack frame, and the indentation shows how frames get nested, pushed, and popped. Example:
'test': events 1-2
|
| 133 | {
| | ^
| | |
| | (1) entering 'test'
| 134 | boxed_int *obj = make_boxed_int (i);
| | ~~~~~~~~~~~~~~~~~~
| | |
| | (2) calling 'make_boxed_int'
|
+--> 'make_boxed_int': events 3-4
|
| 120 | {
| | ^
| | |
| | (3) entering 'make_boxed_int'
| 121 | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (4) calling 'wrapped_malloc'
|
+--> 'wrapped_malloc': events 5-6
|
| 7 | {
| | ^
| | |
| | (5) entering 'wrapped_malloc'
| 8 | return malloc (size);
| | ~~~~~~~~~~~~~
| | |
| | (6) calling 'malloc'
|
<-------------+
|
'test': event 7
|
| 138 | free_boxed_int (obj);
| | ^~~~~~~~~~~~~~~~~~~~
| | |
| | (7) calling 'free_boxed_int'
|
(etc)
-fdiagnostics-show-path-depthsโ this one adds extra info to the control-flow paths attached to a diagnostic ๐
If this option is provided, the stack depth gets printed for each run of events inside -fdiagnostics-path-format=separate-events. It's mainly for GCC developers and plugin developers who are debugging diagnostics that report interprocedural control flow, so unless you're in that headspace, it's not really your moment ๐
-fno-show-columnโ no column numbers in diagnostics, bestie ๐ โโ๏ธ
This can be necessary if the diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu. Lowkey a lifesaver for those tools ๐ซถ
-fdiagnostics-column-unit=UNITโ picks the units for the column number ๐. This affects traditional diagnostics (as long as-fno-show-columnisn't in play) and also JSON format diagnostics if you've asked for them.
The default UNIT, display, counts how many display columns each character takes up ๐
. That can be bigger than the number of bytes needed to encode the character (hello, tab characters ๐), or smaller (hello, multibyte characters ๐). For example, "GREEK SMALL LETTER PI (U+03C0)" takes up one display column but needs two bytes in UTF-8, while "SLIGHTLY SMILING FACE (U+1F642)" takes up two display columns and needs four bytes in UTF-8.
Setting UNIT to byte makes the column number the raw byte count in all cases, which is how GCC used to output it before version 11.1.0 ๐ฐ๏ธ
-fdiagnostics-column-origin=ORIGINโ decides which number the first column gets 1๏ธโฃ. The default value of1matches traditional GCC behaviour and the GNU style guide, so it's the vibe ๐ธ. Some utilities might work better with an origin of0, and any non-negative value is allowed ๐ง-fdiagnostics-escape-format=FORMATโ how weird bytes get shown when GCC prints the source lines for a diagnostic ๐ค.
Normally GCC just prints the source bytes straight up. But some diagnostics are about encoding problems in the source file, like malformed UTF-8 or Unicode normalization issues. Those get flagged, so GCC escapes any bytes that aren't printable ASCII when it prints their source lines. This option controls how those bytes get escaped ๐ซ .
The default FORMAT, unicode, shows non-printable-ASCII Unicode characters as <U+XXXX>, and bytes that aren't a valid UTF-8 encoded Unicode character get shown as hexadecimal in the form <XX> ๐. For example, a source line with the string before, then the Unicode character U+03C0 ("GREEK SMALL LETTER PI", UTF-8 encoding 0xCF 0x80), then the stray byte 0xBF (a UTF-8 trailing byte), then the string after, would be printed for such a diagnostic as:
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 would print:
before<CF><80><BF>after
-fdiagnostics-format=FORMATโ picks a different format for printing diagnostics ๐จ.FORMATistextorjson, and the default istext.
The json format is a top-level JSON array full of JSON objects, each one representing a diagnostic ๐. It's emitted as one line with zero formatting, so the examples below have been spruced up for clarity โจ.
Diagnostics can have child diagnostics, too ๐. For example, this warning 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 get 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,
}
]
where the "note" is a child of the "warning" ๐ซถ.
A diagnostic has a "kind" ๐ท๏ธ. If this is "warning", then there is an "option" key describing the command-line option controlling the warning, so you can always trace back which flag is responsible ๐ฅ.
A diagnostic can have zero or more locations ๐ฆ and each one can come with an optional "label" string, plus up to three positions: a "caret" position, and optional "start" and "finish" positions. A position is described by a "file" name, a "line" number, and three numbers for the column, which come in three flavors:
"display-column"โ counts display columns, so tabs and multibyte characters get accounted for ๐"byte-column"โ counts raw bytes ๐ธ"column"โ is equal to one of the previous two, depending on what-fdiagnostics-column-unitsays ๐
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 examples below, the extra column number outputs are left out to keep things short ๐
Okay, so take 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}
It 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 get printed in JSON form like this:
{
"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 has fix-it hints, it gets a "fixits" array made of half-open intervals, kind of like the output of -fdiagnostics-parseable-fixits โจ For example, here's a 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
It might get printed in JSON form like this:
{
"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 ..."
}
So the fix-it hint basically says to swap out the text from "start" up to but not including "next" with the value of "string" ๐ Deletions are shown by an empty value for "string", and insertions are shown by having "start" equal "next".
If the diagnostic has a path of control-flow events attached, it gets a "path" array of event objects. Each event object has a "description" string, a "location" object, a "function" string, and a "depth" number, which is how interprocedural paths get represented ๐ The "function" is the current function at that event, and the "depth" is the stack depth relative to some baseline. The higher the number, the more frames are on the stack.
For example, the intraprocedural example from -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 "escape-source". It's a hint for whether non-ASCII bytes should be escaped when the relevant lines of source code get printed. It's "true" for diagnostics involving source encoding issues ๐ง
โจ Options to Request or Suppress Warnings โจ
Warnings are the "hmm, sus" messages of GCC ๐ They flag constructions that aren't outright wrong on their own, but that are risky or might mean you goofed somewhere.
These next options don't turn on any specific warnings by themselves. Instead, they control what kinds of diagnostics GCC produces, and they're language-independent ๐
-fsyntax-onlyโ Checks the code for syntax errors, but doesn't do anything beyond that ๐ง-fmax-errors=nโ Limits the maximum number of error messages to n. Once that's hit, GCC bails out instead of trying to keep processing the source code ๐ If n is 0 (the default), there's no limit on how many error messages get produced. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option.-wโ Inhibits all warning messages ๐-Werrorโ Makes all warnings into errors ๐-Werror=โ Makes the specified warning into an error. You append the warning's specifier, so for example-Werror=switchturns the warnings controlled by-Wswitchinto errors. This switch also has a negative form, which negates-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐ฅ
The warning message for each controllable warning includes the option that controls it. You can use that option with -Werror= and -Wno-error= as described above. (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 ๐ซถ
-Wfatal-errorsโ Makes the compiler abort compilation on the first error it hits, instead of trying to keep going and printing more error messages ๐
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, like -Wno-implicit. This manual only lists one of the two forms, whichever one isn't the default ๐ธ For further language-specific options, also refer to C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. Additional warnings can be produced by enabling the static analyzer;
Some options, such as -Wall and -Wextra, turn on other options, like -Wunused, which may turn on even more options, like -Wunused-value. The combined effect of positive and negative forms is that more specific options win over less specific ones, no matter where they sit 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 saying the option isn't recognized. However, if the -Wno- form is used, the behavior is a little 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 will warn that an unrecognized option is present ๐ง
The warnings below get way more powerful when optimization is on too, bestie ๐ง For example, -Wsuggest-final-types works better with link-time optimization, and some instances of other warnings won't get issued at all unless optimization is enabled ๐
Optimization in general makes control and data flow sensitive warnings better โจ but in some cases it can also cause false positives ๐
-Wpedantic / -pedantic ๐
Okay, this is the strict ISO C and ISO C++ vibe check ๐
It issues all the warnings that strict ISO C and ISO C++ demand, and it rejects programs that use forbidden extensions, plus some other programs that don't follow ISO C and ISO C++. For ISO C, it follows whichever version of the standard you picked with any -std option.
Valid ISO C and ISO C++ programs should compile properly with or without this option ๐ซถ Though a rare few need -ansi or a -std option that specifies the version of ISO C they require. Without this option, certain GNU extensions and traditional C and C++ features are still supported. With this option, they get rejected ๐
โโ๏ธ
-Wpedantic doesn't cause warning messages for use of the alternate keywords whose names begin and end with __. That 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__". BUT only system header files should use these escape routes ๐จ Application programs should avoid them, no cap.
Some users try to use -Wpedantic to check programs for strict ISO C conformance, and then they're shook ๐ญ It doesn't do quite what they want. It finds some non-ISO practices, but not all. It only catches the ones ISO C requires a diagnostic for, plus some others that have had diagnostics added.
A feature that reports any failure to conform to ISO C might be useful in some instances, but it would take a ton of extra work and would be super different from -Wpedantic ๐ฅฒ We don't have plans to support something like that in the near future.
Where the standard you specify with -std is a GNU extended dialect of C, such as gnu90 or gnu99, there's a corresponding base standard, which is the version of ISO C that the GNU extended dialect is based on. Warnings from -Wpedantic are given wherever the base standard requires them. It wouldn't make sense to only warn about features that aren't in the specified GNU C dialect, because by definition the GNU dialects include every feature the compiler supports with the given option, so there'd be nothing to warn about ๐คทโโ๏ธ
-pedantic-errors ๐
This one is the upgraded version of the pedantic vibe. It gives an error whenever the base standard (see -Wpedantic) requires a diagnostic. It also errors in some cases where there's undefined behavior at compile-time, and in some other cases that don't stop compilation of programs that are valid according to the standard.
This is NOT the same as -Werror=pedantic, since there are errors enabled by this option that the latter doesn't enable, and vice versa. Don't mix them up, bestie ๐
-Wall ๐
This one turns on all the warnings about constructions that some users consider questionable, and that are easy to avoid (or easy to modify to prevent the warning), even in conjunction with macros. It also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options โจ
-Wall turns on the following warning flags:
-Waddress -Warray-bounds=1 (only with -O2) -Warray-compare
-Warray-parameter=2 (C and Objective-C only) -Wbool-compare
-Wbool-operation -Wc++11-compat -Wc++14-compat -Wcatch-value (C++
and Objective-C++ only) -Wchar-subscripts -Wcomment
-Wdangling-pointer=2 -Wduplicate-decl-specifier (C and Objective-C
only) -Wenum-compare (in C/ObjC; this is on by default in C++)
-Wformat -Wformat-overflow -Wformat-truncation -Wint-in-bool-context
-Wimplicit (C and Objective-C only) -Wimplicit-int (C and Objective-
C only) -Wimplicit-function-declaration (C and Objective-C only)
-Winit-self (only for C++) -Wlogical-not-parentheses -Wmain (only
for C/ObjC and unless -ffreestanding) -Wmaybe-uninitialized
-Wmemset-elt-size -Wmemset-transposed-args -Wmisleading-indentation
(only for C/C++) -Wmismatched-dealloc -Wmismatched-new-delete (only
for C/C++) -Wmissing-attributes -Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros -Wnarrowing (only for C++) -Wnonnull
-Wnonnull-compare -Wopenmp-simd -Wparentheses -Wpessimizing-move
(only for C++) -Wpointer-sign -Wrange-loop-construct (only for C++)
-Wreorder -Wrestrict -Wreturn-type -Wsequence-point -Wsign-compare
(only in C++) -Wsizeof-array-div -Wsizeof-pointer-div
-Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-overflow=1
-Wswitch -Wtautological-compare -Wtrigraphs -Wuninitialized
-Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value
-Wunused-variable -Wuse-after-free=3 -Wvla-parameter (C and
Objective-C only) -Wvolatile-register-var -Wzero-length-bounds
Note that some warning flags are NOT implied by -Wall ๐ Some of them warn about constructions that users generally don't consider questionable, but that you might occasionally want to check for. Others warn about constructions that are necessary or hard to avoid in some cases, and there's no simple way to change the code to suppress the warning. Some of them are enabled by -Wextra, but many of them have to be enabled individually ๐ฆ
-Wextra ๐ธ
This one enables some extra warning flags that are NOT enabled by -Wall. (Fun fact: this option used to be called -W. The older name is still supported, but -Wextra is more descriptive, and honestly it's the one I'd use ๐)
-Wclobbered -Wcast-function-type -Wdeprecated-copy (C++ only)
-Wempty-body -Wenum-conversion (C only) -Wignored-qualifiers
-Wimplicit-fallthrough=3 -Wmissing-field-initializers
-Wmissing-parameter-type (C only) -Wold-style-declaration (C only)
-Woverride-init -Wsign-compare (C only) -Wstring-compare
-Wredundant-move (only for C++) -Wtype-limits -Wuninitialized
-Wshift-negative-value (in C++03 and in C99 and newer)
-Wunused-parameter (only with -Wunused or -Wall)
-Wunused-but-set-parameter (only with -Wunused or -Wall)
The option -Wextra also prints warning messages for the following cases:
- A pointer is compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
- (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared
register. - (C++ only) Taking the address of a variable that has been declared
register. - (C++ only) A base class is not initialized in the copy constructor of a derived class.
-Wabi (C, Objective-C, C++ and Objective-C++ only) ๐ฎ
This one warns about code affected by ABI changes. That includes code that may 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 there's a check added later in a release series for an ABI issue that was discovered after the initial release. -Wabi warns about more things if an older ABI version is selected (with -fabi-version=n).
You can also use -Wabi with 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 is used for compatibility aliases. If no explicit version number is provided with this option, but -fabi-compat-version is specified, that version number is used for C++ ABI warnings.
Although an effort has been made to warn about all such cases, there are probably some cases that aren't warned about, even though G++ is generating incompatible code ๐ฌ There may also be cases where warnings are emitted even though the generated code is compatible.
If you're concerned that code generated by G++ may not be binary compatible with code generated by 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 was folded away.
These mangling issues were fixed in -fabi-version=5.
- Scoped enumerators passed as arguments to a variadic function are promoted like unscoped enumerators, causing
va_argto complain. On most targets this doesn't actually affect the parameter passing ABI, since there's no way to pass an argument smaller thanint.
Also, the ABI changed the mangling of template argument packs, const_cast, static_cast, prefix increment/decrement, and a class scope function used as a template argument.
These issues were corrected in -fabi-version=6.
- Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t.
These issues were corrected in -fabi-version=7.
- When mangling a function type with function-cv-qualifiers, the un-qualified function type was incorrectly treated as a substitution candidate.
This was fixed in -fabi-version=8, the default for GCC 5.1.
decltype(nullptr)incorrectly had an alignment of 1, leading to unaligned accesses. Note that this did not affect the ABI of a function with anullptr_tparameter, as parameters have a minimum alignment.
This was fixed in -fabi-version=9, the default for GCC 5.2.
- Okay so target-specific attributes that change the identity of a type, like ia32 calling conventions on a function type (
stdcall,regparm, etc.), were not affecting the mangled name ๐. That caused name collisions whenever function pointers got used as template arguments ๐ญ
This got fixed in -fabi-version=10, which is the default as of GCC 6.1 โจ
This option also turns on warnings about psABI-related changes ๐ The known psABI changes at this point include:
- For SysV/x86-64, unions with "long double" members get passed in memory the way the psABI specifies ๐ง Before GCC 4.4 that wasn't happening. For example:
union U {
long double ld;
int i;
};
union U is now always passed in memory ๐
-Wchar-subscriptsโ Heads up ๐ this warns when an array subscript has typechar. It's a super common mistake because people forget thatcharis signed on some machines. Enabled by-Wall๐-Wno-coverage-mismatchโ Warns if feedback profiles don't match when you're using-fprofile-use. If a source file changes between compiling with-fprofile-generateand-fprofile-use, the profile feedback files can fail to match the source, and GCC can't use the feedback info ๐ฉ This warning is on by default and is treated as an error. You can turn the warning off with-Wno-coverage-mismatch, or turn off just the error with-Wno-error=coverage-mismatch. Skipping the error can lead to poorly optimized code, so it's only worth it for very minor changes like bug fixes to an existing code-base ๐ธ Totally disabling the warning is not recommended, bestie ๐ โโ๏ธ-Wno-coverage-invalid-line-numberโ Warns in case a function ends earlier than it begins because of invalidlinenummacros ๐ฆ This warning only shows up with--coverageenabled.
By default this warning is on and is treated as an error. Use -Wno-coverage-invalid-line-number to disable the warning, or -Wno-error=coverage-invalid-line-number to disable just the error โจ
-Wno-cpp(C, Objective-C, C++, Objective-C++ and Fortran only) โ Silences the warning messages that come from#warningdirectives ๐คซ-Wdouble-promotion(C, C++, Objective-C and Objective-C++ only) โ Gives a warning when afloatvalue gets implicitly promoted todouble๐ Some CPUs have a 32-bit single-precision floating-point unit that doesfloatin hardware but fakesdoublein software. On those machines, doing math withdoubleis way more expensive because of all that software emulation overhead ๐ค
It's really easy to do double math by accident, because floating-point literals are implicitly double. For example:
float area(float radius)
{
return 3.14159 * radius * radius;
}
The compiler does the whole calculation in double here, because that floating-point literal is a double ๐
-Wduplicate-decl-specifier(C and Objective-C only) โ Warns if a declaration has a duplicateconst,volatile,restrictor_Atomicspecifier ๐งน Enabled by-Wall.-Wformat,-Wformat=nโ Checks calls toprintfandscanf, etc., to make sure the arguments you pass have types that match the format string, and that the conversions in the format string actually make sense ๐ This covers the standard functions plus anything else tagged with format attributes, in theprintf,scanf,strftimeandstrfmonfamilies (strfmonis an X/Open extension, not part of the C standard), or other target-specific families. Which functions get checked without format attributes depends on the standard version you pick. Those checks are turned off by-ffreestandingor-fno-builtin๐
The formats get checked against the format features supported by GNU libc version 2.2. That includes all ISO C90 and C99 features, plus features from the Single Unix Specification and some BSD and GNU extensions. Other library implementations might not support all of these, and GCC 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 selected standard version (not for strfmon formats, though, 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 also implies-Wnonnullโจ Some parts of this level of checking can be switched off with-Wno-format-contains-nul,-Wno-format-extra-args, and-Wno-format-zero-length.-Wformatis enabled by-Wall.-Wformat=2โ Enables-Wformatplus additional format checks ๐ฅ Right now it's equivalent to-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k.
-Wno-format-contains-nulโ If-Wformatis specified, don't warn about format strings that contain NUL bytes ๐ซถ-Wno-format-extra-argsโ If-Wformatis specified, don't warn about extra arguments passed to aprintforscanfformat function. The C standard says those arguments get ignored, so no biggie ๐
If the unused arguments sit between used arguments that have $ operand number specifications, warnings still show up, because the implementation couldn't know what type to hand to va_arg to skip the unused ones ๐ค With scanf formats, though, this option suppresses that warning when all the unused arguments are pointers, since the Single Unix Specification says those unused arguments are allowed ๐ฆ
-Wformat-overflow,-Wformat-overflow=levelโ Warns about calls to formatted input/output functions likesprintfandvsprintfthat might overflow the destination buffer ๐ฑ When the exact number of bytes written by a format directive can't be figured out at compile time, GCC estimates it using heuristics that depend on thelevelargument and on optimization. Turning on optimization usually makes the warning more accurate, but it can also cause false positives ๐-Wformat-overflow,-Wformat-overflow=1โ Level 1, which-Wformatturns on, is the cautious option. It only warns about calls that most likely overflow the buffer ๐งธ At this level, numeric arguments to format directives with unknown values are assumed to be one, and strings of unknown length are assumed to be empty. Numeric arguments known to be bounded to a subrange of their type, or string arguments whose output is bounded by their directive's precision or by a finite set of string literals, are assumed to take whatever value in that range produces the most bytes of output ๐ง
For example, this sprintf call gets diagnosed, because even when both a and b are 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 avoid the overflow itself.
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 when an argument has a big enough length or magnitude ๐ At level 2, unknown numeric arguments are assumed to be 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 to be bounded (by the directive's precision, by a finite set of string literals they might evaluate to, or by the character array they might point to) are assumed to be 1 character long.
At level 2, the call in the example above gets diagnosed again, but this time it's because with a 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 includes the minimum buffer size in an informational note right after the warning ๐
Instead of making the buffer bigger, you can also limit the range of the formatted values ๐ธ The maximum length of string arguments can be capped by putting a precision in the format directive. When numeric arguments can be assumed to be bounded by less than the precision of their type, picking an appropriate length modifier for the format specifier will shrink the buffer size you need. For example, if a and b in the example above can be assumed to fit in the short int type, then using either the %hi format directive or casting the argument to short brings the maximum required buffer size down to 24 bytes โจ
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
-Wno-format-zero-lengthโ If-Wformatis specified, don't warn about zero-length formats. The C standard allows zero-length formats, so it's all good ๐ซง-Wformat-nonliteralโ If-Wformatis specified, also warn if the format string isn't a string literal and therefore can't be checked ๐ The exception is when the format function takes its format arguments as ava_list.-Wformat-securityโ ๐ okay so if-Wformatis on, this one tags along and also flags format function uses that could be security problems ๐จ. Right now it's catchingprintfandscanfcalls where the format string isn't a string literal and there are no format arguments, likeprintf (foo);. That can be a real hole if the format string came from untrusted input and contains%n๐. (It's currently a subset of what-Wformat-nonliteralwarns about, but future-Wformat-securitywarnings might cover things-Wformat-nonliteraldoesn't โจ.)-Wformat-signednessโ ๐ if-Wformatis specified, this one also warns when the format string wants an unsigned argument and you hand it a signed one, and vice versa ๐ซถ.-Wformat-truncation,-Wformat-truncation=levelโ โ๏ธ bestie, this one keeps an eye on formatted I/O calls likesnprintfandvsnprintfthat might cut your output short (aka truncation) ๐ญ. When GCC can't figure out the exact number of bytes a format directive writes at compile time, it estimates 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 ๐. Except where noted, it uses the same logic as-Wformat-overflow.-Wformat-truncation,-Wformat-truncation=1โ level 1 (enabled by-Wformat) is the cautious queen ๐. It only warns about bounded functions whose return value is unused and that will most likely truncate output.-Wformat-truncation=2โ level 2 goes harder ๐ฅ. It also warns about bounded functions whose return value is used and that might truncate given an argument of sufficient length or magnitude.
-Wformat-y2kโ ๐ if-Wformatis specified, this also warns aboutstrftimeformats that may only give you a two-digit year. Y2K energy, and we are NOT doing that again ๐.-Wnonnullโ ๐ซ warns about passing a null pointer to arguments marked as needing a non-null value by thenonnullfunction attribute. It's included in-Walland-Wformat, and you can switch 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 GCC detects paths that trigger erroneous or undefined behavior from dereferencing a null pointer. This option is only active when-fdelete-null-pointer-checksis active, which optimizations enable on most targets ๐ธ. How precise the warnings are depends on the optimization options you use.-Winfinite-recursionโ ๐ warns about infinitely recursive calls. It works at all optimization levels, but you need optimization to catch infinite recursion between two or more functions. It's included in-Wallโจ.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ ๐ช warns about uninitialized variables that are initialized with themselves. Heads up: this option can only be used with the-Wuninitializedoption.
For example, GCC warns about i being uninitialized in the following snippet only when -Winit-self has been specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++.
-Wno-implicit-int(C and Objective-C only) โ ๐ controls warnings when a declaration doesn't specify a type. This warning is enabled by default in C99 and later dialects of C, and also by-Wall.-Wno-implicit-function-declaration(C and Objective-C only) โ controls warnings when a function is used before it's declared ๐ง. This warning is enabled by default in C99 and later dialects of C, and also by-Wall. Fair warning:-pedantic-errorsturns it into an error โ.-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declaration๐. Enabled by-Wall.-Wimplicit-fallthroughโ 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. Picture this, bestie ๐:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
This warning does not fire when the last statement of a case can't fall through, e.g. 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 appropriate. E.g.
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a switch case fall through is desirable, so GCC gives you an attribute, __attribute__ ((fallthrough)), to be used along with a null statement to suppress the warning that would normally show up ๐ฆ:
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 has a standard way to suppress the -Wimplicit-fallthrough warning using [[fallthrough]]; instead of the GNU attribute ๐. In C++11 or C++14, you can use [[gnu::fallthrough]];, which is a GNU extension. Instead of these attributes, you can also add a fallthrough comment to silence the warning. The whole body of the C or C++ style comment should 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:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4case sensitively matches one of the following regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5doesn't recognize any comments as fallthrough comments. Only attributes disable the warning ๐ โโ๏ธ.
The comment needs to be followed, after optional whitespace and other comments, by a case or default keyword, or by a user label that precedes some case or default label ๐
:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is enabled by -Wextra ๐.
-Wno-if-not-aligned(C, C++, Objective-C and Objective-C++ only) โ controls whether warnings triggered by thewarn_if_not_alignedattribute should be issued ๐. These warnings are enabled by default.-Wignored-qualifiers(C and C++ only) โ warns if the return type of a function has a type qualifier such asconst. For ISO C, a type qualifier like that has no effect, since the value returned by a function isn't an lvalue ๐ซ . For C++, the warning is only emitted for scalar types orvoid. ISO C prohibits qualifiedvoidreturn types on function definitions, so those always get a warning, even without this option. This warning is also enabled by-Wextra.-Wno-ignored-attributes(C and C++ only) โ controls warnings when an attribute is ignored. This is different from the-Wattributesoption: it warns whenever the compiler decides to drop an attribute, not when the attribute is unknown, used in the wrong place, etc. ๐๏ธ This warning is enabled by default.-Wmainโ โญ warns if the type ofmainis suspicious.mainshould be a function with external linkage, returningint, taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++, and by either-Wallor-Wpedantic.-Wmisleading-indentation(C and C++ only) โ ๐ warns when the indentation of the code doesn't reflect the block structure. Specifically, a warning is issued forif,else,while, andforclauses with a guarded statement that doesn't use braces, followed by an unguarded statement with the same indentation. Main character energy: the indentation is lying.
In the following example, the call to bar is misleadingly indented as if it were guarded by the if conditional:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
In the case of mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up (defaulting to 8) ๐.
The warning is not issued for code involving multiline preprocessor logic, such as the following example ๐ง:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
This one goes quiet after a #line directive, since that usually means autogenerated code, and nobody can assume anything about the layout of the file the directive points to. โจ This warning is enabled by -Wall in C and C++. ๐ธ
-Wmissing-attributesโ Ooh, this one's a vibe check on function declarations ๐ It warns when a declaration is missing one or more attributes that a related function was declared with, and when that absence could hurt the correctness or efficiency of the generated code. For example, it flags aliases that use attributes to set less strict requirements than their targets, which is typically a potential optimization opportunity ๐ The opposite situation is handled by-Wattribute-alias=2, which warns when the alias is more restrictive than the target, since that could lead to incorrect code generation ๐ญ Attributes considered 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 declared with "alloc_align", "alloc_size", "assume_aligned", "format", "format_arg", "malloc", or "nonnull" is declared without it. 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 typing them all out again ๐ซถ It works on declarations of functions, variables, or types.
-Wmissing-attributes is enabled by -Wall. ๐
Here's the tea. Since the declaration of the primary function template below uses both "malloc" and "alloc_size", the explicit specialization gets diagnosed 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 the example below, the initializer foraisn't fully bracketed, but the one forbis ๐ง
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall. โจ
-Wmissing-include-dirs(C, C++, Objective-C, Objective-C++ and Fortran only) โ Warns if a user-supplied include directory doesn't exist ๐ This option is disabled by default for C, C++, Objective-C, and Objective-C++. For Fortran, it's partially enabled by default, and only warns for-Iand-J๐ฆ-Wno-missing-profileโ This one controls warnings about missing feedback profiles when you use-fprofile-use๐ It's the diagnosis for when a new function or a new file gets added between-fprofile-generateand-fprofile-usewithout regenerating the profiles. The profile feedback data files then have no profile info for that new function or file. Also, if profile count data (.gcda) files get removed, GCC can't use any profile feedback information at all ๐ญ In all of these cases, you'll get warnings reminding you that a profile generation step is due. Ignoring them can result in poorly optimized code. You can use-Wno-missing-profileto turn the warning off, but that's not recommended and should only be done when non-existent profile data is justified ๐ โโ๏ธ-Wmismatched-deallocโ Warns about calls to deallocation functions that get pointer arguments returned from allocation functions the former isn't a suitable deallocator for ๐๏ธ A pair of functions can be linked as matching allocators and deallocators using the attribute"malloc". Unless the-fno-builtinoption disables it, the standard functions"calloc","malloc","realloc", and"free", plus the matching forms of C++"operator new"and"operator delete", are implicitly treated as matching allocators and deallocators ๐ค In the example below,"mydealloc"is the deallocator for pointers returned from"myalloc".
void mydealloc (void*);
__attribute__ ((malloc (mydealloc, 1))) void*
myalloc (size_t);
void f (void)
{
void *p = myalloc (32);
// ...use p...
free (p); // warning: not a matching deallocator for myalloc
mydealloc (p); // ok
}
In C++, the related option -Wmismatched-new-delete diagnoses mismatches involving either "operator new" or "operator delete" ๐
Option -Wmismatched-dealloc is included in -Wall. ๐
-Wmultistatement-macrosโ Warns about unsafe multiple-statement macros that look guarded by a clause like"if","else","for","switch", or"while", but where only the first statement is actually guarded after the macro is expanded ๐จ
#define DOIT x++; y++
if (c)
DOIT;
The code above will increment y unconditionally, not just when c holds. ๐ฑ This can usually be fixed by wrapping the macro in a do-while loop:
#define DOIT do { x++; y++; } while (0)
if (c)
DOIT;
This warning is enabled by -Wall in C and C++. ๐
-Wparenthesesโ Warns if parentheses are omitted in certain contexts, like when there's an assignment where a truth value is expected, or when operators are nested in ways people often get confused about ๐ค
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 interpretation from ordinary mathematical notation ๐
It also warns about dangerous uses of the GNU extension to ?: with an omitted middle operand. When the condition in the ?: operator is a boolean expression, the omitted value is always 1. Programmers often expect it to be a value computed inside the conditional expression instead ๐ญ
For C++, this also warns about some cases of unnecessary parentheses in declarations, which can signal an attempt at a function call instead of a declaration:
{
// Declares a local variable called mymutex.
std::unique_lock<std::mutex> (mymutex);
// User meant std::unique_lock<std::mutex> lock (mymutex);
}
This warning is enabled by -Wall. โจ
-Wsequence-pointโ Okay, bestie, this one is a whole saga ๐ฌ It warns about code that may have undefined semantics because of violations of the sequence point rules in the C and C++ standards.
The standards define the order in which expressions get evaluated in terms of sequence points, which are a partial ordering between parts of the program: the stuff executed before a sequence point, and the stuff executed after it. These show up after the evaluation of a full expression (one that isn't part of a larger expression), after the evaluation of the first operand of a "&&", "||", "? :", or "," (comma) operator, before a function is called (but after its arguments and the expression denoting the called function are evaluated), and in certain other places. Apart from what the sequence point rules say, the order of evaluation of subexpressions isn't specified. These rules only give a partial order, not a total one. For example, if two functions get called within one expression with no sequence point between them, the order of those calls isn't specified. However, the standards committee has ruled that function calls do not overlap ๐ซ
It's not specified when, between sequence points, modifications to object values take effect. Programs whose behavior depends on this have undefined behavior. The C and C++ standards say: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored." If a program breaks these rules, the results on any particular implementation are entirely unpredictable ๐
Examples of code with undefined behavior 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 in general, it's been found fairly effective at detecting this sort of problem ๐
The C++17 standard will define the order of evaluation of operands in more cases. In particular, it requires that the right-hand side of an assignment 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โ Don't warn about returning a pointer (or, in C++, a reference) to a variable that goes out of scope after the function returns ๐ โโ๏ธ-Wreturn-typeโ Warns whenever a function is defined with a return type that defaults toint๐ธ It also warns about anyreturnstatement with no return value in a function whose return type isn'tvoid. (Falling off the end of the function body counts as returning without a value, so yes, that gets flagged too ๐ซถ)
For C only, warn about a return statement with an expression in a function whose return type is void ๐ซถ, unless the expression type is also void. As a GNU extension, that second case gets a pass with no warning unless -Wpedantic is used ๐ง. Trying to use the return value of a non-void function other than main that just flows off the end (aka reaching the closing curly brace that ends the function) is undefined ๐.
๐ Heads up, bestie: in C++, flowing off the end of a non-voidfunction other thanmainresults in undefined behavior even when the value of the function is not used. Unlike C, C++ is not chill about this one ๐ญ
This warning is enabled by default in C++ and by -Wall otherwise โจ.
-Wno-shift-count-negativeโ okay so this one controls warnings if a shift count is negative ๐ธ. It's enabled by default, so you get it for free ๐ .-Wno-shift-count-overflowโ controls warnings if a shift count is greater than or equal to the bit width of the type ๐ฆ. Also enabled by default โจ.-Wshift-negative-valueโ warns if you left shift a negative value ๐. This warning is enabled by-Wextrain C99 and C++11 modes (and newer) ๐.-Wno-shift-overflow,-Wshift-overflow=nโ these options control warnings about left shift overflows ๐ฅ.-Wshift-overflow=1โ this is the warning level of-Wshift-overflowand it's enabled by default in C99 and C++11 modes (and newer) ๐. This level 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 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 ๐. The presence of adefaultlabel prevents this warning.caselabels outside the enumeration range also provoke 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โ same energy as-Wswitch: warns on aswitchwith an enum index that's missing acasefor one or more named codes, andcaselabels outside the enum range also get warnings ๐ . The only difference is that this one warns about an omitted enumeration code even if there's adefaultlabel ๐ญ.-Wno-switch-boolโ don't warn when aswitchstatement has a boolean index 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 of its respective type range ๐ฆ. 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, so watch out ๐ซถ.-Wunused-but-set-parameterโ warns whenever a function parameter gets assigned to but is otherwise unused (aside from its declaration) ๐ท. To suppress this warning, use theunusedattribute. This is also enabled by-Wunusedtogether with-Wextraโจ.-Wunused-but-set-variableโ warns whenever a local variable gets assigned to but is otherwise unused (aside from its declaration) ๐. Enabled by-Wall. To suppress it, use theunusedattribute. This is also enabled by-Wunused, which is enabled by-Wall๐ฅ.-Wunused-functionโ warns whenever astaticfunction is declared but not defined, or a non-inlinestaticfunction is unused ๐ง. Enabled by-Wall.-Wunused-labelโ warns whenever a label is declared but not used ๐ท๏ธ. Enabled by-Wall. To suppress this warning, use theunusedattribute.-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ warns when a typedef locally defined in a function is not used ๐. Enabled by-Wall.-Wunused-parameterโ warns whenever a function parameter is unused aside from its declaration ๐. 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โ warns whenever a local orstaticvariable is unused aside from its declaration ๐ . This option implies-Wunused-const-variable=1for C, but not for C++. Enabled by-Wall. To suppress it, use theunusedattribute.-Wunused-const-variable,-Wunused-const-variable=nโ warns whenever a constantstaticvariable is unused aside from its declaration ๐ฆ.-Wunused-const-variable=1is enabled by-Wunused-variablefor C, but not for C++. In C this declares variable storage, but in C++ it's not an error, sinceconstvariables take the place of#defines ๐ค. To suppress this warning, use theunusedattribute.-Wunused-const-variable=1โ this is the warning level that's enabled by-Wunused-variablefor C ๐. It only warns about unusedstatic constvariables defined in the main compilation unit, but not aboutstatic constvariables declared in any header that's included.-Wunused-const-variable=2โ this level also warns for unused constantstaticvariables in headers (excluding system headers) ๐. This is the warning level of-Wunused-const-variableand it must be explicitly requested, since in C++ it isn't an error and in C it might be harder to clean up all the headers included.
-Wunused-valueโ warns whenever a statement computes a result that is explicitly not used ๐. To suppress this warning, cast the unused expression tovoid. This includes 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. Enabled by-Wall.-Wunusedโ all the above-Wunusedoptions combined ๐ง . To get a warning about an unused function parameter, you must either specify-Wextra -Wunused(note that-Wallimplies-Wunused), or separately specify-Wunused-parameter๐.-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-staticconstmember appears in a class without constructors.
In addition, passing a pointer (or in C++, a reference) to an uninitialized object to a const-qualified argument of a built-in function known to read 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 warnings depend on the precise optimization options and version of GCC used ๐ข.
Note that there may be no warning about a variable that is used only 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โ controls warnings for invocations of__atomicbuilt-ins,__syncbuilt-ins, 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 thememory_orderenumeration ๐งช. For example, since the__atomic_storeand__atomic_store_nbuilt-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 where it is initialized, but some other paths where it is not initialized, the compiler emits a warning if it can't prove those 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 also gets flagged by this warning ๐ซถ (-Wuninitialized is issued for built-in functions known to read the object). bestie, if you annotate the function with attribute access (none), you're telling GCC the argument isn't used to access the object, and the warning goes away โจ
these warnings only show up in optimizing compilation, because otherwise GCC doesn't keep track of what's going on with variables ๐
these warnings are optional because GCC can't always tell when the code is actually correct, even when it looks like there's an error ๐ here's one example of how that happens:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
if the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know that ๐ญ to shut the warning up, you need a default case with assert(0) or similar code ๐ธ
this option also warns when a non-volatile automatic variable might get changed by a call to longjmp ๐ฆ the compiler only sees the calls to setjmp, and it can't know where longjmp will be called (a signal handler could call it at any point in the code, honestly!). so you might get a warning even when there's no real problem, because longjmp can't actually be called at the spot that would cause trouble ๐
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#pragmadirective shows up that GCC doesn't understand. if you use this command-line option, you'll even get warnings for unknown pragmas in system header files. that's not the case if the warnings are only turned on by the-Wallcommand-line option ๐-Wno-pragmasโ ๐ don't warn about misuses of pragmas, like incorrect parameters, invalid syntax, or conflicts between pragmas. see also-Wunknown-pragmas๐-Wno-prio-ctor-dtorโ ๐ skip the warning if a priority from 0 to 100 is used for a constructor or destructor. constructor and destructor attributes let you give a priority to control the order they run in, beforemainis called or after it returns โจ but the priority values have to be greater than 100, because the compiler reserves 0--100 for itself ๐-Wstrict-aliasingโ ๐ฆ only active when-fstrict-aliasingis active. it warns about code that might break the strict aliasing rules the compiler uses for optimization. it doesn't catch every case, but it does try to catch the more common pitfalls. it's included in-Wall, and it's equivalent to-Wstrict-aliasing=3๐-Wstrict-aliasing=nโ ๐ same vibe, only active when-fstrict-aliasingis active. it warns about code that might break those strict aliasing rules. higher levels mean higher accuracy (fewer false positives), and they also take more effort, kinda like how-Oworks ๐ง-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3โจ- Level 1: most aggressive, quick, least accurate ๐ฅ possibly useful when higher levels don't warn but
-fstrict-aliasingstill breaks the code, since it has very few false negatives. however, it has many false positives ๐ญ it warns for all pointer conversions between possibly incompatible types, even if never dereferenced. runs in the front end only. - Level 2: aggressive, quick, not too precise ๐ may still have many false positives (not as many as level 1, though), and few false negatives (but possibly more than level 1). unlike level 1, it only warns when an address is taken. warns about incomplete types. runs in the front end only.
- Level 3 (default for
-Wstrict-aliasing): should have very few false positives and few false negatives ๐ซถ slightly slower than levels 1 or 2 when optimization is enabled. it takes care of the common pun+dereference pattern in the front end:*(int*)&some_float. if optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. only warns when the converted pointer is dereferenced. does not warn about incomplete types.
- Level 1: most aggressive, quick, least accurate ๐ฅ possibly useful when higher levels don't warn but
-Wstrict-overflow,-Wstrict-overflow=nโ this option is only active when signed overflow is undefined ๐ธ it warns about cases where the compiler optimizes based on the assumption that signed overflow doesn't happen. it doesn't warn about every place the code might overflow, only where the compiler actually implements some optimization, so this warning depends on the 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 are issued for undefined signed overflow when estimating how many iterations a loop requires, in particular when figuring out whether a loop will be executed at all ๐-Wstrict-overflow=1โ warns about cases that are both questionable and easy to avoid ๐ for example, the compiler simplifiesx + 1 > xto1. this level of-Wstrict-overflowis enabled by-Wall; higher levels aren't, and must be explicitly requested.-Wstrict-overflow=2โ also warns about other cases where a comparison is simplified to a constant ๐ฆ for example:abs (x) >= 0. this can only be simplified when signed integer overflow is undefined, becauseabs (INT_MIN)overflows toINT_MIN, which is less than zero.-Wstrict-overflow(with no level) is the same as-Wstrict-overflow=2๐-Wstrict-overflow=3โ also warns about other cases where a comparison is simplified ๐ for example:x + 1 > 1is simplified tox > 0.-Wstrict-overflow=4โ also warns about other simplifications not covered by the above cases โจ for example:(x * 10) / 5is simplified tox * 2.-Wstrict-overflow=5โ also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison ๐ญ for example:x + 2 > yis simplified tox + 1 >= y. this is reported only at the highest warning level, because this simplification applies to many comparisons, so this level gives a very large number of false positives ๐
-Wstring-compareโ ๐ฅ warns for calls tostrcmpandstrncmpwhose result is determined to be zero or non-zero in equality tests, because the length of one argument is greater than the size of the array the other argument is stored in (or the bound, forstrncmp). those calls could be mistakes ๐ for example, thestrcmpcall below gets diagnosed because its result is necessarily non-zero no matter what's in the arraya:
extern char a[4];
void f (char *d)
{
strcpy (d, "string");
...
if (0 == strcmp (a, d)) // cannot be true
puts ("a and d are the same");
}
-Wstring-compare is enabled by -Wextra ๐
-Wno-stringop-overflow,-Wstringop-overflow,-Wstringop-overflow=typeโ ๐ง warns 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 to perform to determine the size of the destination. the argument only matters for functions that operate on character arrays, not raw memory functions likememcpy, which always use Object Size type-0. the option also warns for calls that specify a size in excess of the largest possible object, or at mostSIZE_MAX / 2bytes. it gives the best results with optimization enabled, but can detect a small subset of simple buffer overflows even without optimization, in calls to GCC built-in functions like__builtin_memcpythat correspond to the standard functions. either way, it only warns about a subset of the buffer overflows detected by the corresponding overflow checking built-ins. for example, the option issues a warning for thestrcpycall below because it copies at least 5 characters (the string"blue"including the terminating NUL) into a buffer of size 4:
enum Color { blue, purple, yellow };
const char* f (enum Color clr)
{
static char buf [4];
const char *str;
switch (clr)
{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
}
return strcpy (buf, str); // warning here
}
Option -Wstringop-overflow=2 is enabled by default ๐ฅ
-Wstringop-overflow,-Wstringop-overflow=1โ the-Wstringop-overflow=1option uses type-zero Object Size Checking to determine the sizes of destination objects ๐ธ at this setting, the option doesn't warn for writes past the end of subobjects of larger objects accessed by pointers, unless the size of the largest surrounding object is known. when the destination may 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๐ง okay so this one uses type-one Object Size Checking to figure out how big destination objects are. 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 unknown numbers of elements. This is the default setting of the option ๐-Wstringop-overflow=3๐ this one switches to type-two Object Size Checking for destination sizes. At this setting it warns about overflowing the smallest object or data member. It's the most restrictive setting that can still flag totally safe code, so be ready for some false alarms ๐ญ-Wstringop-overflow=4๐ฆ type-three Object Size Checking is in charge here. It warns about overflowing any data members. When the destination is one of several objects, it uses the size of the largest one to decide whether to warn. Like-Wstringop-overflow=3, this setting may warn on benign code ๐-Wno-stringop-overread๐ธ warns for calls to string manipulation functions likememchrorstrcpythat are determined to read past the end of the source sequence.
Option -Wstringop-overread is enabled by default โจ
-Wno-stringop-truncation๐ this one tells GCC to not warn for calls to bounded string functions likestrncat,strncpy, andstpncpythat might truncate the copied string or leave the destination unchanged.
Here's a sneaky example. In the following code, the call to strncat sets a bound that's smaller than the length of the source string. So the copy gets truncated, and the call is diagnosed. To avoid the warning, use bufsize - strlen (buf) - 1) as the bound.
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Another one: this strncpy call copies only the characters before the terminating NUL into d, and doesn't add the NUL to the end. Assuming the result of strncpy is always a NUL-terminated string is a super common mistake, so this call gets diagnosed ๐ To dodge the warning when the result isn't supposed to be NUL-terminated, call memcpy instead.
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
Last one! Here the strncpy call uses the size of the destination buffer as the bound. If the source string's length is equal to or greater than that size, the copy won't be NUL-terminated, so yep, it gets diagnosed too. To avoid the warning, specify sizeof buf - 1 as the bound and set the last element of the buffer to NUL.
void copy (const char *s)
{
char buf[80];
strncpy (buf, s, sizeof buf);
...
}
If you've got a character array that's meant to hold a sequence of bytes with no terminating NUL, you can annotate it with the attribute nonstring to skip this warning ๐ง Just know that arrays like that aren't suitable for functions that expect NUL-terminated strings. To help catch accidental misuse, GCC still issues warnings unless it can prove the use is safe ๐ฅ
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]๐ฎ warns for cases where adding an attribute might be beneficial. The attributes currently supported are listed below.-Wsuggest-attribute=pure,-Wsuggest-attribute=const,-Wsuggest-attribute=noreturn,-Wmissing-noreturn,-Wsuggest-attribute=mallocโจ these warn about functions that might be candidates for the attributespure,const,noreturn, ormalloc. The compiler only warns for functions visible in other compilation units, or (forpureandconst) 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, callingabort, or trapping. This analysis requires option-fipa-pure-const, which is enabled by default at-Oand higher. Higher optimization levels improve the accuracy of the analysis ๐
-Wsuggest-attribute=format,-Wmissing-format-attribute๐จ๏ธ warns about function pointers that might be candidates forformatattributes. Heads up, these are only possible candidates, not absolute ones.
GCC guesses that function pointers with format attributes that get used in assignment, initialization, parameter passing, or return statements should have a matching format attribute 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 a format attribute to avoid the warning.
GCC also warns about function definitions that might be candidates for format attributes. Again, these are just possible candidates. GCC guesses format attributes might be appropriate for any function that calls a function like vprintf or vscanf, but that might not always be the case, and some functions that really should have format attributes may not get detected ๐คทโโ๏ธ
-Wsuggest-attribute=cold๐ง warns about functions that might be candidates for thecoldattribute. This is based on static detection, and it generally only warns about functions that always lead to a call to anothercoldfunction, like wrappers of C++throwor fatal error reporting functions that lead toabort.-Walloc-zero0๏ธโฃ warns about calls to allocation functions decorated with the attributealloc_sizethat specify zero bytes. That includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc.
๐จ Because the behavior of these functions with a zero size differs between implementations (and realloc has been deprecated for this), relying on it can cause subtle portability bugs. Avoid it!
-Walloc-size-larger-than=byte-size๐ warns about calls to functions decorated with the attributealloc_sizethat try to allocate objects larger than the specified number of bytes. It also warns when the result of the size computation, done in an integer type with infinite precision, would exceed the value ofPTRDIFF_MAXon the target.-Walloc-size-larger-than=PTRDIFF_MAXis enabled by default. Warnings controlled by this option can be disabled either by specifying a byte-size ofSIZE_MAXor more, or by-Wno-alloc-size-larger-than.-Wno-alloc-size-larger-than๐ โโ๏ธ disables-Walloc-size-larger-than=warnings. It's equivalent to-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 toallocawith an integer argument whose value is either zero, or that isn't bounded by a controlling predicate limiting its value to at most byte-size. It also warns for calls toallocawhere the bound value is unknown. Arguments of non-integer types are considered unbounded, even if they look like they're constrained to the expected range.
Here's a bounded case of alloca that's totally fine:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
In the above example, passing -Walloca-larger-than=1000 would not issue a warning, 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, but this time because of the lack of bounds checking ๐
Note that even seemingly correct code involving signed integers could cause a warning:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
In the above example, n could be negative, causing a larger than expected argument to be implicitly cast into the alloca call. Plot twist! ๐ช๏ธ
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-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 still get issued even without optimization ๐-Warray-bounds=1โ ๐ This is the default level of-Warray-bounds, and-Wallswitches it on for you. The higher levels aren't on by default, so you have to ask for them by name, bestie ๐-Warray-bounds=2โ ๐ฅ This level goes further. It also flags out-of-bounds accesses to trailing struct members of one-element array types, and the intermediate results of pointer arithmetic that might come out of bounds. ngl it can throw a lot of false positives, so it's deactivated by default ๐-Warray-compareโ ๐ฆ Warns about equality and relational comparisons between two operands of array type. This comparison was deprecated in C++20, so it's not it ๐ For example:
int arr1[5];
int arr2[5];
bool same = arr1 == arr2;
-Warray-compare is enabled by -Wall.
-Warray-parameter,-Warray-parameter=nโ ๐ธ Warns about redeclarations of functions with array or pointer arguments that don't match in kind or form. It also turns on detection of out-of-bounds accesses to those parameters by warnings like-Warray-bounds.
If the first function declaration uses the array form, the bound in the array is treated as the minimum number of elements callers must provide, and also the maximum number of elements the function accesses. Passing arguments that are too small, or accessing more than that maximum, may get flagged by warnings like -Warray-bounds. At level 1, the warning catches inconsistencies involving array parameters declared with the "T[static N]" form.
Here, the warning triggers on the redeclarations because the first one lets an array of any size be passed to f, while the second one, with the keyword static, says the array argument must have at least four elements:
void f (int[static 4]);
void f (int[]); // warning (inconsistent array form)
void g (void)
{
int *p = (int *)malloc (4);
f (p); // warning (array too small)
...
}
At level 2, the warning also triggers on redeclarations with any other inconsistency in array or pointer argument forms that denote array sizes. Pointers and arrays of unspecified bound are treated as equivalent, so they don't trigger a warning:
void g (int*);
void g (int[]); // no warning
void g (int[8]); // warning (inconsistent array bound)
-Warray-parameter=2 is included in -Wall. The -Wvla-parameter option triggers warnings for similar inconsistencies involving Variable Length Array arguments โจ
-Wattribute-alias=n,-Wno-attribute-aliasโ ๐ Warns about declarations using the"alias"and similar attributes whose target doesn't match the alias's type.-Wattribute-alias=1โ The default level diagnoses mismatches between the type of the alias declaration and the type of its target. These mismatches are usually a sign of bugs ๐-Wattribute-alias=2โ At this level, it also diagnoses cases where the alias declaration's attributes are more restrictive than the ones on its target. Those can lead to incorrect code generation. In other cases they're harmless and could be fixed by just adding the missing attribute to the target. For comparison,-Wmissing-attributescontrols diagnostics for when the alias declaration is less restrictive than the target, rather than more restrictive. The attributes considered include"alloc_align","alloc_size","cold","const","hot","leaf","malloc","nonnull","noreturn","nothrow","pure","returns_nonnull", and"returns_twice".
-Wattribute-alias is equivalent to -Wattribute-alias=1, and that's the default. You can turn these warnings off with either -Wno-attribute-alias or -Wattribute-alias=0 ๐
โโ๏ธ
-Wbidi-chars=[none|unpaired|any|ucn]โ ๐ Warns about possibly misleading UTF-8 bidirectional control characters in comments, string literals, character constants, and identifiers. These characters can flip writing direction from left-to-right to right-to-left (and back), which can make the logical order and the visual order fight each other. This can be dangerous. For instance, a piece of code might look commented out when it actually isn't ๐ฑ
GCC supports three warning levels here. The default is -Wbidi-chars=unpaired, which warns about improperly terminated bidi contexts. -Wbidi-chars=none turns the warning off, and -Wbidi-chars=any warns about any use of bidirectional control characters.
By default, this warning doesn't check UCNs. You can turn that checking on with -Wbidi-chars=unpaired,ucn or -Wbidi-chars=any,ucn. Using -Wbidi-chars=ucn is valid too, and it's equivalent to -Wbidi-chars=unpaired,ucn, as long as no earlier -Wbidi-chars=any was specified.
-Wbool-compareโ ๐ง Warns about a boolean expression being compared with an integer value other than"true"/"false". For instance, this comparison is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
This warning is enabled by -Wall.
-Wbool-operationโ ๐ Warns 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โ ๐ Warns when anif-elsehas identical branches. This catches cases like:
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โ ๐ซถ Warns about duplicated conditions in anif-else-ifchain. For instance, it warns for this code:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ ๐ Warns when__builtin_frame_addressor__builtin_return_addressis called with an argument greater than0. Those calls may return indeterminate values or crash the program. This warning is included in-Wall.-Wno-discarded-qualifiers(C and Objective-C only) โ ๐ธ Stops the warning about type qualifiers on pointers being discarded. Usually the compiler warns if a"const char *"variable gets passed to a function that takes a"char *"parameter. Use this option to silence that warning.-Wno-discarded-array-qualifiers(C and Objective-C only) โ ๐ฆ Stops the warning about type qualifiers on arrays that are pointer targets being discarded. Usually the compiler warns if a"const int (*)[]"variable gets passed to a function that takes an"int (*)[]"parameter. Use this option to suppress that warning.-Wno-incompatible-pointer-types(C and Objective-C only) โ ๐ Stops the warning about conversions between pointers with incompatible types. This is for cases that-Wno-pointer-signdoesn't cover; that one handles pointer argument passing or assignment with different signedness.-Wno-int-conversion(C and Objective-C only) โ โจ Stops the warning about incompatible integer-to-pointer and pointer-to-integer conversions. This warning is about implicit conversions. For explicit conversions, you can use-Wno-int-to-pointer-castand-Wno-pointer-to-int-castinstead.-Wzero-length-boundsโ ๐ Warns about accesses to elements of zero-length array members that might overlap other members of the same object. Declaring interior zero-length arrays is discouraged, because accessing them is undefined. See
For example, the first two stores in function bad get flagged, because the array elements overlap the following members b and c. The third store is flagged by -Warray-bounds, because it's 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
}
The option -Wzero-length-bounds is enabled by -Warray-bounds.
-Wno-div-by-zeroโ ๐ข Stops the warning about compile-time integer division by zero. Floating-point division by zero doesn't get warned about, since it can be a legit way to get infinities and NaNs ๐-Wsystem-headersโ ๐ฐ Prints warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they usually aren't real problems and would just make the compiler output harder to read. This option tells GCC to show warnings from system headers as if they came from your own code. Heads up though: using-Wallalongside this option does not warn about unknown pragmas in system headers. For that,-Wunknown-pragmashas to be used too ๐ง-Wtautological-compareโ ๐ Warns if a self-comparison always evaluates to true or false. This catches mistakes like:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always evaluate to true or false. For instance:
if ((a & 16) == 10) { ... }
will always be false.
This warning is enabled by -Wall.
-Wtrampolinesโ okay bestie, this one is about trampolines ๐. These are tiny bits of data or code that get created at run time on the stack whenever you take the address of a nested function, and they're used to call that nested function indirectly ๐ฆ. Some targets only use data, so they need no special treatment โจ. But on most targets a trampoline is made of code ๐, which means the stack has to be made executable for the program to work properly. This flag warns you about trampolines generated for pointers to nested functions.-Wfloat-equalโ warns if floating-point values are used in equality comparisons ๐ฆ. Here's the vibe: sometimes it's convenient to treat floats as approximations of infinitely precise real numbers ๐ธ. If you're doing that, you need to figure out (by analyzing the code or some other way) the maximum or likely maximum error the computation introduces, and account for it when comparing (and when producing output, but that's a whole different problem ๐). Instead of testing for equality, check whether the two values have ranges that overlap. You do that with the relational operators, so equality comparisons are probably a mistake ๐ .-Wtraditional(C and Objective-C only) โ warns about constructs that behave differently in traditional C and ISO C ๐. It also warns about ISO C constructs that have no traditional C equivalent, and/or problematic constructs you should avoid ๐ซถ. Here's the full list of what it catches:- Macro parameters that show up inside string literals in the macro body. Traditional C does macro replacement inside string literals, but ISO C does not ๐ญ.
- Some preprocessor directives didn't exist in traditional C. Traditional preprocessors only treated a line as a directive if the
#was in column 1. So-Wtraditionalwarns about directives that traditional C understands but ignores because the#isn't the first character on the line ๐ง. It also suggests you hide 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.) Heads up: these suffixes show up in macros defined in the system headers of most modern systems, like the_MIN/_MAXmacros in<limits.h>. Using those macros in your own code might normally lead to spurious warnings, but GCC's integrated preprocessor has enough context to avoid warning in these cases ๐. - A function declared external in one block and then used after the end of that block.
- A
switchstatement with an operand of typelong. - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this ๐. - 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) don't get warned about ๐.
- ISO string concatenation usage is detected โจ.
- Initialization of automatic aggregates.
- Identifier conflicts with labels. Traditional C doesn't have a separate namespace for labels ๐.
- Initialization of unions. If the initializer is zero, the warning gets skipped. That's because the zero initializer in user code usually shows up conditioned on something like
__STDC__to avoid missing-initializer warnings, and it relies on default initialization to zero in the traditional C case ๐ฆ. - Conversions by prototypes between fixed-point and floating-point values, and vice versa. Leaving out these prototypes when compiling with traditional C causes serious problems ๐ญ. This is only a subset of the possible conversion warnings; for the full set, use
-Wtraditional-conversion. - Use of ISO C style function definitions. This warning intentionally isn't issued for prototype declarations or variadic functions, because those ISO C features show up in your code when you use libiberty's traditional C compatibility macros,
PARAMSandVPARAMS๐ . This warning is also skipped for nested functions, since 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 without a prototype ๐ฅ. That includes conversions of fixed-point to floating-point and vice versa, and conversions that change the width or signedness of a fixed-point argument, except when that 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 is known from C++, was introduced with ISO C99, and is allowed by default in GCC. It isn't supported by ISO C90 ๐.-Wshadowโ warns whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C), or whenever a built-in function gets shadowed ๐. In C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows astruct/class/enum. If this warning is enabled, it also includes all instances of local shadowing, which means-Wno-shadow=localand-Wno-shadow=compatible-localget ignored when-Wshadowis used ๐. This is the same as-Wshadow=global.-Wno-shadow-ivar(Objective-C only) โ skips the warning 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 the type 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 reason this flag exists (in addition to-Wshadow=local) is 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 in that example 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 cut down on the number of warnings triggered by intentional shadowing ๐
. Also note that shadowing const char *i with char *i does not emit a warning ๐.
This warning is also enabled by -Wshadow=local.
-Wlarger-than=byte-size โ warns whenever an object is defined whose size exceeds byte-size ๐.-Wlarger-than=PTRDIFF_MAXis enabled by default. You can disable warnings from this option either by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-larger-thanโจ. It also warns for calls to bounded functions such asmemchrorstrnlenthat specify a bound greater than the largest possible object, which isPTRDIFF_MAXbytes by default ๐ฅ. These particular 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 โ warns if the size of a function frame exceeds byte-size ๐. The computation done to figure out the stack frame size is approximate and not conservative, so the actual requirements may be somewhat greater than byte-size even if you don't get a warning ๐. Also, any space allocated viaalloca, variable-length arrays, or related constructs is not counted by the compiler when it decides whether to issue a warning ๐.-Wframe-larger-than=PTRDIFF_MAXis enabled by default. You can disable these warnings either by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-frame-larger-than๐.-Wno-frame-larger-thanโ disables-Wframe-larger-than=warnings ๐ง. It's equivalent to-Wframe-larger-than=SIZE_MAXor larger.-Wfree-nonheap-objectโ warns when you try to deallocate an object that was either not allocated on the heap, or using a pointer that wasn't returned from a prior call to the matching allocation function ๐ . Here's a sneaky example: because the call tostpcpyreturns a pointer to the terminating nul character and not to the beginning of the object, the call tofreebelow gets diagnosed ๐ญ.
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wfree-nonheap-object is included in -Wall ๐ซถ.
-Wstack-usage=byte-size โ warns if the stack usage of a function might exceed byte-size ๐. The computation done to determine stack usage is conservative, and any space allocated viaalloca, variable-length arrays, or related constructs is included by the compiler when it decides whether to issue a warning ๐. The message matches the output of-fstack-usage. If the stack usage is fully static but exceeds the specified amount, the message iswarning: stack usage is 1120 bytes๐ฅ. If the stack usage is (partly) dynamic but bounded, the message iswarning: stack usage might be 1648 bytesโจ.
okay so if the stack usage is (partly) dynamic and not bounded, the compiler spits out this message ๐:
warning: stack usage might be unbounded
-Wstack-usage=PTRDIFF_MAX is enabled by default ๐. You can shut off the warnings this option controls in two ways: by giving it a byte-size of SIZE_MAX or more, or by using -Wno-stack-usage.
-Wno-stack-usageโ turns off all the-Wstack-usage=warnings ๐ โโ๏ธ. It's the same as-Wstack-usage=SIZE_MAXor larger.-Wunsafe-loop-optimizationsโ warns when a loop can't be optimized because the compiler can't assume anything about the bounds of the loop indices ๐ง. With-funsafe-loop-optimizations, it warns when the compiler does make those assumptions.-Wno-pedantic-ms-format(MinGW targets only) โ when you use it together with-Wformatand-pedanticwithout GNU extensions, it silences the warnings about non-ISOprintf/scanfformat width specifiersI32,I64, andIon Windows targets ๐ช. Those depend on the MS runtime, so the vibe is "it's fine, I know what I'm doing" ๐ .-Wpointer-arithโ warns about anything that depends on the "size of" a function type or ofvoid๐. GNU C gives these types a size of 1, which is handy for math withvoid *pointers and pointers to functions. In C++, it also warns when an arithmetic operation involvesNULL. This warning is also enabled by-Wpedantic.-Wno-pointer-compareโ doesn't warn if a pointer is compared with a zero character constant ๐. That usually means the pointer was meant to be dereferenced. For example:
const char *p = foo ();
if (p == '\0')
return 42;
Heads up: the code above is invalid in C++11 ๐.
This warning is enabled by default โจ.
-Wtsanโ warns about unsupported features in ThreadSanitizer ๐งต. TSan doesn't supportstd::atomic_thread_fenceand can report false positives, so it's giving "double check your results" ๐ซถ.
This warning is enabled by default โจ.
-Wtype-limitsโ warns if a comparison is always true or always false because of the limited range of the data type ๐ค. Constant expressions are left alone. For example, it warns if an unsigned variable is compared against zero with<or>=. This warning is also enabled by-Wextra.-Wabsolute-value(C and Objective-C only) โ warns about calls to standard functions that compute an absolute value when a better standard function exists ๐. For example, callingabs(3.14)triggers the warning, because the right function for adoubleargument isfabs. It also warns when the argument in a call to such a function has an unsigned type. You can suppress it with an explicit type cast, and it's also enabled by-Wextra.-Wcomment,-Wcommentsโ warns whenever a comment-start sequence/*shows up inside a/*comment, or whenever a backslash-newline shows up in a//comment ๐ฌ. This warning is enabled by-Wall.-Wtrigraphsโ warns if any trigraphs are found that might change the meaning of the program ๐. Trigraphs inside comments don't get flagged, except the ones that would form escaped newlines. This option is implied by-Wall. If you don't pass-Wall, it's still on unless trigraphs are enabled. Want trigraph conversion without the 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.-Wexpansion-to-definedโ warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective ๐ โโ๏ธ. That kind of usage isn't portable. This warning is also 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's 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 flagged.
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, improve the scope of the macro's definition, like moving it into the first skipped block. Or you could add a dummy use, something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ doesn't warn when an#elseor an#endifis followed by text ๐ท๏ธ. This sometimes happens in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should be in comments. This warning is on by default.
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a non-matching type ๐ญ. For example, it warns if a call to a function returning an integer type is cast to a pointer type.-Wc90-c99-compat(C and Objective-C only) โ warns about features that aren't in ISO C90 but are in ISO C99 ๐. For instance, it warns about variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. This option doesn't care about the standards mode. Warnings are disabled in the expression that follows__extension__.-Wc99-c11-compat(C and Objective-C only) โ warns about features that aren't in ISO C99 but are in ISO C11 ๐. For instance, it warns about anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. This option doesn't care about the standards mode. Warnings are disabled in the expression that follows__extension__.-Wc11-c2x-compat(C and Objective-C only) โ warns about features that aren't in ISO C11 but are in ISO C2X ๐ฎ. For instance, it warns about leaving out the string in_Static_assert, using[[]]attribute syntax, using decimal floating-point types, and so on. This option doesn't care about the standards mode. Warnings are disabled in the expression that follows__extension__.-Wc++-compat(C and Objective-C only) โ warns about ISO C constructs that live outside the common subset of ISO C and ISO C++ ๐ค. For example, it warns about implicit conversion fromvoid *to a pointer to a non-voidtype.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changes between ISO C++ 1998 and ISO C++ 2011 ๐. For example, identifiers in ISO C++ 1998 that are keywords in ISO C++ 2011. This warning turns on-Wnarrowingand is enabled by-Wall.-Wc++14-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changes 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 changes 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 changes between ISO C++ 2017 and ISO C++ 2020 ๐. This warning is enabled by-Wall.-Wno-c++11-extensions(C++ and Objective-C++ only) โ doesn't warn about C++11 constructs in code being compiled with an older C++ standard ๐. Even without this option, some C++11 constructs only get diagnosed if you use-Wpedantic.-Wno-c++14-extensions(C++ and Objective-C++ only) โ doesn't warn about C++14 constructs in code being compiled with an older C++ standard ๐. Even without this option, some C++14 constructs only get diagnosed if you use-Wpedantic.-Wno-c++17-extensions(C++ and Objective-C++ only) โ doesn't warn about C++17 constructs in code being compiled with an older C++ standard ๐. Even without this option, some C++17 constructs only get diagnosed if you use-Wpedantic.-Wno-c++20-extensions(C++ and Objective-C++ only) โ doesn't warn about C++20 constructs in code being compiled with an older C++ standard ๐. Even without this option, some C++20 constructs only get diagnosed if you use-Wpedantic.-Wno-c++23-extensions(C++ and Objective-C++ only) โ doesn't warn about C++23 constructs in code being compiled with an older C++ standard ๐. Even without this option, some C++23 constructs only get diagnosed if you use-Wpedantic.-Wcast-qualโ warns whenever a pointer gets cast in a way that removes a type qualifier from the target type ๐. For example, it warns if aconst char *is cast to an ordinarychar *.
It also warns when a cast introduces a type qualifier in an unsafe way. For example, casting char ** to const char ** is unsafe, as in this example:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ warns whenever a pointer gets cast in a way that increases the required alignment of the target ๐. For example, it warns if achar *is cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries.-Wcast-align=strictโ warns whenever a pointer gets cast in a way that increases the required alignment of the target, no matter what machine you're on ๐งฑ. For example, it warns if achar *is cast to anint *regardless of the target machine.-Wcast-function-typeโ warns when a function pointer gets cast to an incompatible function pointer ๐. In a cast involving function types with a variable argument list, only the types of the initial arguments that are provided get considered. Any parameter of pointer-type matches any other pointer-type. Benign differences in integral types get ignored, likeintvs.longon ILP32 targets. Type qualifiers get ignored too. The function typevoid (*) (void)is special and matches everything, so you can use it to suppress this warning ๐คซ. In a cast involving pointer to member types, this warning fires whenever the cast changes the pointer to member type. This warning is enabled by-Wextra.-Wwrite-stringsโ okay bestie, when you're compiling C this one gives string constants the typeconst char[length], so copying one's address into a non-constchar *pointer gets you a warning ๐ . It helps you catch code that might try to write into a string constant at compile time, but ONLY if you've been super careful withconstin your declarations and prototypes ๐ฅบ. Otherwise it's just a nuisance ๐ญ, which is exactly why-Walldoesn't ask for these warnings ๐ซถ. When you're compiling C++, it warns about the deprecated conversion from string literals tochar *, and this one is turned on by default for C++ programs โจ.-Wclobberedโ warns about variables that might get changed bylongjmporvfork๐ฆ. It's also switched on by-Wextra๐ธ.-Wconversionโ the main character of implicit conversions ๐. It warns when an implicit conversion might alter a value, likeabs (x)whenxisdouble(real to integer),unsigned ui = -1(signed to unsigned), orsqrtf (M_PI)(down to a smaller type) ๐. It does NOT warn for explicit casts likeabs ((int) x)andui = (unsigned) -1, or when the value doesn't actually change, likeabs (2.0)๐. Signed/unsigned warnings can be silenced with-Wno-sign-conversion๐. For C++, it also warns about confusing overload resolution for user-defined conversions, plus conversions that never use a type conversion operator (tovoid, the same type, a base class, or a reference to them) ๐ง. Signed/unsigned conversion warnings are off by default in C++ unless you explicitly turn on-Wsign-conversion๐. And warnings about arithmetic on a small type converting back to that same type only show up with-Warith-conversion๐.-Wdangling-elseโ this one is for when anelsecould be confusing about whichifit belongs to ๐. Check out this example:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C/C++, every else branch belongs to the innermost possible if statement, which here is if (b) ๐. That's usually NOT what the programmer meant, even though the indentation suggests otherwise ๐ญ. When this potential confusion exists, GCC warns when this flag is specified ๐จ. To kill the warning, add explicit braces around the innermost if statement so the else can't possibly belong to the enclosing if โจ. It ends up looking like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses ๐.
-Wdangling-pointer,-Wdangling-pointer=nโ okay this is about using pointers (or C++ references) to objects with automatic storage duration AFTER their lifetime has ended ๐. That includes local variables in nested blocks, compound literals, and other unnamed temporary objects ๐. It also warns about storing the address of those objects in escaped pointers ๐ซฃ. It's enabled at all optimization levels, but it might give different results with optimization than without ๐.-Wdangling-pointer=1โ at level 1, only UNCONDITIONAL uses of dangling pointers get diagnosed ๐ฅ. For example:
int f (int c1, int c2, x)
{
char *p = strchr ((char[]){ c1, c2 }, c3);
return p ? *p : 'x'; // warning: dangling pointer to a compound literal
}
In the following function, storing the address of the local variable x in the escaped pointer *p also triggers the warning ๐.
void g (int **p)
{
int x = 7;
*p = &x; // warning: storing the address of a local variable in *p
}
-Wdangling-pointer=2โ at level 2, the warning also catches CONDITIONAL uses of dangling pointers, on top of the unconditional ones ๐ง. For example, the arrayain the following function is out of scope when the pointersthat was set to point at it gets used, so the warning triggers at this level ๐ฆ.
void f (char *s)
{
if (!s)
{
char a[12] = "tmpname";
s = a;
}
strcat (s, ".tmp"); // warning: dangling pointer to a may be used
...
}
-Wdangling-pointer=2 is included in -Wall ๐
.
-Wdate-timeโ warns when the macros__TIME__,__DATE__or__TIMESTAMP__show up, since they might stop your compiles from being bit-wise-identical and reproducible โฐ.-Wempty-bodyโ warns if an empty body shows up in anif,elseordo whilestatement ๐ซง. It's also enabled by-Wextra๐ธ.-Wno-endif-labelsโ don't warn about stray tokens after#elseand#endif๐.-Wenum-compareโ warns about comparisons between values of different enumerated types ๐. In C++, enumerated type mismatches in conditional expressions get diagnosed too, and this one is on by default there โจ. In C, it's enabled by-Wall๐.-Wenum-conversionโ warns when a value of one enumerated type gets implicitly converted to a DIFFERENT enumerated type ๐ฆ. In C, this is enabled by-Wextra๐.-Wjump-misses-init(C, Objective-C only) โ warns if agotoorswitchstatement jumps forward across the initialization of a variable, or jumps backward to a label after that variable has already been initialized ๐ง. It only cares about variables that get initialized when they're declared ๐. This one is only supported for C and Objective-C, because in C++ this sort of branch is an error anyway ๐ โโ๏ธ.-Wjump-misses-initis included in-Wc++-compat๐. You can turn it off with the-Wno-jump-misses-initoption ๐ .
-Wsign-compareโ warns when a comparison between signed and unsigned values could give an incorrect result, because the signed value gets converted to unsigned ๐ฅ. In C++, this is also enabled by-Wall๐ซถ. In C, it's enabled by-Wextra๐ธ.-Wsign-conversionโ warns about implicit conversions that might change the sign of an integer value, like assigning a signed integer expression to an unsigned integer variable ๐. An explicit cast silences it ๐. In C, this option is also enabled by-Wconversion๐.-Wfloat-conversionโ warns about implicit conversions that reduce the precision of a real value ๐. That includes real-to-integer conversions, and conversions from higher-precision real values to lower-precision ones ๐. This option is also enabled by-Wconversionโจ.-Wno-scalar-storage-orderโ don't warn about suspicious constructs involving reverse scalar storage order ๐.-Wsizeof-array-divโ warns about divisions of twosizeofoperators when the first one is applied to an array and the divisor doesn't equal the size of the array element ๐งฎ. In that case the computation won't give you the number of elements in the array, which is probably what you actually wanted ๐. This warns about things like:
int fn ()
{
int arr[10];
return sizeof (arr) / sizeof (short);
}
This warning is enabled by -Wall ๐ซถ.
-Wsizeof-pointer-divโ warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size ๐. That's the usual way to compute an array's size, but it won't work out correctly with pointers ๐ญ. It warns e.g. aboutsizeof (ptr) / sizeof (ptr[0])ifptris a pointer and not an array ๐. This warning is enabled by-Wall๐ .-Wsizeof-pointer-memaccessโ warns about suspicious length parameters to certain string and memory built-in functions when the argument usessizeof๐. It triggers for things likememset (ptr, 0, sizeof (ptr));ifptris a pointer and not an array, and it suggests a possible fix ๐ฆ. It also triggers for stuff likememcpy (&foo, ptr, sizeof (&foo));๐ง. This one also warns about calls to bounded string copy functions likestrncatorstrncpythat use asizeofexpression of the source array as the bound ๐ซฃ. In the example below, the call tostrncatuses the size of the source string as its bound, which is almost certainly a mistake, so the call gets diagnosed ๐จ.
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall ๐ธ.
-Wno-sizeof-array-argumentโ don't warn when thesizeofoperator is applied to a parameter that's declared as an array in a function definition ๐. This warning is enabled by default for C and C++ programs ๐.-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function if the first argument references an array, and the third argument is a number equal to the number of elements but NOT equal to the size of the array in memory ๐. That means you probably forgot to multiply by the element size ๐. This warning is enabled by-Wallโจ.-Wmemset-transposed-argsโ warns about suspiciousmemsetcalls where the second argument isn't zero and the third argument is zero ๐. For example,memset (buf, sizeof buf, 0)gets diagnosed becausememset (buf, 0, sizeof buf)was what you meant ๐ซถ. The diagnostic only shows up if the third argument is a literal zero ๐. If it's an expression that folds to zero, or a cast of zero to some type, the arguments are far less likely to have been mistakenly transposed, so no warning is emitted ๐ฆ. This warning is enabled by-Wall๐ .-Waddressโ warns about suspicious uses of address expressions ๐. These include comparing the address of a function or a declared object to the null pointer constant, such as in
void f (void);
void g (void)
{
if (!func) // warning: expression evaluates to false
abort ();
}
okay so GCC is literally side-eyeing this if (!func) ๐ because a function's address is basically always truthy ๐
(the only exception is weak symbols ๐ซถ). so putting it in a condition is usually a sign you forgot the parentheses on a call or a dereference somewhere ๐
Comparing a pointer to a string literal is also flagged, like this โจ
void f (const char *x)
{
if (x == "abc") // warning: expression evaluates to false
puts ("equal");
}
and so is testing the result of pointer addition or subtraction for equality to null ๐
void f (const int *p, int i)
{
return p + i == NULL;
}
these almost always mean a programmer error, bestie ๐ญ if it's the object-pointer part of the warning you're dealing with, you can shut it up by casting the pointer operand to an integer type, like inptr_t or uinptr_t. comparing against string literals is unspecified behavior and not portable, and it's giving "you meant strcmp" energy ๐ the warning also goes quiet if the sketchy expression came out of a macro expansion. and -Waddress is turned on by -Wall ๐ธ
-Wno-address-of-packed-memberโ don't warn when someone takes the address of a packed member of a struct or union, since that usually gives you an unaligned pointer value. this one is already on by default, so it's the main character ๐-Wlogical-opโ warns about suspicious logical operators in expressions, including when&&or||shows up somewhere a bit-wise operator is probably what you wanted ๐ง it also calls out when both operands of a logical operator are the exact same thing:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns when a logical not is on the left-hand side of a comparison. it won't warn if the right operand counts as a boolean expression. the whole point is catching stuff like this ๐
int a;
...
if (!a > 1) { ... }
if you want to silence it, just wrap the left 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 gets a warning too ๐)-Wno-aggressive-loop-optimizationsโ 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โ don't warn if an unexpected__attribute__shows up, like unrecognized attributes or function attributes slapped onto variables. this does not stop errors for incorrect use of supported attributes, so don't get it twisted ๐ซถ
also, with -Wno-attributes=, you can hush warnings about unknown scoped attributes (in C++11 and C2X). for example, -Wno-attributes=vendor::attr disables the warning for this declaration:
[[vendor::attr]] void f();
you can mute every attribute warning in a namespace with -Wno-attributes=vendor::, which covers both of these at once ๐ฆ
[[vendor::safe]] void f();
[[vendor::unsafe]] void f2();
heads up bestie:-Wno-attributes=does not imply-Wno-attributes๐ญ
-Wno-builtin-declaration-mismatchโ warns if a built-in function is declared with an incompatible signature or as a non-function, or when a built-in function declared with a type that doesn't include 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 function that takes arguments is declared without a prototype. the-Wbuiltin-declaration-mismatchwarning is enabled by default โจ to avoid it, include the appropriate header so the built-in function prototypes are in scope.
check out this memset call. it gets flagged because memset wants a value of type size_t as its argument, but the type of 32 is int ๐
with -Wextra, the declaration gets called out too:
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ don't warn if certain built-in macros get redefined. this silences warnings for redefining__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 allowed without a warning if it's preceded by a declaration that specifies the argument types ๐)-Wold-style-declaration(C and Objective-C only) โ warns about obsolescent usages in a declaration, according to the C Standard. for example, it warns if storage-class specifiers likestaticaren't the first things in a declaration. this one also gets turned on by-Wextra๐ง-Wold-style-definition(C and Objective-C only) โ warns if an old-style function definition is used, and it does this even if there's a previous prototype ๐ a definition using()is not considered an old-style definition in C2X mode, because it's equivalent to(void)in that case. but it is considered old-style for older standards.-Wmissing-parameter-type(C and Objective-C only) โ warns when a function parameter is declared without a type specifier in K&R-style functions ๐ฆ
void foo(bar) { }
this warning is also enabled by -Wextra ๐
-Wmissing-prototypes(C and Objective-C only) โ warns if a global function is defined without a previous prototype declaration. this warning is issued even if the definition itself provides a prototype. use it to catch global functions that don't have a matching prototype declaration in a header file ๐ธ this option is not valid for C++, because all function declarations provide prototypes there, and a non-matching declaration declares an overload rather than conflicting with an earlier declaration. use-Wmissing-declarationsto detect missing declarations in C++ instead.-Wmissing-declarationsโ warns if a global function is defined without a previous declaration, even if the definition itself provides a prototype. use it to catch global functions that aren't declared in header files โจ in C, no warnings are issued for functions with previous non-prototype declarations, so use-Wmissing-prototypesfor those. in C++, no warnings are issued for function templates, inline functions, or functions in anonymous namespaces ๐-Wmissing-field-initializersโ warns if a struct's initializer has some fields missing. for example, this causes such a warning, becausex.his implicitly zero ๐
struct s { int f, g, h; };
struct s x = { 3, 4 };
this option doesn't warn about designated initializers, so the following modification does not trigger a warning โจ
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
in C, this option doesn't warn about the universal zero initializer { 0 } ๐ซถ
struct s { int f, g, h; };
struct s x = { 0 };
likewise, in C++ this option doesn't warn about the empty { } initializer, for example:
struct s { int f, g, h; };
s x = { };
this warning is included in -Wextra. if you want the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers ๐
-Wno-missing-requiresโ by default, the compiler warns about a concept-id appearing as a C++20 simple-requirement ๐
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 instead:
bool satisfied = requires { requires C<T> };
so 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::must be followed by thetemplatekeyword if the parent object is dependent and the member being named is a template ๐ง
template <class X>
void DoStuff (X x)
{
x.template DoSomeOtherStuff<X>(); // Good.
x.DoMoreStuff<X>(); // Warning, x is dependent.
}
in rare cases you can get false positives. to silence them, wrap the expression in parentheses. for example, the following is treated as a template, even where m and N are integers ๐
void NotATemplate (my_class t)
{
int N = 5;
bool test = t.m < N > (0); // Treated as a template.
test = (t.m < N) > (0); // Same meaning, but not treated as a template.
}
this warning can be disabled with -Wno-missing-template-keyword ๐
-Wno-multicharโ don't warn if a multicharacter constant ('FOOF') is used. these usually mean there's a typo in your code, since they have implementation-defined values and shouldn't be used in portable code ๐-Wnormalized=[none|id|nfc|nfkc]โ in ISO C and ISO C++, two identifiers are different if they're different sequences of characters. but when characters outside the basic ASCII set are used, you can have two different character sequences that look exactly the same ๐ to avoid the confusion, the ISO 10646 standard sets out normalization rules that turn look-alike sequences into the same sequence when applied. GCC can warn you if you're using identifiers that haven't been normalized, and this option controls that warning ๐ฆ
Okay so, bestie, GCC has four levels of warning for identifier normalization ๐ซถโจ The default is -Wnormalized=nfc, which yells about any identifier that isn't in the ISO 10646 "C" normalized form, NFC ๐
NFC is the recommended vibe for most uses, and it's the same thing as -Wnormalized.
Real talk though, ISO C and ISO C++ let some characters into identifiers that stop being allowed once they get turned into NFC ๐ญ So there's no way to use those symbols in portable ISO C or C++ and still have every identifier in NFC. -Wnormalized=id silences the warning for just those characters ๐ธ The standards people are hoping future versions will fix this, which is why it isn't the default ๐
You can switch the warning off for every character with -Wnormalized=none or -Wno-normalized ๐ฅบ But only do this if you're using some other normalization scheme (like "D") โจ
Seriously, if you turn this off without a different normalization scheme, you can easily create bugs that are literally impossible to see ๐
Some characters in ISO 10646 have totally different 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 shoved into a superscript ๐ฆ ISO 10646 also defines the NFKC normalization scheme to convert all of these into a standard form, and GCC warns if your code isn't in NFKC when you use -Wnormalized=nfkc ๐ฅ That warning is comparable to warning about every identifier with the letter O, since it might get mixed up with the digit 0, so it's not the default ๐ญ It can still be a useful local coding convention if your programming environment can't be fixed to display these characters distinctly ๐
-Wno-attribute-warningโ stop warning about usage of functions declared with the "warning" attribute ๐ โโ๏ธ This one is on by default, so you only need this if it's bugging you. Use-Wno-attribute-warningto disable the warning, or-Wno-error=attribute-warningto disable the error when you're compiling with-Werror๐-Wno-deprecatedโ do not warn about usage of deprecated features ๐-Wno-deprecated-declarationsโ do not warn about uses of functions, variables, and types marked as deprecated with the "deprecated" attribute ๐ง-Wno-overflowโ do not warn about compile-time overflow in constant expressions ๐-Wno-odrโ warn about One Definition Rule violations during link-time optimization. This one is enabled by default โญ-Wopenacc-parallelismโ warn about potentially suboptimal choices related to OpenACC parallelism ๐ฅ-Wopenmp-simdโ warn if the vectorizer cost model overrides the OpenMP simd directive you set. If you want to loosen the cost model, you can use-fsimd-cost-model=unlimited๐-Woverride-init(C and Objective-C only) โ warn if an initialized field without side effects gets overridden when you're using designated initializers ๐ This one is included in-Wextra. If you want the other-Wextrawarnings but not this one, use-Wextra -Wno-override-init๐ซถ-Wno-override-init-side-effects(C and Objective-C only) โ do not warn if an initialized field with side effects gets overridden when using designated initializers. This is enabled by default โจ-Wpackedโ warn if a structure gets the packed attribute but the packed attribute has no effect on the layout or size of the structure. Those structs can end up misaligned for very little benefit ๐ฅ For instance, in this code, 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, there is no longer a 4-bit padding between fieldaandbin this structure:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default. Use -Wno-packed-bitfield-compat to disable it ๐
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ warn if a structure field with explicitly specified alignment in a packed struct or union is misaligned ๐ For example, a warning gets issued onstruct Sthat reads likewarning: alignment 1 of 'struct S' is less than 8in this code:
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall ๐ธ
-Wpaddedโ warn if padding is included in a structure, either to align an element of the structure or to align the whole structure ๐งธ Sometimes you can rearrange the fields to reduce the padding and make the structure smaller ๐-Wredundant-declsโ warn if anything is declared more than once in the same scope, even in cases where multiple declarations are valid and change nothing ๐-Wrestrictโ warn when an object referenced by arestrict-qualified parameter (or, in C++, a__restrict-qualified parameter) is aliased by another argument, or when copies between those objects overlap ๐จ For example, the call tostrcpybelow tries to truncate the string by replacing its initial characters with the last four. But because the call writes the terminating NUL intoa[4], the copies overlap, and the call gets diagnosed:
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
The -Wrestrict option catches some instances of simple overlap even without optimization, but it works best at -O2 and above. It's included in -Wall ๐ซง
-Wnested-externs(C and Objective-C only) โ warn if anexterndeclaration is encountered within a function ๐ต๏ธ-Winlineโ warn if a function declared asinlinecannot be inlined. Even with this option on, the compiler does not warn about failures to inline functions declared in system headers ๐ โโ๏ธ The compiler uses a bunch of heuristics to decide whether to inline a function, like the size of the function being inlined and how much inlining has already happened in the current function. So seemingly insignificant changes in your source can make the-Winlinewarnings show up or disappear ๐คทโโ๏ธ-Winterference-sizeโ warn about use of the C++17std::hardware_destructive_interference_sizewithout specifying its value with--param destructive-interference-size. It also warns about questionable values for that option ๐ง This variable is meant for controlling class layout, to avoid false sharing in concurrent code:
struct independent_fields {
alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
};
Here, one and two are meant to be far enough apart that stores to one won't require accesses to two to reload the cache line ๐ฆ
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, and sometimes 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 the use is 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โ warn for suspicious use of integer values where boolean values are expected ๐คจ Examples include conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). It also covers left shifting of signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. Likewise for all kinds of multiplications, regardless of the data type. This warning is enabled by-Wall๐-Wno-int-to-pointer-castโ suppress warnings from casts to a pointer type of an integer of a different size. In C++, casting to a pointer type of smaller size is an error, so careful bestie ๐ซWint-to-pointer-castis enabled by default ๐ท-Wno-pointer-to-int-cast(C and Objective-C only) โ suppress warnings from casts from a pointer to an integer type of a different size ๐งโโ๏ธ-Winvalid-pchโ warn if a precompiled header is found in the search path but can't be used ๐-Wlong-longโ warn if thelong longtype is used. This is enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. To inhibit the warning messages, use-Wno-long-long๐ญ-Wvariadic-macrosโ warn 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โ do not warn upon questionable usage of the macros used to handle variable arguments, likeva_start. These warnings are enabled by default ๐ฆ
โ ๏ธ -Wvector-operation-performance ๐
Okay so this one warns you if a vector operation isn't using the SIMD stuff your architecture actually has. It's mainly for performance tuning, bestie ๐๏ธ. A vector operation can get implemented three ways:
- "piecewise": the scalar operation runs on every single vector element one by one ๐
- "in parallel": the vector operation uses scalars of a wider type, which is normally more performance efficient ๐
- "as a single scalar": the vector fits into a scalar type, so it's one scalar op ๐ฏ
๐ -Wvla
Warns if a variable-length array shows up in your code. -Wno-vla stops the -Wpedantic warning about variable-length arrays, so you can keep the drama down ๐คซ
๐ -Wvla-larger-than=byte-size
If you use this, GCC will warn about variable-length array declarations whose size is either unbounded, or bounded by an argument that lets the array go past byte-size bytes. It's giving -Walloca-larger-than=byte-size energy, just for VLAs instead ๐ซถ
Heads up: GCC might optimize small variable-length arrays with a known value into plain arrays, so this warning may not fire for those.
-Wvla-larger-than=PTRDIFF_MAX is turned on by default, but it's typically only actually effective when -ftree-vrp is active. That's on by default for -O2 and above ๐
See also -Walloca-larger-than=byte-size.
๐
โโ๏ธ -Wno-vla-larger-than
Disables the -Wvla-larger-than= warnings. It's the same as -Wvla-larger-than=SIZE_MAX or larger ๐
๐งฉ -Wvla-parameter
This one warns about function redeclarations where the arguments are variable-length array types of inconsistent kinds or forms. It also turns on detecting out-of-bounds accesses to those parameters, through warnings like -Warray-bounds ๐ฆ
If the first function declaration uses the VLA form, the bound in the array is treated as the minimum number of elements expected to be passed to the function, and the maximum number of elements it accesses. Passing arguments that are too small, or accessing more than that max, may get diagnosed ๐
Here's the example, and why the warning triggers. The first declaration lets an array of any size 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 bigger than the actual VLA bound also triggers a warning โจ
void f (int n, int[n]);
void f (int, int[]); // warning: argument 2 previously declared as a VLA
void g (int n)
{
if (n > 4)
return;
int a[n];
f (sizeof a, a); // warning: access to a by f may be out of bounds
...
}
-Wvla-parameter is included in -Wall. And -Warray-parameter handles similar problems, but for ordinary array arguments ๐
๐ -Wvolatile-register-var
Warns if a register variable is declared volatile. Here's the tea: the volatile modifier doesn't stop every optimization that might eliminate reads and/or writes to register variables, so it's not the safety net you'd think ๐ This warning is enabled by -Wall ๐ธ
๐ข -Wdisabled-optimization
Warns if a requested optimization pass gets disabled. Not gonna lie, this doesn't usually mean your code is broken ๐ It just means GCC's optimizers can't handle the code effectively. Often your code is too big or too complex, and GCC refuses to optimize programs when the optimization would probably take an absurd amount of time ๐ฉ
โ๏ธ -Wpointer-sign (C and Objective-C only)
Warns for pointer argument passing or assignment with different signedness. This is only supported for C and Objective-C ๐ท It's implied by -Wall and by -Wpedantic, and you can turn it off with -Wno-pointer-sign.
๐ก๏ธ -Wstack-protector
This only does anything when -fstack-protector is active. It warns about functions that aren't protected against stack smashing ๐งฑ
๐ -Woverlength-strings
Warns about string constants that are longer than the "minimum maximum" length the C standard specifies. Modern compilers are chill and allow string constants way longer than the standard's minimum, but very portable programs should avoid longer strings ๐
The limit applies after string constant concatenation, and it doesn't count the trailing NUL. In C90 the limit was 509 characters, and in C99 it got raised to 4095. C++98 doesn't set a normative minimum maximum, so GCC doesn't diagnose overlength strings in C++ ๐
This option is implied by -Wpedantic, and you can disable it with -Wno-overlength-strings.
๐ข -Wunsuffixed-float-constants (C and Objective-C only)
Issues a warning for any floating constant that doesn't have a suffix ๐ซ When you combine it with -Wsystem-headers, it warns about those constants in system header files too. This is super useful when you're prepping code to use with the "FLOAT_CONST_DECIMAL64" pragma from the decimal floating-point extension to C99 ๐งฎ
๐ -Wno-lto-type-mismatch
During link-time optimization, this stops GCC from warning about type mismatches in global declarations across different compilation units. It requires -flto to be enabled, and it's enabled by default ๐ซถ
๐ฏ -Wno-designated-init (C and Objective-C only)
Suppresses warnings when a positional initializer is used to initialize a structure that's been marked with the "designated_init" attribute ๐
๐ Options That Control Static Analysis
๐ต๏ธ -fanalyzer
This option turns on a static analysis of program flow. It hunts for "interesting" interprocedural paths through your code and issues warnings for problems it finds on them ๐ Fair warning, it's way more expensive than other GCC warnings, so it's not a fast bestie ๐
Enabling this option effectively enables the following warnings:
-Wanalyzer-double-fclose -Wanalyzer-double-free
-Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak
-Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak
-Wanalyzer-mismatching-deallocation
-Wanalyzer-possible-null-argument
-Wanalyzer-possible-null-dereference -Wanalyzer-null-argument
-Wanalyzer-null-dereference -Wanalyzer-shift-count-negative
-Wanalyzer-shift-count-overflow -Wanalyzer-stale-setjmp-buffer
-Wanalyzer-tainted-allocation-size -Wanalyzer-tainted-array-index
-Wanalyzer-tainted-divisor -Wanalyzer-tainted-offset
-Wanalyzer-tainted-size -Wanalyzer-unsafe-call-within-signal-handler
-Wanalyzer-use-after-free -Wanalyzer-use-of-uninitialized-value
-Wanalyzer-use-of-pointer-in-stale-stack-frame
-Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal
This option is only available if GCC was configured with analyzer support enabled. No analyzer, no vibes ๐
๐งญ -Wanalyzer-too-complex
If -fanalyzer is enabled, the analyzer uses a bunch of heuristics to explore the control flow and data flow in the program ๐บ๏ธ But sufficiently complicated code can totally defeat them. By default, the analysis silently stops if the code is too complicated and it hits an internal limit. -Wanalyzer-too-complex makes it warn you when that happens ๐ข
๐ -Wno-analyzer-double-fclose
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-double-fclose to disable it ๐
โโ๏ธ
It warns for paths through the code where a FILE * can have fclose called on it more than once ๐
๐ชฃ -Wno-analyzer-double-free
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-double-free to disable it.
It warns for paths through the code where a pointer can have a deallocator called on it more than once. That deallocator can be free, or a deallocator referenced by attribute "malloc" ๐งน
๐ค -Wno-analyzer-exposure-through-output-file
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-exposure-through-output-file to disable it.
It warns for paths through the code where a security-sensitive value gets written to an output file, like writing a password to a log file ๐ Yikes, don't do that bestie ๐ญ
๐งพ -Wno-analyzer-file-leak
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-file-leak to disable it.
It warns for paths through the code where a <stdio.h> FILE * stream object gets leaked ๐ง
๐ฒ -Wno-analyzer-free-of-non-heap
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-free-of-non-heap to disable it.
It warns for paths through the code where free gets called on a non-heap pointer, like an on-stack buffer or a global ๐
๐ง -Wno-analyzer-malloc-leak
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-malloc-leak to disable it.
It warns for paths through the code where a pointer allocated via an allocator is leaked. That allocator can be malloc, or a function marked with attribute "malloc" ๐ซ
๐ -Wno-analyzer-mismatching-deallocation
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-mismatching-deallocation to disable it.
It warns for paths through the code where the wrong deallocation function gets called on a pointer value, based on which function was used to allocate it. It'll flag mismatches between free, scalar delete and vector delete[], and those marked as allocator/deallocator pairs using attribute "malloc" ๐ซ
โ -Wno-analyzer-possible-null-argument
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-possible-null-argument to disable it.
It warns for paths through the code where a possibly-NULL value gets passed to a function argument marked with __attribute__((nonnull)), which requires a non-NULL value ๐
๐ป -Wno-analyzer-possible-null-dereference
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-possible-null-dereference to disable it.
It warns for paths through the code where a possibly-NULL value gets dereferenced ๐
๐ซฅ -Wno-analyzer-null-argument
This warning requires -fanalyzer, which enables it. Use -Wno-analyzer-null-argument to disable it. โจ
This one's about a value the analyzer knows is NULL getting handed to a function argument marked __attribute__((nonnull)), which means that argument really needs a non-NULL value ๐ซถ bestie, that's a whole vibe check.
-Wno-analyzer-null-dereferenceโ needs-fanalyzerto turn it on, and you can switch it off with-Wno-analyzer-null-dereference๐ It flags paths where something known to be NULL gets dereferenced ๐-Wno-analyzer-shift-count-negativeโ needs-fanalyzer, and you disable it with-Wno-analyzer-shift-count-negative๐ธ It catches paths where a shift happens with a negative count. It's the analyzer's cousin of-Wshift-count-negativefrom the C/C++ front ends, except this one follows interprocedural paths instead of just reading the syntax tree. The analyzer doesn't prioritize finding these, so false negatives are more likely than with other warnings ๐-Wno-analyzer-shift-count-overflowโ needs-fanalyzer, and you turn it off with-Wno-analyzer-shift-count-overflowโจ This one flags paths where the shift count is greater than or equal to the precision of the operand's type. Same energy as-Wshift-count-overflowin the front ends, but it's built on interprocedural paths rather than the syntax tree. Again, the analyzer doesn't prioritize these, so false negatives are more likely relative to other warnings ๐ง-Wno-analyzer-stale-setjmp-bufferโ needs-fanalyzer, and disabling is-Wno-analyzer-stale-setjmp-buffer๐ฆ It warns about paths wherelongjmptries to rewind to ajmp_buftied to asetjmpcall inside a function that has already returned. Whensetjmpruns on ajmp_buf, it records the stack frame, and that frame goes invalid once the function returns. Rewinding to it means pointing at a stack frame that doesn't exist anymore, which can crash or get even worse ๐ญ-Wno-analyzer-tainted-allocation-sizeโ needs both-fanalyzerand-fanalyzer-checker=taint, and you turn it off with-Wno-analyzer-tainted-allocation-size๐ฅ It flags paths where a value an attacker could control becomes the size of an allocation without being sanitized. That lets an attacker push in a huge allocation and cause a denial of service. See CWE-789: Memory Allocation with Excessive Size Value athttps://cwe.mitre.org/data/definitions/789.html๐-Wno-analyzer-tainted-array-indexโ needs both-fanalyzerand-fanalyzer-checker=taint, and disabling it is-Wno-analyzer-tainted-array-index๐ It catches an attacker-controllable value used as an array index without sanitizing, which could sneak in an out-of-bounds access. See CWE-129: Improper Validation of Array Index athttps://cwe.mitre.org/data/definitions/129.html๐-Wno-analyzer-tainted-divisorโ needs both-fanalyzerand-fanalyzer-checker=taint, and you switch it off with-Wno-analyzer-tainted-divisor๐ It warns when an attacker-controllable value is the divisor in a division or modulus operation with no sanitizing, so an attacker could inject a division-by-zero ๐-Wno-analyzer-tainted-offsetโ needs both-fanalyzerand-fanalyzer-checker=taint, and disabling it is-Wno-analyzer-tainted-offset๐ This one is for attacker-controllable values used as a pointer offset without sanitizing, which could inject an out-of-bounds access. See CWE-823: Use of Out-of-range Pointer Offset athttps://cwe.mitre.org/data/definitions/823.html๐ซถ-Wno-analyzer-tainted-sizeโ needs both-fanalyzerand-fanalyzer-checker=taint, and you turn it off with-Wno-analyzer-tainted-size๐ It flags an attacker-controllable value used as the size of an operation likememsetwithout sanitizing, which could inject an out-of-bounds access โจ-Wno-analyzer-unsafe-call-within-signal-handlerโ needs-fanalyzer, and you disable it with-Wno-analyzer-unsafe-call-within-signal-handler๐ It catches paths where a function that's known to be async-signal-unsafe, likefprintf, gets called from inside a signal handler.-Wno-analyzer-use-after-freeโ needs-fanalyzer, and disabling is-Wno-analyzer-use-after-free๐ It warns about paths where a pointer gets used after a deallocator has been called on it. That deallocator is eitherfree, or one referenced by themallocattribute ๐ญ-Wno-analyzer-use-of-pointer-in-stale-stack-frameโ needs-fanalyzer, and you switch it off with-Wno-analyzer-use-of-pointer-in-stale-stack-frame๐ฆ It flags paths where a pointer gets dereferenced and points to a variable living in a stale stack frame.-Wno-analyzer-write-to-constโ needs-fanalyzer, and you disable it with-Wno-analyzer-write-to-const๐ธ It warns when the analyzer detects someone trying to write through a pointer to aconstobject. The analyzer doesn't prioritize these paths, so false negatives are more likely than with other warnings ๐-Wno-analyzer-write-to-string-literalโ needs-fanalyzer, and turning it off is-Wno-analyzer-write-to-string-literal๐ This one flags attempts to write through a pointer to a string literal. Same deal as before: the analyzer doesn't prioritize these, so false negatives are more likely relative to other warnings โจ-Wno-analyzer-use-of-uninitialized-valueโ needs-fanalyzer, and you disable it with-Wno-analyzer-use-of-uninitialized-value๐ง It warns about paths where an uninitialized value gets used.
Okay so, these are the knobs for steering the exploration ๐๏ธ Pertinent parameters for controlling the exploration are: --param analyzer-bb-explosion-factor=value, --param analyzer-max-enodes-per-program-point=value, --param analyzer-max-recursion-depth=value, and --param analyzer-min-snodes-for-call-summary=value ๐
The following options control the analyzer, and they're giving main character energy ๐
-fanalyzer-call-summariesโ this simplifies interprocedural analysis by computing the effect of certain calls, instead of exploring every path through the function from the callsite to each possible return ๐ If it's enabled, call summaries only get 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 turns that checker on ๐ Some checkers are disabled by default, even with-fanalyzer. The "taint" checker, which implements-Wanalyzer-tainted-array-index, is one of them, and this option is required to enable it ๐ฅ
-fno-analyzer-feasibilityโ this one's 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 with no feasible path get rejected. You can suppress that filtering with-fno-analyzer-feasibilitywhen you're debugging issues in this code ๐-fanalyzer-fine-grainedโ also for analyzer developers ๐ฆ Internally, the analyzer builds an "exploded graph" that combines control flow graphs with data flow information. By default, one edge in this graph can hold the effects of a run of multiple statements within a basic block. With-fanalyzer-fine-grained, every statement gets its own edge โจ-fanalyzer-show-duplicate-countโ another developer one ๐ง If several diagnostics are detected as duplicates of each other, this emits a note when reporting the best diagnostic, telling you how many additional diagnostics the deduplication logic suppressed ๐-fno-analyzer-state-mergeโ developer-only, babe ๐ By default, the analyzer simplifies things by merging sufficiently similar states at each program point while it builds the "exploded graph".-fno-analyzer-state-mergesuppresses that merging, which is handy for debugging state-handling issues ๐-fno-analyzer-state-purgeโ developer-only too ๐ธ By default, the analyzer purges aspects of state at a program point that seem no longer relevant, like the values of locals that aren't accessed later in the function and don't matter for leak analysis. With-fno-analyzer-state-purge, that purging gets suppressed, again for debugging state-handling issues ๐-fanalyzer-transitivityโ turns on transitivity of constraints within the analyzer ๐-fanalyzer-verbose-edgesโ for analyzer developers ๐ซถ It gives more verbose, lower-level detail in the descriptions of control flow within diagnostic paths ๐ฅ-fanalyzer-verbose-state-changesโ developer-facing too ๐ This one gives more verbose, lower-level detail in the descriptions of events related to state machines within diagnostic paths โจ-fanalyzer-verbosity=levelโ controls how complex the control flow paths are that get emitted for analyzer diagnostics ๐ง
okay so the analyzer has five verbosity levels, and your level can be one of these ๐
0โ the baseline ๐ฆ you get interprocedural call and return events (the stuff that jumps between functions), plus the most important state changes for a diagnostic. For example, for a double-free diagnostic, both calls tofreeget shown.1โ everything from level 0, plus events for entering each function โจ2โ everything from level 1, plus control-flow events that matter for triggering the issue, like "true path taken" at a conditional ๐ง This level is the default. bestie, you don't have to do anything for this one.3โ everything from level 2, but now you get all the control-flow events, not just the significant ones ๐4โ this one is built for analyzer developers ๐ฅ It adds a bunch of extra events meant for debugging the analyzer itself.
-fdump-analyzerโ dumps internal details about what the analyzer is up to intofile.analyzer.txt. Heads up,-fdump-analyzer-stderroverrides this one ๐-fdump-analyzer-stderrโ same deal, but the dump goes to stderr instead ๐ This one overrides-fdump-analyzer.-fdump-analyzer-callgraphโ dumps a call graph you can view with GraphViz, saved tofile.callgraph.dot๐ธ-fdump-analyzer-exploded-graphโ dumps the "exploded graph" for GraphViz, saved tofile.eg.dot. The nodes are color-coded by state-machine states so state changes pop ๐-fdump-analyzer-exploded-nodesโ emits diagnostics showing where the nodes in the "exploded graph" sit relative to your program's source โจ-fdump-analyzer-exploded-nodes-2โ dumps a textual version of the "exploded graph" tofile.eg.txt๐-fdump-analyzer-exploded-nodes-3โ dumps a textual version of the "exploded graph," but one dump file per node, namedfile.eg-id.txt๐ญ Expect a lot of files.-fdump-analyzer-exploded-pathsโ dumps a textual "exploded path" for each diagnostic intofile.idx.kind.epath.txt๐ฆ-fdump-analyzer-feasibilityโ dumps internal details about how the analyzer searches for feasible paths. It's written so you can view it with GraphViz, in files namedfile.*.fg.dotandfile.*.tg.dot๐ง-fdump-analyzer-jsonโ dumps a compressed JSON version of the analyzer's internals tofile.analyzer.json.gz๐ The precise format is subject to change, so don't build anything permanent on it yet.-fdump-analyzer-state-purgeโ same vibe as-fdump-analyzer-supergraph(it dumps a "supergraph" for GraphViz), but this one annotates the graph with what state gets purged at each node. It's written tofile.state-purge.dot๐ฅ-fdump-analyzer-supergraphโ dumps representations of the "supergraph" for GraphViz, saved tofile.supergraph.dotandfile.supergraph-eg.dot. These show every control-flow graph in the program, with interprocedural edges for calls and returns ๐ The second dump has annotations showing nodes in the "exploded graph" and any diagnostics tied to them.
โจ Options for Debugging Your Program โจ
okay bestie, if you want GCC to emit extra info for a debugger, you almost always just need to add -g to your other options ๐ซถ Some debug formats can co-exist (like DWARF with CTF) as long as you enable each one explicitly with its own command-line option.
GCC lets you use -g with -O. Fair warning though, optimized code takes some lowkey surprising shortcuts ๐ some variables you declared might not exist at all, flow of control may briefly jump somewhere you didn't expect, some statements may not run because they compute constant results or their values are already on hand, and some statements may run in different places because they got moved out of loops. Still, it is possible to debug optimized output ๐ which makes it reasonable to use the optimizer for programs that might have bugs.
If you aren't using some other optimization option, consider -Og with -g ๐ With no -O option at all, some compiler passes that collect debugging-friendly info don't run, so -Og may give you a better debugging experience.
-gโ produces debugging info in the operating system's native format (stabs, COFF, XCOFF, or DWARF) ๐ GDB can work with this info. On most systems that use stabs,-gturns on extra debugging info that only GDB can use. Those extras make debugging in GDB better, but they'll probably make other debuggers crash or refuse to read the program ๐ญ If you want to be certain which extra info gets generated, use-gstabs+,-gstabs,-gxcoff+,-gxcoff, or-gvms(more on those below).-ggdbโ produces debugging info for GDB ๐ฅ It uses the most expressive format available (DWARF, stabs, or the native format if neither of those is supported), including GDB extensions whenever possible.-gdwarf,-gdwarf-versionโ produces debugging info in DWARF format (if supported) ๐ฆ The version can be 2, 3, 4 or 5. The default is 5 for most targets, except VxWorks, TPF and Darwin/Mac OS X, which default to version 2, and AIX, which defaults to version 4.
Heads up: with DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables. Version 4 may need GDB 7.0 and -fvar-tracking-assignments for maximum benefit, and version 5 needs GDB 8.0 or higher.
GCC no longer supports DWARF Version 1, which is substantially different from Version 2 and later. For historical reasons, some other DWARF-related options such as -fno-dwarf2-cfi-asm) still have 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 info can be generated alongside DWARF when both formats are enabled explicitly through their own command-line options.-gctf,-gctflevelโ requests CTF debug info, where level sets how much CTF info gets produced โจ If you write-gctfwithout a value for level, the default level is 2. CTF info can be generated alongside DWARF when both are enabled explicitly through their own options.- Level 0 produces no CTF debug info at all, so
-gctf0negates-gctf๐ - Level 1 produces CTF info for tracebacks only. This includes callsite info but not type info.
- Level 2 produces type info for entities (functions, data objects etc.) at file scope or global scope only.
- Level 0 produces no CTF debug info at all, so
-gstabsโ produces debugging info in stabs format (if supported), without GDB extensions ๐ง This is the format DBX uses on most BSD systems. On MIPS, Alpha and System V Release 4 systems, this option produces stabs output that DBX doesn't understand. On System V Release 4 systems, this option requires the GNU assembler.-gstabs+โ produces debugging info in stabs format (if supported), using GNU extensions that only the GNU debugger (GDB) understands ๐ Using these extensions will likely make other debuggers crash or refuse to read the program.-gxcoffโ produces debugging info in XCOFF format (if supported) ๐ This is the format DBX uses on IBM RS/6000 systems.-gxcoff+โ produces debugging info in XCOFF format (if supported), using GNU extensions that only GDB understands ๐ฅ Using these extensions will likely make other debuggers crash or refuse to read the program, and may cause assemblers other than the GNU assembler (GAS) to fail with an error.-gvmsโ produces debugging info in Alpha/VMS debug format (if supported) ๐ This is the format DEBUG uses on Alpha/VMS systems.-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ requests debugging info and uses level to set 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 to make backtraces in parts of the program you don't plan to debug. This includes descriptions of functions and external variables, plus line number tables, but no info about local variables.
- Level 3 includes extra info, like all the macro definitions in the program. Some debuggers support macro expansion when you use
-g3๐ฆ
- Level 0 produces no debug info at all, so
If you use multiple -g options, with or without level numbers, the last one is the one that takes effect.
-gdwarf doesn't accept a concatenated debug level, to avoid confusion with -gdwarf-level. Instead, use an additional -glevel option to change the debug level for DWARF โจ
-fno-eliminate-unused-debug-symbolsโ by default, no debug info is produced for symbols that aren't actually used. Use this option if you want debug info for all symbols ๐ซถ-femit-class-debug-alwaysโ instead of emitting debugging info for a C++ class in only one object file, this emits it in every object file that uses the class ๐ Only use this with debuggers that can't handle how GCC normally emits class debug info. Using this option increases the size of the debugging info by as much as a factor of two, so it's a lot ๐ญ-fno-merge-debug-stringsโ tells the linker not to merge strings in the debugging info that are identical across different object files ๐ธ Merging isn't supported by all assemblers or linkers. It shrinks the debug info in the output file but costs more link processing time. Merging is enabled by default, so you only need this if you want it off.-fdebug-prefix-map=old=new๐บ๏ธ โ okay so when you compile files living in directoryold, GCC records their debug info as if they lived innewinstead. This is perfect 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.for new. It can give you more reproducible, location-independent builds, but you might need an extra command to tell GDB where to find the source files. See also-ffile-prefix-map. ๐-fvar-tracking๐ โ runs the variable tracking pass, which works out where variables are stored at each position in the code. Better debug info gets generated (if your debug format supports it) โจ- Lowkey on by default when you compile with optimization (
-Os,-O,-O2, ...) and debug info (-g), as long as the debug info format supports it. ๐ธ
- Lowkey on by default when you compile with optimization (
-fvar-tracking-assignments๐ โ annotates assignments to user variables early in compilation, then tries to carry those annotations all the way to the end to improve debug info while optimizing. Using-gdwarf-4alongside it is recommended ๐ซถ- It can be enabled even when var-tracking is disabled. In that case the annotations get created and maintained, but thrown away at the end.
- By default this rides along with
-fvar-tracking, except when selective scheduling is enabled. ๐
-gsplit-dwarf๐ง โ if DWARF debug info is enabled, it separates as much of it as possible into a separate output file with the extension.dwo. This lets your build system skip linking files that carry debug info. To be useful, you need a debugger that can read.dwofiles. ๐ฆ-gdwarf32,-gdwarf64๐ โ if DWARF debug info is enabled,-gdwarf32picks the 32-bit DWARF format and-gdwarf64picks the 64-bit one. The default depends on the target, but on most targets it's-gdwarf32. 32-bit is smaller, but it can't handle more than 2GiB of debug info in any of the DWARF debug info sections. 64-bit allows bigger debug info, but not every consumer supports it well yet ๐-gdescribe-dies๐ โ adds description attributes to some DWARF DIEs that have no name attribute, like artificial variables, external references, and call site parameter DIEs.-gpubnames๐ โ generates the DWARF.debug_pubnamesand.debug_pubtypessections.-ggnu-pubnames๐ โ generates.debug_pubnamesand.debug_pubtypesin a format that's suitable for converting into a GDB index. This is only useful with a linker that can produce GDB index version 7 ๐ซง-fdebug-types-section๐ง โ when you're using DWARF Version 4 or higher, type DIEs can get their own.debug_typessection instead of living in.debug_info. It's more efficient in a separate comdat section, since the linker can then remove duplicates. BUT not all DWARF consumers support.debug_typesyet, and on some objects it makes the debug info bigger instead of smaller ๐ญ-grecord-gcc-switches,-gno-record-gcc-switches๐ โ makes the command-line options that might affect code generation get appended to theDW_AT_producerattribute in DWARF debug info. They're joined with spaces, separating them from each other and from the compiler version. It's enabled by default. See also-frecord-gcc-switchesfor another way to store compiler options in the object file. โจ-gstrict-dwarf๐ซ โ disallows using extensions from a later DWARF standard version than the one you picked with-gdwarf-version. On most targets, using non-conflicting extensions from later versions is allowed anyway ๐-gno-strict-dwarf๐๏ธ โ allows using extensions from a later DWARF standard version than the one you picked with-gdwarf-version.-gas-loc-support๐ โ tells the compiler that the assembler supports.locdirectives. The compiler can then use them so the assembler generates DWARF2+ line number tables. This is generally desirable, because assembler-generated line-number tables are way more compact than the ones the compiler makes itself. It's enabled by default if, at GCC configure time, the assembler was found to support those directives. ๐ฆ-gno-as-loc-support๐ โ forces GCC to generate DWARF2+ line number tables internally, if DWARF2+ line number tables are going to be generated at all.-gas-locview-support๐ โ tells the compiler that the assembler supports "view" assignment and reset assertion checking in.locdirectives. It's enabled by default if, at GCC configure time, the assembler was found to support them.-gno-as-locview-support๐ง โ forces GCC to assign view numbers internally, if-gvariable-location-viewshas been explicitly requested.-gcolumn-info,-gno-column-info๐ โ emits location column information into DWARF debug info, not just file and line. It's enabled by default. ๐ซถ-gstatement-frontiers,-gno-statement-frontiers๐ฉ โ makes GCC create markers in the internal representation at the beginning of statements, and keep them roughly in place throughout compilation. Those markers guide the output of "is_stmt" markers in the line number table. It's enabled by default when you compile with optimization (-Os,-O1,-O2, ...) and output DWARF 2 debug info at the normal level ๐ฅ-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-views๐ธ โ augments variable location lists with progressive view numbers implied from the line number table. This lets debug info consumers inspect state at certain points of 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 will emit the line number table itself, which makes it somewhat less compact. The augmented line number tables and location lists are fully backward-compatible, so consumers that don't know about these augmentations can still read them, but they won't get any benefit from them either.- Default: this is enabled when outputting DWARF 2 debug info at the normal level, as long as there's assembler support,
-fvar-tracking-assignmentsis enabled, and-gstrict-dwarfis not. Without assembler support it may still be enabled, but that forces GCC to output internal line number tables. And if-ginternal-reset-location-viewsisn't enabled, that will most certainly lead to silently mismatching location views. ๐ฑ - There's a proposed representation for view numbers that is not backward compatible with the location list format introduced in DWARF 5. You can enable it with
-gvariable-location-views=incompat5. ๐งช
- Default: this is enabled when outputting DWARF 2 debug info at the normal level, as long as there's assembler support,
โ ๏ธ Heads up bestie: -gvariable-location-views=incompat5 may be removed in the future, and it's only provided as a reference implementation of the proposed representation. Debug info consumers aren't expected to support this extended format, and they'd be rendered unable to decode location lists that use it. ๐
-ginternal-reset-location-views,-gno-internal-reset-location-views๐งฉ โ attempts to determine which location views can be left out of location view lists. This requires 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". This is only enabled on ports that define a reliable estimation function. ๐ซ-ginline-points,-gno-inline-pointsโจ โ generates extended debug info for inlined functions. Location view tracking markers get inserted at inlined entry points, so address and view numbers can be computed and output in the debug info. This can be enabled independently of location views, in which case the view numbers won't be output. It can only be enabled along with statement frontiers, and it's only enabled by default if location views are enabled. ๐ง-gz[=type]๐๏ธ โ produces compressed debug sections in DWARF format, if that's supported. If type isn't given, the default depends on what the assembler and linker can do. type may be one of:noneโ don't compress debug sectionszlibโ use zlib compression in ELF gABI formatzlib-gnuโ use zlib compression in traditional GNU format
If the linker doesn't support writing compressed debug sections, the option gets rejected. Otherwise, if the assembler doesn't support them, -gz is silently ignored when producing object files. ๐คทโโ๏ธ
-femit-struct-debug-baseonly๐ฏ โ emits debug info for struct-like types only when the base name of the compilation source file matches the base name of the file where the struct is defined. This substantially reduces the size of debug info, but there's a significant potential loss in type information for the debugger. See-femit-struct-debug-reducedfor a less aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option works only with DWARF debug output. ๐ท-femit-struct-debug-reduced๐ฟ โ emits debug info for struct-like types only when the base name of the compilation source file matches the base name of the file where the type is defined, unless the struct is a template or defined in a system header. It significantly reduces the size of debug info, with some potential loss in type information for the debugger. See-femit-struct-debug-baseonlyfor a more aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option works only with DWARF debug output. ๐-femit-struct-debug-detailed[=spec-list]๐ โ specifies the struct-like types that the compiler generates debug info for. The goal is to cut down on duplicate struct debug info between different object files within the same program. ๐ซถ
okay so this one is literally the detailed version of -femit-struct-debug-reduced and -femit-struct-debug-baseonly ๐
those two handle most needs, but this is the extra-fancy control panel for when you want to fine-tune which structs get debug info โจ
A specification has the 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 counts as used directly when it's the type of a variable, member. Indirect uses happen through pointers to structs. So 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 ๐ For 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 come from, so the compiler knows which ones should get debug info ๐ none and any mean what you'd expect. base means the base name of the file where the type is declared has to match the base name of the main compilation file. In real life, that means when you compile foo.c, debug info is generated for types declared in that file and foo.h, but not other header files ๐ sys means those types satisfying base or declared in system or compiler headers.
You may need to experiment to find the best settings for your app ๐ง
The default is -femit-struct-debug-detailed=all.
This option works only with DWARF debug output โ ๏ธ
-fno-dwarf2-cfi-asmโ Emits DWARF unwind info as a compiler-generated".eh_frame"section, instead of using GAS".cfi_*"directives. Bestie, it's giving "do it the compiler's way" ๐-fno-eliminate-unused-debug-typesโ Normally, when producing DWARF output, GCC skips debug symbols for types that are nowhere used in the source file being compiled ๐งน Sometimes you actually want debugging info for every type declared in a compilation unit, even unused ones. For example, if you want to cast a value to a type that's declared but never actually used in your program, in the debugger ๐ The catch? It often results in a significant amount of wasted space ๐ญ
โจ Options That Control Optimization โจ
These options control various sorts of optimizations ๐ฅ
Without any optimization option, the compiler's goal is to reduce the cost of compilation and make debugging produce the expected results ๐ Statements are independent: if you stop the program at a breakpoint between statements, you can assign a new value to any variable or change the program counter to any other statement in the function, and get exactly the results you expect from the source code. Iconic behavior, honestly ๐
Turning on optimization flags makes the compiler try to improve performance and/or code size, at the expense of compilation time and possibly your ability to debug the program ๐ The compiler optimizes based on what it knows about the program. Compiling multiple files at once to a single output file lets the compiler use information gained from all of the files when compiling each of them ๐ง
Not every optimization is controlled directly by a flag. Only optimizations that have a flag are listed in this section ๐ฆ
Most optimizations are completely disabled at -O0, or if an -O level isn't set on the command line, even if individual optimization flags are specified ๐ Similarly, -Og suppresses many optimization passes.
Depending on the target and how GCC was configured, a slightly different set of optimizations may be enabled at each -O level than the ones listed here. To find out the exact set enabled at each level, invoke GCC with -Q --help=optimizers ๐
โจ -O, -O1 โจ
Optimize ๐ธ Optimizing compilation takes somewhat more time, and a lot more memory for a large function.
With -O, the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time ๐
-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 โจ
Optimize even more ๐ฅ GCC performs nearly all supported optimizations that don't involve a space-speed tradeoff. Compared to -O, this option increases both compilation time and the performance of the 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: please note the warning under-fgcseabout invoking-O2on programs that use computed gotos โ ๏ธ
โจ -O3 โจ
Optimize yet more ๐ -O3 turns on all optimizations specified by -O2, and also turns on 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 โจ
Reduce compilation time and make debugging produce the expected results ๐ง This is the default ๐
โจ -Os โจ
Optimize for size ๐ -Os enables all -O2 optimizations except those that often increase code size:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, makes the compiler tune for code size rather than execution speed, and performs further optimizations designed to reduce code size ๐ซถ
โจ -Ofast โจ
Disregard strict standards compliance ๐
-Ofast enables all -O3 optimizations. It also enables optimizations that aren't valid for all standard-compliant programs.
Be careful with this one ๐ 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 โจ
Optimize the debugging experience ๐ -Og should be the optimization level of choice for the standard edit-compile-debug cycle ๐ It offers a reasonable level of optimization while keeping compilation fast and the debugging experience good. It's a better choice than -O0 for producing 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 controlling them have no effect. Otherwise, -Og enables all -O1 optimization flags except for those that may interfere with debugging:
-fbranch-count-reg -fdelayed-branch -fdse -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fmove-loop-stores -fssa-phiopt
-ftree-bit-ccp -ftree-dse -ftree-pta -ftree-sra
โจ -Oz โจ
Optimize aggressively for size rather than speed ๐ฆ This may increase the number of instructions executed if those instructions require fewer bytes to encode. -Oz behaves similarly to -Os, including enabling most -O2 optimizations.
If you use multiple -O options, with or without level numbers, the last one is the one that takes effect ๐
Options of the form -fflag specify machine-independent flags ๐ธ Most flags have both positive and negative forms; the negative form of -ffoo is -fno-foo. In the table below, only one of the forms is listed (the one you typically use). You can figure out the other form by either removing no- or adding it ๐งฉ
The following options control specific optimizations. They're either activated by -O options or related to ones that are. You can use these flags in the rare cases when "fine-tuning" of the optimizations to be performed is desired ๐ง
-fno-defer-popโ For machines that must pop arguments after a function call, this always pops the arguments as soon as each function returns. At levels-O1and higher,-fdefer-popis the default, which lets the compiler let arguments pile up on the stack for several function calls and 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 are performed and the second is scheduled after loop unrolling ๐ฆ
This option is enabled by default at optimization levels -O1, -O2, -O3, -Os.
-ffp-contract=styleโ okay so this one decides whether the compiler is allowed to squish floating-point math together ๐งฎโจ-ffp-contract=offflat out disables expression contraction ๐ โโ๏ธ-ffp-contract=fastturns it on so things like fused multiply-add operations can get formed, but only if the target has native support for them ๐ฅ-ffp-contract=onturns it on only if the language standard allows it ๐ but bestie, this one isn't actually implemented yet ๐ so it's treated exactly the same as-ffp-contract=off. The default is-ffp-contract=fast๐-fomit-frame-pointerโ omit the frame pointer in functions that don't actually need one ๐ฆ this skips all the work of saving, setting up, and restoring the frame pointer, and on lots of targets it also frees up an extra register for you โจ on some targets it does nothing, because the standard calling sequence always uses a frame pointer, so it can't be left out ๐ also,-fno-omit-frame-pointerdoesn't guarantee the frame pointer gets used in every function, since several targets always omit it in leaf functions ๐ enabled by default at-O1and higher ๐-foptimize-sibling-callsโ optimizes sibling and tail recursive calls ๐ enabled at levels-O2,-O3,-Os๐ธ-foptimize-strlenโ glow-up time ๐ this optimizes various standard C string functions (like"strlen","strchr"or"strcpy") and their"_FORTIFY_SOURCE"counterparts into faster alternatives ๐ enabled at levels-O2,-O3โญ-fno-inlineโ no inlining for you, unless the function has thealways_inlineattribute ๐ this is the default when you aren't optimizing ๐ and if you want to exempt a single function from inlining, just mark it with thenoinlineattribute ๐ซถ-finline-small-functionsโ integrates functions into their callers when their body is smaller than the code for the function call itself, so the overall program gets smaller ๐ง the compiler heuristically decides which functions are simple enough to be worth it, and this applies to all functions, even the ones not declaredinline๐ enabled at levels-O2,-O3,-Osโจ-findirect-inliningโ inlines indirect calls that are discovered to be known at compile time, thanks to earlier inlining ๐ช this only does anything if inlining is turned on by-finline-functionsor-finline-small-functions๐ enabled at levels-O2,-O3,-Os๐-finline-functionsโ considers all functions for inlining, even if they aren't declaredinline๐ the compiler heuristically picks which ones are worth it ๐ง if every call to a given function gets integrated and the function is declaredstatic, then it usually won't be output as assembler code on its own ๐ซง enabled at levels-O2,-O3,-Os, and also enabled by-fprofile-useand-fauto-profile๐ฅ-finline-functions-called-onceโ considers allstaticfunctions called exactly once for inlining into their caller, even if they aren't markedinline๐ if that call gets integrated, the function isn't output as assembler code by itself ๐ฆ enabled at levels-O1,-O2,-O3and-Os, but not-Og๐-fearly-inliningโ inlines functions markedalways_inline, plus any functions whose body seems smaller than the call overhead, early on, before the-fprofile-generateinstrumentation and the real inlining pass ๐ง doing it this way makes profiling way cheaper and usually makes inlining faster in programs with big chains of nested wrapper functions ๐ enabled by default ๐-fipa-sraโ does interprocedural scalar replacement of aggregates ๐งฉ it also removes unused parameters and swaps parameters passed by reference for parameters passed by value ๐ enabled at levels-O2,-O3and-Os๐ธ-finline-limit=nโ by default GCC limits how big a function can be and still get inlined, and this flag gives you coarse control over that limit ๐๏ธnis the size of functions that can be inlined, measured in pseudo instructions ๐ inlining is actually controlled by a bunch of parameters, which you can set one at a time with--param name=value, and-finline-limit=nsets some of them like this:max-inline-insns-singleis set ton/2max-inline-insns-autois set ton/2
See below for documentation on the individual inlining parameters and their defaults ๐
Note: there may be no value to -finline-limit that results in default behavior ๐คทโโ๏ธ Note: a pseudo instruction, in this context, is just an abstract measurement of a function's size ๐ซ it in no way represents a count of assembly instructions, and its exact meaning might change from one release to another ๐
-fno-keep-inline-dllexportโ this is a more fine-grained version of-fkeep-inline-functions๐ it only applies to functions declared with thedllexportattribute or declspec ๐ฏ-fkeep-inline-functionsโ in C, it emitsstaticfunctions that are declaredinlineinto the object file, even if they've been inlined into all of their callers ๐ฆ this switch doesn't affect 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 they're never used ๐๏ธ no notes, just vibes ๐ท-fkeep-static-constsโ emits variables declaredstatic constwhen optimization isn't turned on, even if they aren't referenced ๐ GCC enables this by default ๐ฅฐ if you want the compiler to check whether a variable is referenced no matter what optimization is doing, use the-fno-keep-static-constsoption ๐ซถ-fmerge-constantsโ attempts to merge identical constants (string constants and floating-point constants) across compilation units ๐งฒ this is the default for optimized compilation if the assembler and linker support it โจ use-fno-merge-constantsto stop it ๐ enabled at levels-O1,-O2,-O3,-Os๐-fmerge-all-constantsโ attempts to merge identical constants and identical variables ๐ซจ this implies-fmerge-constants, and on top of that it considers things like constant initialized arrays or initialized constant variables with integral or floating-point types ๐งฎ
Warning, bestie ๐ C and C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations, so using -fmerge-all-constants results in non-conforming behavior ๐จ
-fmodulo-schedโ performs 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โ more aggressive SMS-based modulo scheduling, with register moves allowed ๐๏ธ setting this flag deletes certain anti-dependence edges, which triggers the generation of reg-moves based on life-range analysis ๐ง it's only effective when-fmodulo-schedis enabled ๐-fno-branch-count-regโ disables the optimization pass that hunts for chances to use "decrement and branch" instructions on a count register, instead of sequences that decrement a register, compare it to zero, and then branch based on the result ๐ this only matters on architectures that support those instructions, which include x86, PowerPC, IA-64 and S/390 ๐ฅ๏ธ note that-fno-branch-count-regdoesn't remove decrement and branch instructions that other optimization passes already put in the instruction stream ๐ซ the default is-fbranch-count-regat-O1and higher, except for-Og๐-fno-function-cseโ does not put function addresses in registers, so each instruction that calls a constant function contains the function's address explicitly ๐ this makes less efficient code, but some strange hacks that alter the assembler output can get confused by the optimizations you get when this option isn't used ๐ the default is-ffunction-cse
-fno-zero-initialized-in-bssโ if the target supports a BSS section, GCC puts variables that are initialized to zero into BSS by default, which can save space in the resulting code ๐พ this option turns that off, because some programs explicitly rely on variables going into the data section ๐ฅบ for example, so the executable can find the beginning of that section, or make assumptions based on it ๐งญ the default is-fzero-initialized-in-bss๐ธ-fthread-jumpsโ performs optimizations that check whether a jump branches to a location where another comparison subsumed by the first one is found ๐งต if so, the first branch gets redirected to either the destination of the second branch or a point right after it, depending on whether the condition is known to be true or false ๐ฆ enabled at levels-O1,-O2,-O3,-Osโจ-fsplit-wide-typesโ when using a type that takes up multiple registers, likelong longon a 32-bit system, this splits the registers apart and allocates them independently ๐งฉ this usually generates better code for those types, but it may make debugging more difficult ๐ enabled at levels-O1,-O2,-O3,-Os๐-fsplit-wide-types-earlyโ fully splits wide types early, instead of very late ๐ฐ๏ธ this option has no effect unless-fsplit-wide-typesis turned on ๐ it's the default on some targets ๐-fcse-follow-jumpsโ during common subexpression elimination (CSE), scans through jump instructions when the target of the jump isn't reached by any other path ๐ต๏ธ for example, when CSE encounters anifstatement with anelseclause, it follows the jump when the tested condition is false ๐ช enabled at levels-O2,-O3,-Os๐ท-fcse-skip-blocksโ similar to-fcse-follow-jumps, but this one makes CSE follow jumps that conditionally skip over blocks ๐ฆ when CSE hits a simpleifstatement with noelseclause,-fcse-skip-blocksmakes it follow 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 have been performed ๐ enabled at levels-O2,-O3,-Os๐-fgcseโ okay so this one runs a global common subexpression elimination pass ๐ง โจ. It also handles global constant and copy propagation, which is giving main character energy ๐. It turns on at-O2,-O3, and-Os๐ .
Note: when you're compiling a program that uses computed gotos (a GCC extension) ๐, you might get better run-time performance if you turn off the global common subexpression elimination pass by adding -fno-gcse to your command line. Bestie, test it and see ๐.
-fgcse-lmโ when this is on, global common subexpression elimination tries to move loads that only get killed by stores back into themselves ๐ธ. That means a loop with a load/store sequence can become a load outside the loop and a copy/store inside it. Lowkey genius ๐ง. It's enabled by default whenever-fgcseis enabled.-fgcse-smโ this runs a store motion pass right after global common subexpression elimination ๐ฆ. It tries to yeet stores out of loops. Team it up with-fgcse-lmand loops with a load/store sequence can turn into a load before the loop and a store after it ๐ฅ. Not enabled at any optimization level, so you have to ask for it ๐ซถ.-fgcse-lasโ with this on, the global common subexpression elimination pass cleans up redundant loads that show up after stores to the same memory location, covering both partial and full redundancies โจ. Also not enabled at any optimization level ๐.-fgcse-after-reloadโ this one runs a redundant load elimination pass after reload ๐งน. Its whole purpose is cleaning up redundant spilling. It's enabled by-O3,-fprofile-use, and-fauto-profile๐.-faggressive-loop-optimizationsโ the loop optimizer uses language constraints to figure out bounds for how many times a loop runs ๐. It assumes your loop code won't trigger undefined behavior, like signed integer overflows or out-of-bound array accesses ๐ญ. Those bounds then guide loop unrolling, loop peeling, and loop exit test optimizations. This option is enabled by default ๐ .
Heads up bestie: because this assumes no undefined behavior, code that does hit signed integer overflow or out-of-bound array accesses in a loop is not what this option is built for ๐.
-funconstrained-commonsโ this tells the compiler that variables declared in common blocks (think Fortran ๐ง) might get overridden later with longer trailing arrays ๐. It stops certain optimizations that rely on knowing the array bounds, so it's a bit of a buzzkill but it keeps things safe ๐ซถ.-fcrossjumpingโ this does a cross-jumping transformation ๐ฆ. It merges equivalent code together to save code size. The result might run better, or it might not, so it's a vibe check ๐คทโโ๏ธ. It turns on at-O2,-O3, and-Osโจ.-fauto-inc-decโ this combines increments or decrements of addresses with memory accesses ๐. The pass is always skipped on architectures that don't have instructions to support it. It's enabled by default at-O1and higher, but only on architectures that actually support it ๐ธ.-fdceโ this performs dead code elimination (DCE) on RTL ๐๏ธ. Bye bye useless code ๐ . It's enabled by default at-O1and higher.-fdseโ this performs dead store elimination (DSE) on RTL ๐งน. Stores that nobody reads get tossed. It's enabled by default at-O1and higher ๐ฅ.-fif-conversionโ this attempts to turn conditional jumps into branch-less equivalents โจ. It uses things like conditional moves, min, max, set flags, and abs instructions, plus some tricks you can do with standard arithmetic ๐ง . On chips that have conditional execution, that part is handled by-fif-conversion2. It's enabled at-O1,-O2,-O3, and-Os, but not with-Og๐ โโ๏ธ.-fif-conversion2โ this uses conditional execution (where your chip has it) to turn conditional jumps into branch-less equivalents ๐ฆ. It's enabled at-O1,-O2,-O3, and-Os, but not with-Og๐.-fdeclone-ctor-dtorโ okay so the C++ ABI needs multiple entry points for constructors and destructors ๐ง: one for a base subobject, one for a complete object, and one for a virtual destructor that callsoperator deleteafterwards ๐. With a hierarchy that has virtual bases, the base and complete variants end up as clones, which means two copies of the same function ๐ญ. With this option, those variants become thunks that call one common implementation instead ๐ . It's enabled by-Os๐.-fdelete-null-pointer-checksโ this assumes programs can't safely dereference null pointers, and that no code or data lives at address zero ๐. It turns on simple constant folding optimizations at all optimization levels ๐. Other GCC passes use this flag to run global dataflow analyses that delete useless null pointer checks. Those analyses assume that touching address zero always traps, 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 ๐. If your program depends on that behavior, use -fno-delete-null-pointer-checks to turn this optimization off.
This option is enabled by default on most targets ๐. On Nios II ELF, it defaults to off ๐. On AVR, CR16, and MSP430, it's completely disabled ๐ซ. Passes that use the dataflow information are enabled independently at different optimization levels ๐.
-fdevirtualizeโ this tries to convert calls to virtual functions into direct calls ๐ฆ. It happens both within a procedure and across procedures, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp) โจ. It's enabled at-O2,-O3, and-Os๐ .-fdevirtualize-speculativelyโ this tries to convert virtual function calls into speculative direct calls ๐ฎ. It looks at the type inheritance graph to figure out the set of likely targets for a call ๐ง . If that set is small, ideally size 1, the call becomes a conditional that picks between a direct call and an indirect call ๐. These speculative calls unlock more optimizations, like inlining ๐ฅ. If they stop being useful after further optimization, they get converted back to their original form ๐.-fdevirtualize-at-ltransโ this streams extra info needed for aggressive devirtualization when the link-time optimizer runs in local transformation mode ๐. You get more devirtualization, but the amount of streamed data goes up a lot ๐ญ. Because of that, it's disabled by default ๐.-fexpensive-optimizationsโ this performs a bunch of minor optimizations that are relatively expensive to run ๐ธ. It's enabled at-O2,-O3, and-Os๐ธ.-freeโ this tries to remove redundant extension instructions โ๏ธ. It's especially helpful on the x86-64 architecture, which implicitly zero-extends 64-bit registers after writing to their lower 32-bit half ๐ง. It's enabled for Alpha, AArch64, and x86 at-O2,-O3, and-Os๐.-fno-lifetime-dseโ in C++, an object's value is only affected by changes made during its lifetime ๐ฆ. When the constructor begins, the object has an indeterminate value, and any changes made during its lifetime are dead once it's destroyed ๐. Normally dead store elimination takes advantage of that. But if your code relies on the object's storage value sticking around after the lifetime ends, use this flag to turn that optimization off ๐ซถ. If you want to keep stores made before the constructor starts (say youroperator newclears the object storage) but still treat the object as dead after the destructor, use-flifetime-dse=1๐. The default can be picked explicitly with-flifetime-dse=2๐.-flifetime-dse=0is the same as-fno-lifetime-dse๐.-flive-range-shrinkageโ this tries to cut down register pressure through register live range shrinkage ๐. It's especially helpful on fast processors with small or moderate-sized register sets ๐.-fira-algorithm=algorithmโ this picks the coloring algorithm for the integrated register allocator ๐จ. Thealgorithmcan bepriority, which is Chow's priority coloring, orCB, which is Chaitin-Briggs coloring ๐ง . Chaitin-Briggs isn't implemented for every architecture, but on targets that do support it, it's the default because it generates better code ๐ .-fira-region=regionโ this picks which regions the integrated register allocator uses ๐บ๏ธ. Theregionargument should be one of the following:allโ uses all loops as register allocation regions ๐. This can give the best results on machines with a small and/or irregular register set ๐ฅ.mixedโ uses all loops except loops with small register pressure as the regions โจ. This value usually gives the best results in most cases and for most architectures ๐. It's enabled by default when you compile with optimization for speed (-O,-O2, ...) ๐.oneโ uses all functions as a single region ๐งฉ. This typically gives the smallest code size, and it's enabled by default for-Osor-O0๐ธ.
-fira-hoist-pressureโ this uses IRA to evaluate register pressure in the code hoisting pass when deciding whether to hoist expressions ๐๏ธ. It usually gives smaller code, but it can slow the compiler down ๐ข. It's enabled at-Osfor all targets ๐.-fira-loop-pressureโ this uses IRA to evaluate register pressure in loops when deciding whether to move loop invariants ๐. On machines with large register files (>= 32 registers), it usually makes code faster and smaller ๐. The catch is it can slow the compiler down too ๐ซ . It's enabled at-O3for some targets โจ.-fno-ira-share-save-slotsโ this turns off sharing of stack slots used for saving call-used hard registers that live through a call ๐ โโ๏ธ. Every hard register gets its own stack slot, so function stack frames end up bigger ๐ฆ.-fno-ira-share-spill-slotsโ this turns off sharing of stack slots allocated for pseudo-registers ๐ โโ๏ธ. Each pseudo-register that doesn't get a hard register gets its own stack slot, so yep, function stack frames get bigger too ๐ฆ๐.-flra-rematโ this enables CFG-sensitive rematerialization in LRA ๐งช. Instead of loading the values of spilled pseudos, LRA tries to rematerialize (recalculate) them when that's profitable ๐ง . It's enabled at-O2,-O3, and-Os๐ .-fdelayed-branchโ if your target machine supports it, this tries to reorder instructions so they fill the instruction slots available after delayed branch instructions ๐ฆ. It's enabled at-O1,-O2,-O3, and-Os, but not at-Og๐ โโ๏ธ.-fschedule-insnsโ okay bestie, if the target machine supports it, GCC will try to reshuffle instructions so the CPU stops stalling while it waits for data ๐ซถ this is a lifesaver on machines with slow floating point or memory load instructions, because other stuff can get issued while the load or float op is still cooking. Enabled at levels-O2,-O3๐-fschedule-insns2โ this is giving-fschedule-insnsbut with an extra pass of instruction scheduling that runs after register allocation is done ๐ฅ it's especially iconic on machines with a relatively small number of registers where memory load instructions take more than one cycle. Enabled at levels-O2,-O3,-Os๐ฆ-fno-sched-interblockโ the vibe here is no scheduling across basic blocks ๐ โโ๏ธ normally this is on when scheduling happens before register allocation, so basically with-fschedule-insnsor at-O2or higher.-fno-sched-specโ shutting down speculative motion of non-load instructions ๐ซ this is normally on when scheduling happens before register allocation, so with-fschedule-insnsor at-O2or higher.-fsched-pressureโ main character energy ๐ this turns on register pressure sensitive insn scheduling before register allocation. It only makes sense when that pre-allocation scheduling is on, so with-fschedule-insnsor at-O2or higher. It can make the generated code better and smaller by stopping register pressure from climbing above the number of available hard registers, which means fewer nasty spills during register allocation ๐ธ-fsched-spec-loadโ allows speculative motion of some load instructions ๐ง this only makes sense when scheduling before register allocation, so with-fschedule-insnsor at-O2or higher.-fsched-spec-load-dangerousโ ngl this one is spicy ๐ถ๏ธ it allows speculative motion of more load instructions. Same deal, it only makes sense when scheduling before register allocation, so with-fschedule-insnsor at-O2or higher. ๐-fsched-stalled-insns,-fsched-stalled-insns=nโ this controls how many insns (if any) can get moved early from the queue of stalled insns into the ready list during the second scheduling pass ๐-fno-sched-stalled-insnsmeans nothing gets moved early,-fsched-stalled-insns=0means there's no limit on how many queued insns can jump the line, and-fsched-stalled-insnswith no value is the same as-fsched-stalled-insns=1โจ-fsched-stalled-insns-dep,-fsched-stalled-insns-dep=nโ this sets how many insn groups (cycles) get checked for a dependency on a stalled insn that's a candidate for being pulled out early ๐ it only has an effect during the second scheduling pass, and only if-fsched-stalled-insnsis being used.-fno-sched-stalled-insns-depis the same as-fsched-stalled-insns-dep=0, and-fsched-stalled-insns-depwith no value is the same as-fsched-stalled-insns-dep=1๐ฆ-fsched2-use-superblocksโ when scheduling after register allocation, this uses superblock scheduling ๐ that lets instructions move across basic block boundaries, which can give you faster schedules.
โ ๏ธ This one is experimental, because not all of the machine descriptions GCC uses model the CPU closely enough to avoid unreliable results from the algorithm. Be careful bestie ๐
It only makes sense when scheduling after register allocation, so with -fschedule-insns2 or at -O2 or higher.
-fsched-group-heuristicโ turns on the group heuristic in the scheduler ๐ it favors the instruction that belongs to a schedule group. It's enabled by default whenever scheduling is on, so with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-critical-path-heuristicโ enables the critical-path heuristic in the scheduler ๐ฃ๏ธ it favors instructions that sit on the critical path. Also on by default whenever scheduling is enabled, so with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-spec-insn-heuristicโ enables the speculative instruction heuristic in the scheduler ๐ฎ it favors speculative instructions with greater dependency weakness. On by default whenever scheduling is enabled, so with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-rank-heuristicโ enables the rank heuristic in the scheduler ๐ it favors instructions that belong to a basic block with greater size or frequency. On by default whenever scheduling is enabled, so with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-last-insn-heuristicโ enables the last-instruction heuristic in the scheduler ๐ซ it favors the instruction that is less dependent on the last instruction scheduled. On by default whenever scheduling is enabled, so with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-dep-count-heuristicโ enables the dependent-count heuristic in the scheduler ๐ it favors the instruction that has more instructions depending on it. On by default whenever scheduling is enabled, so with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-freschedule-modulo-scheduled-loopsโ modulo scheduling happens before the traditional scheduling ๐ if a loop got 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 ๐งฉ selective scheduling runs instead of the first scheduler pass.-fselective-scheduling2โ schedules instructions using the selective scheduling algorithm too ๐งฉ but this time it runs instead of the second scheduler pass.-fsel-sched-pipeliningโ enables software pipelining of innermost loops during selective scheduling ๐ this option does nothing unless-fselective-schedulingor-fselective-scheduling2is turned on.-fsel-sched-pipelining-outer-loopsโ when pipelining loops during selective scheduling, this also pipelines the outer loops ๐ it does nothing unless-fsel-sched-pipeliningis turned on.-fsemantic-interpositionโ okay this one is deep ๐ซง some object formats, like ELF, let the dynamic linker interpose symbols. That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, since the function or variable might get swapped out. It's useful for things like rewriting memory allocation functions with a debugging implementation, but it's expensive for 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 vibe for variables: if interposition happens, the constructor of the variable will be the same. This flag has no effect on functions explicitly declaredinline, where interposition is never allowed to change semantics, and it has no effect on symbols explicitly declared weak ๐ฆ-fshrink-wrapโ emits function prologues only before the parts of the function that actually need them, instead of at the top of the function ๐ this is enabled by default at-Oand higher.-fshrink-wrap-separateโ shrink-wraps the parts of the prologue and epilogue separately, so each part only runs when it's needed ๐ท this is on by default, but it does nothing unless-fshrink-wrapis also turned on and the target supports it.
-fcaller-savesโ enables allocation of values to registers that get clobbered by function calls ๐งบ GCC does this by emitting extra instructions to save and restore those registers around the calls. It only happens when it seems to give better code โจ
This option is always enabled by default on certain machines, usually the ones with no call-preserved registers to use instead ๐ Enabled at levels -O2, -O3, -Os.
-fcombine-stack-adjustmentsโ tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐ง enabled by default at-O1and higher.-fipa-raโ uses caller save registers for allocation if those registers aren't used by any called function ๐ง that means there's no need to save and restore them around calls. This is only possible if the called functions are part of the same compilation unit as the current function and they're compiled before it ๐ซถ enabled at levels-O2,-O3,-Os, but it gets disabled if the generated code will be instrumented for profiling (-p, or-pg), or if the callee's register usage can't be known exactly (this happens on targets that don't expose prologues and epilogues in RTL) ๐-fconserve-stackโ attempts to minimize stack usage, even if that makes the program slower ๐ข it uses less stack space on purpose. This option 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 ๐โโ๏ธ this tries to move the evaluation of expressions that run on all paths to the function exit as early as possible. It's especially useful as a code size optimization, but it often helps code speed too ๐ enabled by default at-O2and higher.-ftree-preโ performs partial redundancy elimination (PRE) on trees ๐งน enabled at-O2and-O3.-ftree-partial-preโ makes partial redundancy elimination (PRE) more aggressive ๐ค enabled at-O3.-ftree-forwpropโ performs forward propagation on trees โก๏ธ enabled by default at-O1and higher.-ftree-freโ performs full redundancy elimination (FRE) on trees ๐งฝ the difference between FRE and PRE is that FRE only considers expressions that are computed on all paths leading to the redundant computation. That makes the analysis 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 okay so this one speculatively hoists loads from both branches of an if-then-else ๐ธ but only when the loads grab adjacent locations in the same structure, and the target has a conditional move instruction โจ it's enabled by default at -O2 and higher ๐
-ftree-copy-prop bestie, this does copy propagation on trees ๐ฆ it gets rid of unnecessary copy operations (iconic behaviour, no cap) ๐ซถ enabled by default at -O1 and higher
-fipa-pure-const this one discovers which functions are pure or constant ๐ฎ enabled by default at -O1 and higher
-fipa-reference this discovers which static variables do not escape the compilation unit ๐ enabled by default at -O1 and higher
-fipa-reference-addressable this discovers read-only, write-only and non-addressable static variables ๐ง enabled by default at -O1 and higher
-fipa-stack-alignment it reduces stack alignment on call sites if possible ๐ enabled by default
-fipa-pta okay this is the big one ๐ญ it performs interprocedural pointer analysis and interprocedural modification and reference analysis ๐ฅ
heads up: this can cause excessive memory and compile-time usage on large compilation units ๐
it is not enabled by default at any optimization level ๐
-fipa-profile this performs interprocedural profile propagation ๐ functions called only from cold functions get marked as cold โ๏ธ functions executed once (like "cold", "noreturn", static constructors or destructors) are identified too โจ cold functions and loopless parts of functions executed once then get optimized for size ๐ enabled by default at -O1 and higher
-fipa-modref this performs interprocedural mod/ref analysis ๐ฆ it looks at the side effects of functions (memory locations that are modified or referenced) and enables better optimization across the function call boundary ๐ enabled by default at -O1 and higher
-fipa-cp this performs interprocedural constant propagation ๐ it figures out when values passed to functions are constants and optimizes accordingly ๐ซถ this can substantially increase performance if the app has constants passed to functions โญ enabled by default at -O2, -Os and -O3, and also enabled by -fprofile-use and -fauto-profile
-fipa-cp-clone this performs function cloning to make interprocedural constant propagation stronger ๐งฌ when enabled, it clones functions when an externally visible function can be called with constant arguments ๐ซง since this can create multiple copies of functions, it may significantly increase code size (see --param ipa-cp-unit-growth=value) ๐ enabled by default at -O3, and also enabled by -fprofile-use and -fauto-profile
-fipa-bit-cp when enabled, this performs interprocedural bitwise constant propagation ๐ธ enabled by default at -O2 and by -fprofile-use and -fauto-profile ๐
it requires that -fipa-cp is enabled โ ๏ธ
-fipa-vrp when enabled, this performs interprocedural propagation of value ranges ๐ enabled by default at -O2 ๐ it requires that -fipa-cp is enabled ๐ซถ
-fipa-icf this performs Identical Code Folding for functions and read-only variables ๐ช it reduces code size but may disturb unwind stacks by swapping a function for an equivalent one with a different name ๐ฌ it works more effectively with link-time optimization enabled โจ
okay so the Gold Linker has its own ICF optimization too, and it's similar, 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 this controls GCC's optimizations so the output is suitable for live-patching ๐ฉน
if the compiler's optimization uses a function's body (or info pulled from its body) to optimize or change another function, that latter function is called an impacted function of the former ๐ซง if a function gets patched, its impacted functions should be patched too ๐
impacted functions are decided by the compiler's interprocedural optimizations ๐ง for example, a caller is impacted when a function gets inlined into it, when a function is cloned and its caller is changed to call the new clone, or when function pureness/constness info is extracted to optimize its direct or indirect callers ๐
usually, the more IPA optimizations are enabled, the more impacted functions each function has ๐ so to control that number (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 includes inlining, cloning, interprocedural scalar replacement of aggregates and partial inlining ๐ท so when patching a function, all its callers and its clones' callers are impacted and need patching too ๐ฉท
-flive-patching=inline-clone disables the following optimization flags: -fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment -fipa-modref ๐ซ
inline-only-static only inlining of static functions is enabled ๐ช so when patching a static function, all its callers are impacted and need patching too ๐ซถ
on top of everything -flive-patching=inline-clone disables, -flive-patching=inline-only-static also disables these: -fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp ๐
โโ๏ธ
when -flive-patching is specified without any value, the default is inline-clone ๐
this flag is disabled by default ๐ค
heads up:-flive-patchingis not supported with link-time optimization (-flto) ๐จ
-fisolate-erroneous-paths-dereference this detects paths that trigger erroneous or undefined behaviour from dereferencing a null pointer ๐ต๏ธโโ๏ธ it isolates those paths from the main control flow and turns the statement into a trap ๐ชค enabled by default at -O2 and higher, and it depends on -fdelete-null-pointer-checks also being enabled ๐ฅบ
-fisolate-erroneous-paths-attribute this detects paths that trigger erroneous or undefined behaviour because a null value gets used in a way forbidden by a "returns_nonnull" or "nonnull" attribute ๐ โโ๏ธ it isolates those paths from the main control flow and turns the statement into a trap ๐ชค this is not currently enabled, but it may be enabled by -O2 in the future ๐ฎ
-ftree-sink this performs forward store motion on trees ๐ enabled by default at -O1 and higher ๐
-ftree-bit-ccp this performs sparse conditional bit constant propagation on trees and propagates pointer alignment info ๐ it only operates on local scalar variables ๐ฏ enabled by default at -O1 and higher, except for -Og, and it requires that -ftree-ccp is enabled ๐ซถ
-ftree-ccp this performs sparse conditional constant propagation (CCP) on trees ๐ง it only operates on local scalar variables ๐ enabled by default at -O1 and higher ๐
-fssa-backprop this propagates info about uses of a value up the definition chain to simplify the definitions ๐ for example, it strips sign operations if the sign of a value never matters ๐งผ enabled by default at -O1 and higher โจ
-fssa-phiopt this does pattern matching on SSA PHI nodes to optimize conditional code ๐งฉ enabled by default at -O1 and higher, except for -Og ๐ท
-ftree-switch-conversion this converts simple initializations in a switch into initializations from a scalar array ๐ช enabled by default at -O2 and higher ๐
-ftree-tail-merge this looks for identical code sequences ๐ฏโโ๏ธ 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 -O2 and higher ๐ซถ the compilation time in this pass can be limited with the max-tail-merge-comparisons parameter and the max-tail-merge-iterations parameter โฑ๏ธ
-ftree-dce this performs dead code elimination (DCE) on trees ๐งน enabled by default at -O1 and higher ๐
-ftree-builtin-call-dce this performs 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 -O2 and higher if -Os is not also specified ๐
-ffinite-loops this assumes that a loop with an exit will eventually take the exit and not loop forever ๐ that lets the compiler remove loops that otherwise have no side effects, without treating 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 this does 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 -O1 and higher โจ
-ftree-dse this performs dead store elimination (DSE) on trees ๐งฝ a dead store is a store into a memory location that gets overwritten by another store later, with no loads in between ๐ in that case the earlier store can be deleted ๐๏ธ enabled by default at -O1 and higher ๐
-ftree-ch this performs loop header copying on trees ๐ it's beneficial because it boosts the effectiveness of code motion optimizations ๐ it also saves one jump ๐ฆ enabled by default at -O1 and higher ๐ธ it is not enabled for -Os, since it usually increases code size ๐ โโ๏ธ
-ftree-loop-optimize this performs loop optimizations on trees ๐ enabled by default at -O1 and higher ๐
-ftree-loop-linear,-floop-strip-mine,-floop-blockโ Okay, these three are all doing the same job ๐ They do loop nest optimizations, exactly like-floop-nest-optimize. To actually use this, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure is switched on โจ-fgraphite-identityโ This one is lowkey a tester ๐ It turns on the identity transformation for Graphite. For every SCoP, GCC builds the polyhedral representation and then converts it back to GIMPLE. That lets you measure what the GIMPLE -> GRAPHITE -> GIMPLE round trip costs or gains you ๐ง isl's code generator also does some minimal cleanup along the way, like index splitting and dead code elimination in loops.-floop-nest-optimizeโ The isl-based loop nest optimizer, and it's giving main character energy ๐ It's a generic optimizer built on the Pluto algorithms, and it works out a loop structure tuned for data locality and parallelism ๐ฅ Heads up: this one is experimental โ ๏ธ-floop-parallelize-allโ Graphite's data dependence analysis hunts down loops that can be parallelized ๐ง It parallelizes every loop it can analyze as free of loop-carried dependences, and it does not check whether parallelizing is actually profitable first ๐-ftree-coalesce-varsโ When GCC is leaving SSA form, this flag tries to cut down on copying by merging versions of different user-defined variables, not just compiler temporaries ๐ฆ Quick warning, bestie: this can seriously limit your ability to debug an optimized program compiled with-fno-var-tracking-assignments๐ญ The negated form,-fno-tree-coalesce-vars, stops SSA coalescing of user variables. It's on by default when optimization is on, and it barely does anything otherwise ๐-ftree-loop-if-convertโ This one takes conditional jumps in the innermost loops and turns them into branch-less equivalents ๐ธ The goal is to get rid of control flow so the vectorizer can handle those loops better. It's enabled by default whenever vectorization is enabled ๐-ftree-loop-distributionโ Loop distribution, which can help cache performance on big loop bodies and open the door for things like parallelization or vectorization โจ Here's the Fortran 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
This flag is enabled by default at -O3. It's also turned on by -fprofile-use and -fauto-profile ๐ซถ
-ftree-loop-distribute-patternsโ This one distributes loops that can be code generated as calls into a library ๐ It's enabled by default at-O2and higher, and by-fprofile-useand-fauto-profile. It handles initialization loops and swaps them for a call to memset zero ๐งน Look at this:
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
and the initialization loop turns into a call to memset zero. This flag is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-floop-interchangeโ Loop interchange, happening outside of Graphite ๐ It can boost cache performance on a loop nest and make room for stuff like vectorization โจ Check out this C glow-up:
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];
becomes:
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's also enabled by -fprofile-use and -fauto-profile ๐ฆ
-floop-unroll-and-jamโ Unroll and jam on the feasible loops ๐ In a loop nest, it unrolls the outer loop by some factor and fuses the resulting multiple inner loops together. Enabled by default at-O3, and also by-fprofile-useand-fauto-profile๐ธ-ftree-loop-imโ Loop invariant motion on trees ๐ง It only moves the 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 the operands of invariant conditions out of the loop, so loop unswitching can get away with trivial invariance analysis ๐ง This pass also includes store motion ๐-ftree-loop-ivcanonโ Creates a canonical counter for the number of iterations in loops where figuring out the count needs complicated analysis ๐ Later optimizations can then work out the number easily. It's especially useful alongside unrolling โจ-ftree-scev-cpropโ Final value replacement, bestie ๐ If a variable changes in a loop in a way that its value on exit can be worked out from only its initial value and the number of iterations, GCC swaps uses of the final value for that computation, as long as it's cheap enough. That cuts down on data dependencies and can unlock more simplifications ๐ซถ Enabled by default at-O1and higher.-fivoptsโ Induction variable optimizations on trees, covering strength reduction, induction variable merging, and induction variable elimination ๐ฅ-ftree-parallelize-loops=nโ This splits a loop's iteration space so it runs across n threads ๐งต It only works for loops whose iterations are independent and can be reordered however. It's only really worth it on multiprocessor machines, and for CPU-intensive loops rather than ones held back by something like memory bandwidth ๐ This option implies-pthread, so it's only supported on targets that support-pthreadโจ-ftree-ptaโ Function-local points-to analysis on trees ๐ It's enabled by default at-O1and higher, except for-Og๐-ftree-sraโ Scalar replacement of aggregates ๐ฆ It swaps structure references out for scalars so structures don't get committed to memory too early ๐ง Enabled by default at-O1and higher, except for-Og๐ธ-fstore-mergingโ Merges narrow stores that hit consecutive memory addresses ๐งน It takes contiguous stores of immediate values that are narrower than a word and folds them into fewer, wider stores, so you get fewer instructions ๐ Enabled by default at-O2and higher, and at-Osโจ-ftree-terโ Temporary expression replacement during the SSA->normal phase ๐ Single use/single def temporaries get replaced at their use location by their defining expression. This makes non-GIMPLE code, but it gives the expanders much more complex trees to chew on, which leads to better RTL generation ๐ง Enabled by default at-O1and higher.-ftree-slsrโ Straight-line strength reduction on trees ๐ It spots related expressions involving multiplications and swaps them for cheaper calculations whenever it can ๐ Enabled by default at-O1and higher.-ftree-vectorizeโ Vectorization on trees, bestie ๐ฅ This flag turns on-ftree-loop-vectorizeand-ftree-slp-vectorizeas well, unless you've explicitly specified them ๐ซถ-ftree-loop-vectorizeโ Loop vectorization on trees โญ Enabled by default at-O2, and also by-ftree-vectorize,-fprofile-use, and-fauto-profile๐-ftree-slp-vectorizeโ Basic block vectorization on trees ๐ธ Enabled by default at-O2, and also by-ftree-vectorize,-fprofile-use, and-fauto-profile๐-ftrivial-auto-var-init=choiceโ This one is all about security and predictability ๐ It initializes automatic variables with either a pattern or zeroes, which protects against uninitialized memory being disclosed or used ๐ญ GCC still treats an automatic variable with no explicit initializer as uninitialized, so-Wuninitializedand-Wanalyzer-use-of-uninitialized-valuewill still warn about those ๐ With this option, GCC also zeroes any padding in automatic variables of structure or union types โจ
The three values of choice are:
uninitializedโ Doesn't initialize any automatic variables at all. This is the default for C and C++ ๐ฅฑpatternโ Fills automatic variables with values that will likely turn logic bugs into crashes down the line ๐ฅ They're easy to spot in a crash dump and aren't values programmers can rely on for real program semantics ๐งฉ The pattern is a byte-repeatable one using byte0xFE. The values used for pattern initialization might change in the future โ ๏ธzeroโ Initializes automatic variables with zeroes ๐ซง
The default is uninitialized ๐ท
You can control this behavior for a specific variable with the variable attribute uninitialized ๐
-fvect-cost-model=modelโ okay so this one lets you change the cost model for vectorization ๐ The model has to beunlimited,dynamic,cheaporvery-cheap. Withunlimited, the vectorized code path is just assumed to be profitable ๐ฅ Withdynamic, a runtime check guards the vectorized path so it only kicks in for iteration counts that will likely run faster than the original scalar loop โจcheapis the "no drama" option: 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 the same asdynamic๐ Andvery-cheaponly vectorizes if the vector code would entirely replace the scalar code being vectorized. For example, if each vectorized iteration can only handle exactly four iterations of the scalar loop,very-cheaponly allows it if the scalar iteration count is known to be a multiple of four ๐ง
The default cost model depends on other optimization flags and is either dynamic or cheap ๐
-fsimd-cost-model=modelโ this is the same vibe but for loops marked with the OpenMPsimddirective ๐ฆ The model should be one ofunlimited,dynamic,cheap. Every value means the same thing as it does in-fvect-cost-model, and by default, whatever cost model you set with-fvect-cost-modelis used ๐ซถ-ftree-vrpโ Value Range Propagation on trees, bestie ๐ It's kind of like constant propagation, except instead of tracking single values, it tracks ranges of values. This lets the optimizers remove unnecessary range checks, like array bound checks and null pointer checks ๐ It's enabled by default at-O2and higher. Heads up though: null pointer check elimination only happens if-fdelete-null-pointer-checksis enabled ๐-fsplit-pathsโ splits paths that lead to loop backedges, which can glow up dead code elimination and common subexpression elimination โจ Enabled by default at-O3and above ๐-fsplit-ivs-in-unrollerโ when a loop is 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 makes the scheduling passes more efficient ๐ฅ
A combo of -fweb and CSE is often enough to get the same effect, ngl ๐
But 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โ when unrolling a loop, the compiler makes multiple copies of some local variables, which can end up giving you superior code ๐ฆ
This one is enabled by default for PowerPC targets, but disabled by default everywhere else ๐ธ
-fpartial-inliningโ inlines parts of functions ๐ This only does anything if inlining is already turned on by-finline-functionsor-finline-small-functions. Enabled at levels-O2,-O3,-Osโจ-fpredictive-commoningโ the compiler reuses computations from previous iterations of loops, especially memory loads and stores ๐ง โจ Enabled at level-O3, and also turned on by-fprofile-useand-fauto-profile๐-fprefetch-loop-arraysโ if the target machine supports it, the compiler generates instructions to prefetch memory, which can help loops that access large arrays ๐ Heads up: this might make the code better or worse, and the results are super dependent on how the loops are structured in your source ๐ญ Disabled at level-Os๐-fno-printf-return-valueโ this stops the compiler from swapping in constants for the known return values of formatted output functions like"sprintf","snprintf","vsprintf", and"vsnprintf". ("printf"and"fprintf"are not included.) ๐ Normally this is a big win, because it lets GCC optimize or even eliminate branches based on those known return values, as long as the arguments are constant or known to be in a range where the exact return value can be figured out ๐ฅ For example, with-fprintf-return-valuein effect, both the branch and the body of the"if"statement (but not the call tosnprint) can be optimized away wheniis a 32-bit or smaller integer, because the return value is guaranteed to be at most 8 ๐ฆ
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations, so it gives the best results at -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โ tells GCC to stop guessing branch probabilities using heuristics ๐
Normally, if profiling feedback (-fprofile-arcs) doesn't provide branch probabilities, GCC uses heuristics based on the control flow graph to guess them ๐ง If some branch probabilities are specified by __builtin_expect, the heuristics guess the rest of the control flow graph while taking that __builtin_expect info into account. The interactions between the two can get complicated, so sometimes it helps 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 ๐ The algorithm can besimple, which doesn't increase code size (except sometimes through secondary effects like alignment), orstc, the "software trace cache" algorithm, which puts all the often executed code together. It minimizes the number of branches executed by making extra copies of code, so it can get a little chunky ๐ซ
The default is simple at levels -O1 and -Os, and stc at levels -O2 and -O3 ๐
-freorder-blocks-and-partitionโ on top of reordering basic blocks to cut down taken branches, this one splits hot and cold basic blocks into separate sections of the assembly and.ofiles ๐ธ That helps paging and cache locality performance โจ
This optimization is automatically turned off in a bunch of 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, it isn't enabled by default (to avoid linker errors), but you can still turn it on explicitly if you're using a working linker ๐ง
Enabled for x86 at levels -O2, -O3, -Os ๐
-freorder-functionsโ reorders functions in the object file to improve code locality ๐ง This works by putting the most frequently executed functions in the special.text.hotsubsections and the unlikely ones in.text.unlikely๐ The linker does the reordering, so your object file format has to support named sections, and the linker has to place them somewhere reasonable ๐
This option isn't effective unless you 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. An object of one type is assumed to never 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 it has undefined behavior, even if the cast uses a union type ๐ญ For example:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os ๐
-fipa-strict-aliasingโ controls whether the rules of-fstrict-aliasingget applied across function boundaries ๐ Just a heads up: if multiple functions get inlined into a single function, the memory accesses are no longer considered to be crossing a function boundary ๐ง
The -fipa-strict-aliasing option is enabled by default, and 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โ bestie, this one is all about lining up function starts ๐ฆ. It aligns the start of functions to the next power-of-two that's greater than or equal to n, skipping up to m-1 bytes โจ. The point is that the CPU can grab at least the first m bytes of the function without crossing an n-byte alignment boundary ๐ .- If m isn't specified, it defaults to n ๐ธ.
-falign-functions=32aligns functions to the next 32-byte boundary ๐-falign-functions=24aligns to the next 32-byte boundary only if this can be done by skipping 23 bytes or less ๐-falign-functions=32:7aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less ๐ง
The second pair of n2:m2 values gives you a secondary alignment ๐. -falign-functions=64:7:32:3 aligns to the next 64-byte boundary if that can be done by skipping 6 bytes or less. 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, it gets rounded up ๐.
-fno-align-functions and -falign-functions=1 are equivalent, and they both mean functions are not aligned ๐ญ.
If n isn't specified or is zero, the compiler uses a machine-dependent default. The maximum allowed n value is 65536 โจ.
Enabled at levels -O2, -O3 ๐ฅ.
-flimit-function-alignmentโ this one is the responsible friend ๐ซถ. When it's enabled, the compiler tries not to overalign functions for no reason. It asks the assembler to align by the amount set by-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-falign-functions๐.-fno-align-labelsand-falign-labels=1are equivalent, and they mean labels are not aligned ๐ญ.- If
-falign-loopsor-falign-jumpsapply and their values are bigger than this one, their values win instead ๐. - If n isn't specified or is zero, you get a machine-dependent default that is very likely to be
1, which means no alignment ๐ฅฑ. - The maximum allowed n value is
65536๐ .
Enabled at levels -O2, -O3 โจ.
-falign-loops,-falign-loops=n,-falign-loops=n:m,-falign-loops=n:m:n2,-falign-loops=n:m:n2:m2โ aligns loops to a power-of-two boundary ๐. If the loops run a lot of times, this makes up for the cost of running the dummy padding instructions ๐.- If
-falign-labelsis bigger than this value, its value gets used instead ๐ธ. - The parameters are analogous to
-falign-functions๐ฆ. -fno-align-loopsand-falign-loops=1are equivalent, and they mean loops are not aligned ๐.- The maximum allowed n value is
65536๐ฅ. - If n isn't specified or is zero, the compiler uses a machine-dependent default ๐ง.
- If
Enabled at levels -O2, -O3 ๐.
-falign-jumps,-falign-jumps=n,-falign-jumps=n:m,-falign-jumps=n:m:n2,-falign-jumps=n:m:n2:m2โ aligns branch targets to a power-of-two boundary, but only for branch targets that can only be reached by jumping ๐ฆ. In that case, no dummy operations need to run โจ.- If
-falign-labelsis bigger than this value, its value gets used instead ๐. - The parameters are analogous to
-falign-functions๐. -fno-align-jumpsand-falign-jumps=1are equivalent, and the original page says they mean that loops are not aligned ๐.- If n isn't specified or is zero, the compiler uses a machine-dependent default ๐.
- The maximum allowed n value is
65536๐.
- If
Enabled at levels -O2, -O3 โจ.
-fno-allocation-dceโ don't remove unused C++ allocations during dead code elimination ๐งน.-fallow-store-data-racesโ this one is a vibe with a warning label โ ๏ธ. It 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 touch optimization of local data ๐ธ. It's only safe to use if you already know global data won't be accessed by multiple threads ๐ซถ.
Examples of optimizations this enables include hoisting, or if-conversions, that might cause a value already in memory to get rewritten with that same value ๐. That rewrite is fine in a single-threaded context, but it can be unsafe in a multi-threaded one ๐. Also, on some processors, if-conversions may be required before vectorization can happen ๐ง .
Enabled at level -Ofast ๐ฅ.
-funit-at-a-timeโ kept around for compatibility only ๐ฐ๏ธ. It has no effect by itself.-fno-unit-at-a-time, though, implies-fno-toplevel-reorderand-fno-section-anchors๐.
Enabled by default ๐ .
-fno-toplevel-reorderโ don't reorder top-level functions, variables, and"asm"statements ๐. They get output in the same order they appear in the input file โจ. With this on, unreferenced static variables are not removed ๐๏ธ. It exists to support existing code that depends on a specific ordering. For new code, it's better to use attributes when possible ๐ก.
-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested ๐ฆ. On top of that, -fno-toplevel-reorder implies -fno-section-anchors ๐ธ.
-fwebโ this builds webs, the way they're commonly used for register allocation, and gives each web its own individual pseudo register ๐ธ๏ธ. The register allocation pass can then operate on pseudos directly, and it also strengthens several other optimization passes, like CSE, the loop optimizer, and the trivial dead code remover ๐. The catch? It can make debugging impossible, because variables no longer stay in a"home register"๐ญ.
Enabled by default with -funroll-loops โจ.
-fwhole-programโ assume the current compilation unit is the whole program being compiled ๐. All public functions and variables become static functions, except formainand anything merged by the attribute"externally_visible"๐. Because of that, the interprocedural optimizers can get more aggressive ๐ฅ.
Don't use this together with -flto. Relying on a linker plugin instead should give you safer and more precise information ๐จ.
-flto[=n]โ the standard link-time optimizer, and it's iconic ๐. When you invoke it with source code, it generates GIMPLE (one of GCC's internal representations) and writes it to special ELF sections in the object file ๐ง. When the object files get linked together, all the function bodies are read back from those ELF sections and instantiated as if they were part of the same translation unit ๐ซถ.
To use the link-time optimizer, -flto and your optimization options should be specified at compile time and during the final link โจ. It's recommended that you compile all the files in the same link with the same options, and then specify those options at link time too ๐
. For example:
gcc -c -O2 -flto foo.c
gcc -c -O2 -flto bar.c
gcc -o myprog -flto -O2 foo.o bar.o
The first two invocations save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o ๐ฆ. The final invocation reads that GIMPLE bytecode from foo.o and bar.o, merges the two files into a single internal image, and compiles the result as usual ๐. Since both files get merged into one image, all the interprocedural analyses and optimizations work across the two files as if they were a single one ๐. For example, the inliner can inline functions in bar.o into functions in foo.o, and vice-versa ๐ฅ.
There's also a simpler way to turn on link-time optimization ๐ธ:
gcc -o myprog -flto -O2 foo.c bar.c
That generates bytecode for foo.c and bar.c, merges them into a single GIMPLE representation, and optimizes them as usual to produce myprog ๐.
The big thing to remember is that you need to use the GCC driver to perform the link step if you want link-time optimizations ๐. GCC automatically performs link-time optimization if any of the objects involved were compiled with the -flto command-line option ๐ค. You can always override that automatic decision by passing -fno-lto to the link command ๐
โโ๏ธ.
To make whole program optimization effective, you have to make certain whole program assumptions ๐ง . The compiler needs to know which functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit ๐งฉ. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes that information to the compiler about used and externally visible symbols ๐. When the linker plugin isn't available, use -fwhole-program so the compiler can make these assumptions, which leads to more aggressive optimization decisions ๐ฅ.
When a file is compiled with -flto and without -fuse-linker-plugin, the generated object file is larger than a regular one ๐ฆ. That's because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects) ๐ญ. This means object files with LTO information can still be linked as normal object files. If -fno-lto is passed to the linker, though, no interprocedural optimizations get applied ๐. Also, when -fno-fat-lto-objects is enabled, the compile stage is faster, but you cannot perform a regular, non-LTO link on those objects ๐ซ.
When producing the final binary, GCC only applies link-time optimizations to the files that contain bytecode ๐ฏ. That means you can mix and match object files and libraries with GIMPLE bytecodes and final object code ๐งฆ. GCC automatically picks which files to optimize in LTO mode and which files to just link without any further processing ๐ค.
Generally, options specified at link time override the ones specified at compile time ๐. Sometimes, though, GCC tries to infer link-time options from the settings used to compile the input files ๐.
If you leave out the optimization level -O at link time, GCC just uses the highest level that was used when compiling the object files ๐
. But ngl, it's pretty ineffective to only set -O at link time and skip it at compile time ๐. There are two reasons. First, compiling without optimization skips the compiler passes that gather the info needed for good link-time optimization ๐. Second, some early optimization passes can only happen at compile time, not link time. So set it at both steps, bestie ๐ซถ.
Some code generation flags get preserved by GCC when it makes bytecode, because they need to be used during the final link โจ. Right now those are -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm and all the -m target flags. Their settings get taken from the first object file that explicitly specifies them ๐ง.
The PIC and PIE flags (-fPIC, -fpic, -fpie and -fPIE) get combined using this scheme, and it's giving very precise vibes ๐:
-fPIC + -fpic = -fpic
-fPIC + -fno-pic = -fno-pic
-fpic/-fPIC + (no option) = (no option)
-fPIC + -fPIE = -fPIE
-fpic + -fPIE = -fpie
-fPIC/-fpic + -fpie = -fpie
Certain ABI-changing flags have to match across every compilation unit. If you try to override one at link time with a conflicting value, it gets ignored ๐ซ. That includes stuff like -freg-struct-return and -fpcc-struct-return, so don't even try ๐
.
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 them at link time.
Diagnostic options like -Wstringop-overflow get passed through to the link stage too, and their setting matches the compile step at function granularity ๐. This only matters for diagnostics that come out during optimization. Also, code transforms like inlining can make warnings get enabled or disabled for certain regions if the code isn't consistent with the compile-time setting ๐ญ.
When you need to pass options to the assembler with-Waor-Xassembler, make sure you either compile those translation units with-fno-lto, or use the same assembler options on every translation unit ๐จ. You can also specify assembler options at LTO link time instead.
To turn on debug info generation, you need to supply -g at compile time ๐. If any input files at link time were built with debug info enabled, the link will turn on debug info generation 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 keep it consistent, babe ๐ฅน.
If LTO runs into objects with C linkage that were declared with incompatible types across separate translation units being linked together, that's undefined behavior according to ISO C99 6.2.7 ๐. GCC might issue a non-fatal diagnostic, but the behavior is still undefined at run time. Similar diagnostics might show up for other languages too ๐.
LTO also lets you apply interprocedural optimizations to files written in different languages, and this is the main character moment ๐:
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
The final link is done with g++ so you get 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 containing 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 show the symbols of object files with GIMPLE bytecode, use gcc-nm. Those commands require that ar, ranlib and nm were compiled with plugin support ๐ง. At link time, use the flag -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 enabled, 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 still get extracted and linked as usual ๐. But they won't participate in the LTO optimization process ๐. To make a static library that works for both LTO optimization and regular 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 the program doesn't require any symbols to be exported, you can combine -flto and -fwhole-program. That lets the interprocedural optimizers use more aggressive assumptions, which can 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 makes no attempt to generate bytecode that's portable between different types of hosts ๐. The bytecode files are versioned with a strict version check, so bytecode generated by one version of GCC won't work with an older or newer version of GCC ๐.
Link-time optimization doesn't play well with debugging info on systems that aren't using a combo of ELF and DWARF ๐ญ.
If you specify the optional n, the optimization and code generation done at link time runs in parallel using n parallel jobs, by using an installed make program ๐โโ๏ธ. The environment variable MAKE can override which program gets used ๐ง.
-flto-partition=algโ Picks the partitioning algorithm the link-time optimizer uses ๐. The value is1to1, which mirrors the original source files, orbalanced, which splits things into equally sized chunks where possible, ormax, which makes a new partition for every symbol where possible. Settingnoneas the algorithm turns off partitioning and streaming completely. The default isbalanced.1to1can work as a workaround for various code ordering issues, butmaxpartitioning is only meant for internal testing ๐งช. The valueoneuses exactly one partition, and the valuenoneskips partitioning and runs the link-time optimization step straight from the WPA phase ๐.-flto-compression-level=nโ Sets how much the intermediate language written to LTO object files gets compressed ๐๏ธ. It only matters when you're in LTO mode (-flto). GCC supports two LTO compression algorithms. Forzstd, valid values are0(no compression) up to19(maximum compression), whilezlibsupports values from0to9. Values outside the range get clamped to the minimum or maximum of the supported values. If you don't give the option, a default balanced compression setting is used ๐.-fuse-linker-pluginโ Turns on the use of a linker plugin during link-time optimization ๐. This needs plugin support in the linker, which you get with gold or GNU ld 2.21 or newer ๐ฆ.
This option lets GCC pull object files with GIMPLE bytecode out of library archives. That makes the optimization better by exposing more code to the link-time optimizer ๐ฅ. It also tells the optimizer which symbols can be accessed externally, meaning by a non-LTO object or during dynamic linking. The code quality improvements you get on binaries (and on shared libraries that use hidden visibility) are similar to -fwhole-program โจ. See -flto for a description of what this flag does and how to use it ๐
.
This option is enabled by default when LTO support is enabled in GCC and GCC was configured to work with a linker that supports plugins (GNU ld 2.21 or newer, or gold) ๐.
-ffat-lto-objectsโ Fat LTO objects are object files that hold both the intermediate language and the object code ๐ฑ. That makes them usable for both LTO linking and normal linking ๐. This option only works when you're compiling with-flto, and it gets ignored at link time ๐.
-fno-fat-lto-objects speeds up compilation compared to plain LTO, but it needs the complete toolchain to be aware of LTO ๐ฌ. It needs a linker with linker plugin support for basic functionality. On top of that, nm, ar and ranlib need to support linker plugins so you get a full-featured build environment (one that can build static libraries and so on) ๐ ๏ธ. GCC provides the gcc-ar, gcc-nm and gcc-ranlib wrappers to pass the right options to these tools. With non-fat LTO, makefiles need to be modified to use them ๐.
Modern binutils come with a plugin auto-load mechanism, and that's pretty iconic ๐. 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โ okay so after register allocation and post-register allocation instruction splitting, GCC hunts for arithmetic instructions that set processor flags like a comparison based on that same arithmetic ๐. If it's 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๐.
-fcprop-registersโ after register allocation and post-register allocation instruction splitting, GCC runs a copy-propagation pass ๐ . It tries to reduce scheduling dependencies and occasionally eliminate the copy ๐ซถ.- Enabled at levels
-O1,-O2,-O3,-Os๐ธ.
- Enabled at levels
-fprofile-correctionโ profiles collected with an instrumented binary for multi-threaded programs can be inconsistent because some counter updates got missed ๐ญ. 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โจ.
- This option is enabled by
-fprofile-partial-trainingโ with-fprofile-use, every part of the program that didn't run during the train run gets optimized aggressively for size instead of speed ๐ง. Sometimes it isn't practical to train every possible hot path. For example, a program might have functions specific to some hardware, and training might not cover every hardware configuration the program runs on ๐. With-fprofile-partial-training, profile feedback is ignored for all functions that weren't executed during the train run, so they get optimized as if they were compiled without profile feedback ๐. This gives better performance when the train run isn't representative, but it also leads to significantly bigger code ๐ฆ.-fprofile-use,-fprofile-use=pathโ enable profile feedback-directed optimizations, plus the following optimizations, many of which are generally 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 first generate profiling information ๐.
By default, GCC emits an error message if the feedback profiles don't match the source code ๐ฌ. You can turn that error into a warning with -Wno-error=coverage-mismatch. Just note that 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 in that path for the profile feedback data files. See -fprofile-dir ๐.
-fauto-profile,-fauto-profile=pathโ enable sampling-based feedback-directed optimizations, plus the following optimizations, many of which are generally 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 ๐๏ธ.
Making an AutoFDO profile data file means running your program with the perf utility on a supported GNU/Linux target system ๐ง. For more info, check out <https://perf.wiki.kernel.org/> ๐.
E.g.
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Next, 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 between speed and correctness, so they all have to be specifically enabled ๐ซง.
-ffloat-storeโ don't store floating-point variables in registers, and inhibit other options that might change whether a floating-point value gets pulled from a register or from memory ๐ โโ๏ธ.- This prevents undesirable excess precision 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-storeafter modifying them to store all pertinent intermediate computations into variables ๐.
- This prevents undesirable excess precision on machines like the 68000, where the floating registers (of the 68881) keep more precision than a
-fexcess-precision=styleโ 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. That 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 actually happens ๐ข. - When compiling C, if
-fexcess-precision=standardis specified, excess precision follows the rules in ISO C99. Specifically, both casts and assignments cause values to be rounded to their semantic types (whereas-ffloat-storeonly affects assignments) ๐. - This option is enabled by default for C if a strict conformance option like
-std=c99is used ๐.-ffast-mathenables-fexcess-precision=fastby default, regardless of whether a strict conformance option is used ๐๏ธ. -fexcess-precision=standardisn't implemented for languages other than C ๐. On the x86, it has no effect if-mfpmath=sseor-mfpmath=sse+387is specified. In the former case, IEEE semantics apply without excess precision. In the latter, rounding is unpredictable ๐.
- By default,
-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 isn't turned on by any
-Ooption besides-Ofast๐ . It can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications ๐โโ๏ธ.
- This option causes the preprocessor macro
-fno-math-errnoโ don't seterrnoafter calling math functions that run with a single instruction, likesqrt๐งฎ. A program that relies on IEEE exceptions for math error handling may want this flag for speed while keeping IEEE arithmetic compatibility ๐ซถ.- This option isn't turned on by any
-Ooption, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications โ ๏ธ. - The default is
-fmath-errno๐. - On Darwin systems, the math library never sets
errno, so there's no reason for the compiler to consider the possibility that it might. That means-fno-math-errnois the default there ๐.
- This option isn't turned on by any
-funsafe-math-optimizationsโ allows optimizations for floating-point arithmetic that (a) assume that arguments and results are valid and (b) may violate IEEE or ANSI standards ๐ค. When used at link time, it may include libraries or startup files that change the default FPU control word or do other similar optimizations ๐ง.- This option isn't turned on by any
-Ooption, for the same reason as before: it can give incorrect output for programs that depend on exact IEEE or ISO rules for math functions. It may, however, yield faster code for programs that don't need those guarantees ๐. - It enables
-fno-signed-zeros,-fno-trapping-math,-fassociative-mathand-freciprocal-math๐งฉ. - The default is
-fno-unsafe-math-optimizations๐งท.
- This option isn't turned on by any
-fassociative-mathโ allows re-association of operands in series of floating-point operations ๐. This violates the ISO C and C++ language standard by possibly changing the computation result ๐ต.- NOTE: re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. Because of that, it can't be used on code that relies on rounding behavior, like
"(x + 2**52) - 2**52"๐ซ. It may also reorder floating-point comparisons, so it may not be used when ordered comparisons are required ๐. - This option requires that both
-fno-signed-zerosand-fno-trapping-mathbe in effect ๐ค. Moreover, it doesn't make much sense with-frounding-math๐คทโโ๏ธ. - For Fortran, the option is automatically enabled when both
-fno-signed-zerosand-fno-trapping-mathare in effect ๐ช. - The default is
-fno-associative-math๐.
- NOTE: re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. Because of that, it can't be used on code that relies on rounding behavior, like
-freciprocal-mathโ allows the reciprocal of a value to be used instead of dividing by the value, if that enables optimizations ๐ง . For example,"x / y"can be replaced with"x * (1/y)", which is useful if"(1/y)"is subject to common subexpression elimination ๐ก.- Heads up: this loses precision and increases the number of flops operating on the value ๐.
- The default is
-fno-reciprocal-math๐ท.
-ffinite-math-onlyโ allows optimizations for floating-point arithmetic that assume arguments and results are not NaNs or +-Infs ๐ซ .- This option isn't turned on by any
-Ooption, 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 those guarantees ๐ข. - The default is
-fno-finite-math-only๐.
- This option isn't turned on by any
-fno-signed-zerosโ okay bestie, this one tells the optimizer it can ignore whether a zero is positive or negative ๐ง. IEEE arithmetic treats distinct+0.0and-0.0values as different, which is why stuff likex+0.0or0.0*xcan't get simplified away, even with-ffinite-math-only๐ญ. This flag says the sign of a zero result isn't significant. The default is-fsigned-zeros๐ .-fno-trapping-mathโ this one assumes floating-point operations can't throw user-visible traps ๐ฆ. Those traps are division by zero, overflow, underflow, inexact result, and invalid operation. It requires-fno-signaling-nansto be in effect โจ. Turning it on can give faster code if your program relies on "non-stop" IEEE arithmetic, for example ๐ธ.
โ ๏ธ Never, ever turn this on through any-Ooption! It can produce incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions ๐. The default is-ftrapping-math.
-frounding-mathโ this turns off transformations and optimizations that assume the default floating-point rounding behavior ๐. That default means round-to-zero for all floating-point to integer conversions, and round-to-nearest for all other arithmetic truncations. Use it if your program changes the FP rounding mode dynamically, or might run with a non-default rounding mode ๐. It also disables compile-time constant folding of floating-point expressions (since rounding mode can change those results) and arithmetic transformations that aren't safe with sign-dependent rounding modes ๐. The default is-fno-rounding-math.
๐งช This one is experimental! It doesn't currently guarantee that every GCC optimization affected by rounding mode gets disabled. Future versions of GCC might give finer control over this setting using C99'sFENV_ACCESSpragma, and this command-line option will be used to set the default state forFENV_ACCESS๐ฎ.
-fsignaling-nansโ this tells the compiler to assume IEEE signaling NaNs may cause user-visible traps during floating-point operations ๐ฅ. It disables optimizations that might change how many exceptions are visible with signaling NaNs. It also implies-ftrapping-math๐. Turning it on defines the preprocessor macro__SUPPORT_SNAN__โจ. The default is-fno-signaling-nans.
๐งช Also experimental! It doesn't currently guarantee that every GCC optimization affecting signaling NaN behavior is disabled ๐ญ.
-fno-fp-int-builtin-inexactโ this stops the built-in functionsceil,floor,round, andtrunc(plus theirfloatandlong doublevariants) from generating code that raises theinexactfloating-point exception for noninteger arguments ๐. ISO C99 and C11 let these raiseinexact, but ISO/IEC TS 18661-1:2014 (the C bindings to IEEE 754-2008, as integrated into ISO C2X) doesn't allow it ๐. The default is-ffp-int-builtin-inexact, so the exception is raised, unless C2X 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, the inexact exception might still be raised if that library doesn't follow TS 18661 ๐.
-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 a complex multiplication or division result is"NaN + I*NaN", and skips trying to rescue that situation ๐ฆ. The default is-fno-cx-limited-range, but-ffast-mathturns it on ๐. This option controls the default setting of the ISO C99CX_LIMITED_RANGEpragma. It applies to all languages, though ๐ .-fcx-fortran-rulesโ complex multiplication and division follow Fortran rules ๐ง. Range reduction happens as part of complex division, but there's no checking for a"NaN + I*NaN"result and no attempt to rescue it ๐ญ. The default is-fno-cx-fortran-rules.
The following options control optimizations that may improve performance, but none of them are enabled by any -O options ๐. This section includes experimental options that may produce broken code ๐, so proceed with caution, bestie!
-fbranch-probabilitiesโ okay this one is a whole glow-up arc โจ. First you run a program compiled with-fprofile-arcs, and then you compile it a second time with-fbranch-probabilitiesto improve optimizations based on how many times each branch was taken ๐. When a program compiled with-fprofile-arcsexits, it saves arc execution counts to a file calledsourcename.gcdafor each source file ๐พ. That data is super dependent on the structure of the generated code, so you must use the same source code and the same optimization options for both compilations ๐ซถ.
With -fbranch-probabilities, GCC puts a REG_BR_PROB note on each JUMP_INSN and CALL_INSN ๐ฆ. These can be used to improve optimization. Right now they're only used in one place: in reorg.cc. Instead of guessing which path a branch is most likely to take, the REG_BR_PROB values are used to exactly determine which path is taken more often ๐. Enabled by -fprofile-use and -fauto-profile.
-fprofile-valuesโ if you combine this with-fprofile-arcs, it adds code that gathers some data about the values of expressions in your program ๐. With-fbranch-probabilities, it reads back that data and uses it for optimizations ๐ง. Enabled by-fprofile-generate,-fprofile-use, and-fauto-profile.-fprofile-reorder-functionsโ function reordering based on profile instrumentation records the first time each function executes, then orders those functions in ascending order โฐ. Enabled with-fprofile-use.-fvptโ if combined with-fprofile-arcs, this tells the compiler to add code that collects information about the values of expressions ๐. With-fbranch-probabilities, it reads that data back and actually performs optimizations based on it ๐ . Right now the optimizations include specializing division operations using what it knows about the value of the denominator โจ. Enabled with-fprofile-useand-fauto-profile.-frename-registersโ this tries to avoid false dependencies in scheduled code by using registers left over after register allocation ๐ธ. It helps the most on processors with lots of registers ๐. Heads up though: depending on the debug information format the target uses, it can make debugging impossible, since variables no longer stay in a "home register" ๐ญ. Enabled by default with-funroll-loops.-fschedule-fusionโ a target-dependent pass over the instruction stream that schedules instructions of the same type together ๐งฉ. That's because the target machine can run them more efficiently when they're next to each other in the instruction flow ๐. Enabled at levels-O2,-O3,-Os.-ftracerโ performs tail duplication to enlarge the superblock size ๐ฆ. This simplifies the control flow of the function, which lets other optimizations do a better job ๐ซถ. Enabled by-fprofile-useand-fauto-profile.-funroll-loopsโ unrolls loops whose number of iterations can be determined at compile time or upon entry to the loop ๐.-funroll-loopsimplies-frerun-cse-after-loop,-fweb, and-frename-registers๐. It also turns on complete loop peeling, which fully removes loops with a small constant number of iterations โ๏ธ. This option makes code larger, and it may or may not make it run faster ๐คทโโ๏ธ. Enabled by-fprofile-useand-fauto-profile.-funroll-all-loopsโ unrolls all loops, even if their number of iterations is uncertain when the loop is entered ๐ฌ. This usually makes programs run more slowly ๐ข.-funroll-all-loopsimplies the same options as-funroll-loops.-fpeel-loopsโ peels loops that have enough information to show they won't roll much, either from profile feedback or static analysis ๐. It also turns on complete loop peeling (fully removing loops with a small constant number of iterations) โจ. Enabled by-O3,-fprofile-use, and-fauto-profile.-fmove-loop-invariantsโ enables the loop invariant motion pass in the RTL loop optimizer ๐. 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, in exchange for carrying the stored value in a register across the iteration ๐ง . For this option to have an effect,-ftree-loop-imhas to be enabled too ๐ซถ. Enabled at level-O1and higher, except for-Og.-fsplit-loopsโ splits a loop into two if it contains a condition that's always true for one side of the iteration space and always false for the other ๐ช. Enabled by-fprofile-useand-fauto-profile.-funswitch-loopsโ moves branches with loop invariant conditions out of the loop ๐. You get duplicates of the loop on both branches, each modified according to the result of the condition ๐ฏ. Enabled by-fprofile-useand-fauto-profile.-fversion-loops-for-stridesโ if a loop iterates over an array with a variable stride, GCC creates another version of the loop that assumes the stride is always one ๐ง. For example, this loop:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
This is especially useful for assumed-shape arrays in Fortran, where it allows better vectorization by assuming contiguous accesses ๐. This flag is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐.
-ffunction-sections, -fdata-sections โ okay so these tell GCC to tuck each function or data item into its own section in the output file โจ, as long as the target supports arbitrary sections. The function's name or the data item's name decides what that section is called. ๐
Use these on systems where the linker can do optimizations that improve locality of reference in the instruction space ๐ฆ. Most systems using the ELF object format have linkers that can do this. On AIX, the linker rearranges sections (CSECTs) based on the call graph. The performance impact varies, so it's not guaranteed to be a glow-up ๐ธ.
Together with a linker garbage collection (linker --gc-sections option), these options may lead to smaller statically-linked executables (after stripping) ๐ซถ.
On ELF/DWARF systems, these options do not degrade the quality of the debug information ๐. There could be issues with other object files and debug info formats though, so keep that in mind ๐.
๐จ Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker create larger object and executable files, and they're also slower ๐ญ. These options affect code generation. They prevent optimizations by the compiler and assembler from using relative locations inside a translation unit, since those locations aren't known until link time. An example of such an optimization is relaxing calls to short call instructions.
-fstdarg-opt โ optimize the prologue of variadic argument functions based on how those arguments get used ๐ง.
-fsection-anchors โ this one is a whole vibe โจ. It tries to reduce the number of symbolic address calculations by using shared "anchor" symbols to address nearby objects. On some targets, that can cut down on GOT entries and GOT accesses ๐.
For example, take the following function foo:
static int a, b, c;
int foo (void) { return a + b + c; }
Normally it calculates the addresses of all three variables, but if you compile it with -fsection-anchors, it grabs the variables from one common anchor point instead ๐. The effect is kinda like this pseudocode (which isn't valid C, sorry bestie ๐):
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
Not every target supports this option, so check before you commit ๐.
-fzero-call-used-regs=choice โ main character energy for program security ๐ฅ. This zeroes call-used registers at function return, which can help mitigate Return-Oriented Programming (ROP) attacks or prevent information leakage through registers ๐ก๏ธ.
The possible values of choice are the same as for the zero_call_used_regs attribute. The default is skip ๐
.
You can control this behavior for a specific function by using the function attribute zero_call_used_regs ๐ฆ.
--param name=value โ okay this one is for the nerds who love tuning ๐ค. GCC uses various constants to control how much optimization happens. For example, GCC won't inline functions that contain more than a certain number of instructions ๐
โโ๏ธ. You can tweak some of these constants on the command line with --param.
โ ๏ธ The names of specific parameters, and what their values mean, are tied to the compiler's internals and can change without notice in future releases. So don't build your whole personality around them ๐ญ.
To get the minimal, maximal, and default value of a parameter, use --help=param -Q options ๐ง. In each case, the value is an integer. These are the names recognized for all targets:
predictable-branch-outcomeโ when a branch is predicted to be taken with a probability lower than this threshold (in percent), it's considered well predictable โจ.max-rtl-if-conversion-insnsโ RTL if-conversion tries to remove conditional branches around a block and swap them for conditionally executed instructions ๐. This parameter sets the maximum number of instructions in a block that should be considered for if-conversion. The compiler also uses other heuristics to decide whether if-conversion is likely to be profitable ๐ง .max-rtl-if-conversion-predictable-costโ RTL if-conversion will try to remove conditional branches around a block and replace them with conditionally executed instructions ๐ซ. These parameters set the maximum permissible cost for the sequence that if-conversion would generate, depending on whether the branch is statically determined to be predictable or not. The units are the same as those for the GCC internalseq_costmetric ๐. The compiler tries to provide a reasonable default for this parameter using theBRANCH_COSTtarget macro ๐ฏ.max-crossjump-edgesโ the maximum number of incoming edges to consider for cross-jumping. The algorithm used by-fcrossjumpingis O(N^2) in the number of edges incoming to each block ๐ตโ๐ซ. Higher values mean more aggressive optimization, which makes compilation time go up for probably a small improvement in executable size ๐ข.min-crossjump-insnsโ the minimum number of instructions that must be matched at the end of two blocks before cross-jumping happens on them ๐. This value is ignored when all instructions in the block being cross-jumped from are matched ๐ซ .max-grow-copy-bb-insnsโ the maximum code size expansion factor when copying basic blocks instead of jumping ๐งฉ. The expansion is relative to a jump instruction.max-goto-duplication-insnsโ the maximum number of instructions to duplicate into a block that jumps to a computed goto ๐ช. To avoid O(N^2) behavior in a bunch of passes, GCC factors computed gotos early in compilation and unfactors them as late as possible ๐ฐ๏ธ. Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsget unfactored โจ.max-delay-slot-insn-searchโ the maximum number of instructions to consider when looking for an instruction to fill a delay slot ๐. If more than this arbitrary number gets searched, the time saved by filling the delay slot is minimal, so GCC stops searching ๐. Higher values mean more aggressive optimization, making compilation take longer for probably a small improvement in execution time ๐.max-delay-slot-live-searchโ when filling delay slots, the maximum number of instructions to consider when searching for a block with valid live register information ๐. Cranking this arbitrarily chosen value up means more aggressive optimization and longer compilation time ๐. This parameter should be removed once the delay slot code is rewritten to maintain the control-flow graph ๐ง.max-gcse-memoryโ the approximate maximum amount of memory in "kB" that can be allocated for the global common subexpression elimination optimization ๐พ. If more memory than specified is required, the optimization just doesn't happen ๐.max-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is larger than this value for any expression, RTL PRE inserts or removes the expression ๐. Otherwise it leaves partially redundant computations in the instruction stream ๐ซค.max-pending-list-lengthโ the maximum number of pending dependencies the scheduler allows before it flushes the current state and starts over ๐งน. Big functions with few branches or calls can create excessively large lists that needlessly eat memory and resources ๐.max-modulo-backtrack-attemptsโ the maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop ๐. Larger values can exponentially increase compilation time ๐๐.max-inline-functions-called-once-loop-depthโ the maximal loop depth of a call considered by the inline heuristics that try to inline all functions called once ๐.max-inline-functions-called-once-insnsโ the maximal estimated size of functions produced while inlining functions called once ๐.max-inline-insns-singleโ several parameters control the tree inliner used in GCC ๐ณ. This number sets the maximum number of instructions (counted in GCC's internal representation) in a single function that the tree inliner considers for inlining ๐งฎ. It only affects functions declaredinlineand methods implemented in a class declaration (C++) ๐ .max-inline-insns-autoโ when you use-finline-functions(included in-O3), a lot of functions that otherwise wouldn't be considered for inlining get investigated ๐ฌ. For those functions, a different, more restrictive limit than the one for functions declaredinlinecan be applied (--param max-inline-insns-auto) ๐ซถ.max-inline-insns-smallโ this is the bound applied to calls considered relevant with-finline-small-functions๐งธ.max-inline-insns-sizeโ this is the bound applied to calls that are optimized for size ๐ฆ. A small growth may be desirable to anticipate optimization opportunities exposed by inlining ๐ฑ.uninlined-function-insnsโ the number of instructions the inliner counts as function overhead, like the function prologue and epilogue ๐งพ.uninlined-function-timeโ the extra time the inliner counts as function overhead, like the time needed to run the function's prologue and epilogue โฑ๏ธ.inline-heuristics-hint-percentโ the scale (in percent) applied toinline-insns-single,inline-insns-single-O2, andinline-insns-autowhen the inline heuristics hint that inlining is very profitable (it'll enable later optimizations) ๐.uninlined-thunk-insns,uninlined-thunk-timeโ same as--param uninlined-function-insnsand--param uninlined-function-time, but applied to function thunks ๐งต.inline-min-speedupโ when the estimated performance improvement of caller plus callee runtime exceeds this threshold (in percent), the function can be inlined regardless of the limit on--param max-inline-insns-singleand--param max-inline-insns-auto๐๐.large-function-insnsโ ๐๏ธ This is the cutoff for "really large" functions. Once a function is bigger than this after inlining,--param large-function-growthstarts putting the brakes on inlining. It's mainly there to stop compile times from going totally off the rails because of the non-linear algorithms the back end uses. ๐ญlarge-function-growthโ ๐ This caps how much a large function can grow from inlining, measured in percent. So a value of100keeps growth to 2.0 times the original size. โจlarge-unit-insnsโ ๐ฆ This is the line for a large translation unit. Growth from inlining in units bigger than this gets limited by--param inline-unit-growth, and for small units that limit can be a bit too tight. Picture a unit with an inlineable function A and a function B that calls A three times. If B is small compared to A, the unit grows by 300%, and honestly that inlining is still very sane. ๐ซถ But for really huge units packed with 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--param inline-unit-growthgets applied. ๐งlazy-modulesโ ๐งฉ This is the maximum number of C++ module files that can be open at the same time when lazy loading is happening. ๐inline-unit-growthโ ๐ฑ This sets the maximum overall growth of the compilation unit from inlining. A value of20limits unit growth to 1.2 times the original size. Also, cold functions (whether they're marked cold with an attribute or flagged cold by profile feedback) don't count toward the unit size. ๐งipa-cp-unit-growthโ ๐ This is the maximum overall growth of the compilation unit from interprocedural constant propagation. A value of10limits unit growth to 1.1 times the original size. ๐ธipa-cp-large-unit-insnsโ ๐ This is the size at which the IPA-CP pass decides a translation unit counts as large. ๐ฆlarge-stack-frameโ ๐ฅ This is the limit that defines large stack frames. While inlining, the algorithm tries really hard not to grow past this limit too much. ๐large-stack-frame-growthโ ๐๏ธ This caps how much large stack frames can grow from inlining, in percent. A value of1000limits growth to 11 times the original size. Yes, that's a lot. ๐max-inline-insns-recursive,max-inline-insns-recursive-autoโ ๐ These set the maximum number of instructions an out-of-line copy of a self-recursive inline function can grow into while doing recursive inlining.--param max-inline-insns-recursiveis for functions that are declared inline. For functions that aren't declared inline, recursive inlining only happens when-finline-functionsis enabled (it's included in-O3), and that's when--param max-inline-insns-recursive-autotakes over. ๐max-inline-recursive-depth,max-inline-recursive-depth-autoโ ๐ These set the maximum recursion depth used for recursive inlining. Same deal as above:--param max-inline-recursive-depthapplies to functions declared inline, while functions that aren't declared inline only get recursive inlining when-finline-functions(included in-O3) is enabled, and then--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 backfire by making the prologue bigger or making the function body more complicated for other optimizers. > Heads up: this one can genuinely hurt performance if you use it on the wrong functions. ๐ When profile feedback is available (see-fprofile-generate), the compiler can guess the real recursion depth from how likely a function is to recurse through a given call expression. This parameter then limits inlining to call expressions whose probability is higher than the threshold, measured in percent. ๐early-inlining-insnsโ ๐ This sets how much growth the early inliner is allowed to make. Basically, it lets the early inliner do more inlining for code that has a large abstraction penalty. ๐max-early-inliner-iterationsโ ๐ This is the limit on how many iterations the early inliner runs. It's basically the bound on how many nested indirect calls the early inliner can resolve. Deeper chains still get handled later by late inlining. ๐งcomdat-sharing-probabilityโ ๐ค This is 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โ ๐๏ธ These set the maximum number of base pointers, references, and accesses that get stored for a single function by mod/ref analysis. ๐ซงmodref-max-testsโ ๐ This is the maximum number of tests the alias oracle can run to tell memory locations apart using mod/ref information. It should be bigger than--param modref-max-basesand--param modref-max-refs. ๐modref-max-depthโ ๐ณ๏ธ This is the maximum depth of the DFS walk used by modref escape analysis. Setting it to0disables the analysis completely. ๐ โโ๏ธmodref-max-escape-pointsโ ๐ช This is the maximum number of escape points that modref tracks per SSA-name. ๐modref-max-adjustmentsโ ๐ This is the maximum amount the access range can get enlarged during modref dataflow analysis. ๐profile-func-internal-idโ ๐ชช This controls whether the function's internal id is used when looking things up in the profile database. If the value is0, the compiler uses an id based on the function's assembler name and filename instead. That makes old profile data way more tolerant of source changes, like functions getting reordered. ๐ฅนmin-vect-loop-boundโ ๐ข This is the minimum number of iterations a loop needs before it gets vectorized when-ftree-vectorizeis used. The number of iterations after vectorization has to be greater than this value for vectorization to happen. ๐gcse-cost-distance-ratioโ ๐ This is a scaling factor in figuring out the maximum distance an expression can be moved by GCSE optimizations. It's only supported in the code hoisting pass. The bigger the ratio, the more aggressively simple expressions get hoisted, meaning expressions that cost less thangcse-unrestricted-cost. Setting it to0turns off hoisting of simple expressions completely. ๐gcse-unrestricted-costโ ๐ธ This is the cost, roughly measured as the cost of a single typical machine instruction, at which GCSE optimizations stop limiting how far an expression can travel. It's also only supported in the code hoisting pass. The lower the cost, the more aggressive the hoisting is, and setting it to0lets every expression travel unrestricted distances. ๐โโ๏ธmax-hoist-depthโ ๐ณ This is how deep the search goes into the dominator tree looking for expressions to hoist. It exists to avoid quadratic behavior in the hoisting algorithm. A value of0means there's no limit on the search, but it might slow down compilation of huge functions. ๐max-tail-merge-comparisonsโ โ๏ธ This is the maximum number of similar bbs that a bb gets compared against. It's there to avoid quadratic behavior in tree tail merging. ๐งmax-tail-merge-iterationsโ ๐ This is the maximum number of iterations of the pass over the function. It limits compilation time in tree tail merging. โฑ๏ธstore-merging-allow-unalignedโ ๐งท This lets the store merging pass introduce unaligned stores, but only if that's legal to do. ๐ทmax-stores-to-mergeโ ๐งบ This is the maximum number of stores the store merging pass will try to merge into wider stores. ๐max-store-chains-to-trackโ ๐ This is the maximum number of store chains tracked at the same time while trying to merge them into wider stores in the store merging pass. ๐max-stores-to-trackโ ๐ This is the maximum number of stores tracked at the same time while the store merging pass tries to merge them into wider stores. ๐ซถmax-unrolled-insnsโ ๐ This is the maximum number of instructions a loop can have and still be unrolled. If a loop does get unrolled, this parameter also decides how many times the loop code gets unrolled. ๐งถmax-average-unrolled-insnsโ ๐ This is the maximum number of instructions a loop can have and still be unrolled, where the instructions are weighted by how likely they are to execute. If a loop is unrolled, this parameter also decides how many times the loop code is unrolled. ๐max-unroll-timesโ ๐ข This is the maximum number of unrollings a single loop can get. ๐max-peeled-insnsโ ๐ This is the maximum number of instructions a loop can have and still be peeled. If a loop gets peeled, this parameter also decides how many times the loop code is peeled. ๐งmax-peel-timesโ ๐ช This is the maximum number of peelings a single loop can get. ๐max-peel-branchesโ ๐ฟ This is the maximum number of branches on the hot path through the peeled sequence. ๐ฅmax-completely-peeled-insnsโ ๐งฎ This is the maximum number of insns a completely peeled loop can have. ๐ธmax-completely-peel-timesโ โณ This is the maximum number of iterations a loop can have and still be suitable for complete peeling. ๐ฃmax-completely-peel-loop-nest-depthโ ๐ช This is the maximum depth of a loop nest that's suitable for complete peeling. ๐งธmax-unswitch-insnsโ ๐ This is the maximum number of insns an unswitched loop can have. ๐ฆmax-unswitch-levelโ ๐ช This is the maximum number of branches that get unswitched in a single loop. โญlim-expensiveโ ๐ฐ This is the minimum cost an expression needs to count as expensive in loop invariant motion. ๐min-loop-cond-split-probโ โ๏ธ When FDO profile information is available, this sets the minimum probability threshold a semi-invariant condition statement needs before it triggers a loop split. ๐งiv-consider-all-candidates-boundโ ๐งญ This is the bound on the number of candidates for induction variables. If there are this many candidates or fewer, all of them get considered for each use in induction variable optimizations. If there are more than that, only the most relevant ones get considered, so the time complexity doesn't go quadratic. ๐ฅณiv-max-considered-usesโ okay so the induction variable optimizations literally give up ๐ญ on any loop that has more induction variable uses than this. not a bug, just a vibe check ๐iv-always-prune-cand-set-boundโ if the set has fewer candidates than this value, the compiler always tries to clear out unnecessary ivs whenever it adds a new one. bestie, keep the set lean โจavg-loop-niterโ the average number of iterations a loop is expected to run ๐dse-max-object-sizeโ the biggest size (in bytes) of objects that dead store elimination tracks bytewise ๐งน. bigger numbers can mean longer compile times, so it's giving trade-off ๐ซถdse-max-alias-queries-per-storeโ the max number of questions dead store elimination can ask the alias oracle for each store ๐ฎ. more questions means slower compiles, but also possibly more dead stores getting cleaned up, so it's a whole vibe ๐scev-max-expr-sizeโ caps how big the expressions can get in the scalar evolutions analyzer ๐. huge expressions make the analyzer slow, so keep it tidy bestie ๐งscev-max-expr-complexityโ caps how complex those scalar evolutions expressions are allowed to be ๐งฉ. complicated ones slow the analyzer down, obviously ๐max-tree-if-conversion-phi-argsโ the max number of arguments a PHI can have and still get supported by TREE if conversion ๐ธ. this doesn't apply if the loop has a simd pragma, so iykyk ๐vect-max-version-for-alignment-checksโ the most run-time checks the vectorizer will do when it versions a loop for alignment ๐ฆvect-max-version-for-alias-checksโ same energy, but for alias checks: the most run-time checks the vectorizer will do when it versions a loop for aliasing ๐vect-max-peeling-for-alignmentโ the max number of loop peels the vectorizer will do to make memory access aligned ๐. setting it to-1means no limit at all, periodt ๐max-iterations-to-trackโ how many iterations of a loop the brute-force algorithm will try to evaluate when it's figuring out how many times the loop runs ๐งฎhot-bb-count-fractionโ this is the denominator n in the fraction 1/n ๐ฐ. a basic block needs an execution count above that fraction of the program's maximum block count to count as hot ๐ฅ. the default is10000, so a block is hot when its count is more than 1/10000 of the max ๐. setting it to0means nothing is ever hot ๐ฅ. this only applies in non-LTO mode, so don't mix it up with the LTO one ๐hot-bb-count-ws-permilleโ the number of most-executed permilles (somewhere from0to1000) of the whole program's profiled execution that a block's count has to belong to in order to be hot ๐. the default is990, which means a block is hot if its count is part of the top 990 permilles, aka 99.0%, of the profiled run ๐ท.0means nothing is ever hot. this one is used in LTO mode โจhot-bb-frequency-fractionโ the denominator n in the fraction 1/n of the entry block's execution frequency in a function ๐ฏ. a block in that function needs to hit this to be hot ๐ฅ. the default is1000, so a block is hot if it runs more often than 1/1000 of the entry block's frequency ๐ .0means it's never hot ๐unlikely-bb-count-fractionโ the denominator n in the fraction 1/n of the profiled runs of the whole program ๐ง. if a block's execution count is below that fraction, it's considered unlikely to be executed. the default is20, so a block is unlikely if it runs in fewer than 1/20, aka 5%, of the program's runs ๐ด.0means it's always considered unlikely ๐max-predicted-iterationsโ the max number of loop iterations the compiler predicts statically ๐ข. this helps when a function has one loop with a known bound and another with an unknown one ๐ง. the known count gets predicted right, but the unknown count averages out to about 10, so the unbounded loop looks artificially cold next to the other one ๐ฅถbuiltin-expect-probabilityโ controls the probability that an expression has the value you specified ๐ฒ. it takes a percentage, so anything from0to100๐ฏbuiltin-string-cmp-inline-lengthโ the max length of a constant string in a builtin string compare call that's allowed to get inlined ๐งตalign-thresholdโ picks a fraction of the maximal execution frequency of a basic block in a function, and that's what decides whether the block gets aligned ๐align-loop-iterationsโ any loop that's expected to iterate at least this many times gets aligned ๐ชtracer-dynamic-coverage,tracer-dynamic-coverage-feedbackโ this value limits superblock formation once a given percentage of executed instructions is covered ๐ง. it stops code size from blowing up for no reason ๐
The tracer-dynamic-coverage-feedback one is only used when profile feedback is available ๐. real profiles aren't as balanced as statically estimated ones, so the threshold can be set to a bigger value ๐
tracer-max-code-growthโ stops tail duplication once code growth hits this percentage ๐. honestly 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 (in percent) ๐tracer-min-branch-probability,tracer-min-branch-probability-feedbackโ stops forward growth if the best edge has a probability lower than this threshold ๐
These two work like the tracer-dynamic-coverage pair. tracer-min-branch-probability-feedback is for compiles with profile feedback, and tracer-min-branch-probability is for compiles without it ๐. the feedback value needs to be more conservative (higher) to make the tracer effective ๐ช
stack-clash-protection-guard-sizeโ sets the size of the operating system's stack guard, as 2 raised to num bytes ๐ก๏ธ. higher values can mean fewer explicit probes, but if the value is bigger than the OS-provided guard, your code is left open to stack clash style attacks ๐จstack-clash-protection-probe-intervalโ stack clash protection probes the stack as it gets allocated ๐. this param sets the max distance between those probes, as 2 raised to num bytes ๐. higher values can mean fewer explicit probes, but a value bigger than the OS-provided guard leaves code open to stack clash style attacks ๐ญmax-cse-path-lengthโ the max number of basic blocks on a path that CSE looks at ๐ค๏ธmax-cse-insnsโ the max number of instructions CSE processes before it flushes ๐ฟggc-min-expandโ GCC uses a garbage collector to manage its own memory ๐๏ธ. this sets the minimum percentage the collector's heap is allowed to grow between collections ๐ฆ. tuning it might speed up compilation, but it has zero effect on code generation ๐ โโ๏ธ
The default is 30% + 70% * (RAM/1GB), capped at 100% when RAM is at least 1GB ๐. if getrlimit is available, "RAM" means the smallest of actual RAM, RLIMIT_DATA, or RLIMIT_AS ๐ง . if GCC can't work out RAM on a platform, it falls back to the 30% lower bound ๐ฅบ. setting this and ggc-min-heapsize to zero makes a full collection happen at every opportunity. that's extremely slow, but it can be useful for debugging ๐๐ง
ggc-min-heapsizeโ the minimum size the garbage collector's heap has to reach before it starts bothering to collect garbage ๐งบ. the first collection happens after the heap grows byggc-min-expand% pastggc-min-heapsize๐ฑ. again, tuning this may speed up compilation, and it has no effect on code generation โจ
The default is the smallest of RAM/8, RLIMIT_RSS, or a limit that tries to make sure RLIMIT_DATA or RLIMIT_AS don't get exceeded ๐. but 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 really, really large basically turns garbage collection off ๐ซ. setting it and ggc-min-expand to zero makes a full collection happen at every opportunity ๐
max-reload-search-insnsโ the max number of instructions reload will look backward through to find an equivalent register ๐. higher values mean more aggressive optimization, which makes compile time go up with probably slightly better performance ๐๏ธmax-cselib-memory-locationsโ the max number of memory locations cselib should take into account ๐ง . higher values mean more aggressive optimization, which makes compile time go up with probably slightly better performance ๐max-sched-ready-insnsโ the max number of instructions that are ready to be issued the scheduler should consider at any given time during the first scheduling pass ๐๏ธ. higher values mean more thorough searches, which makes compile time go up with probably little benefit ๐ฅฑmax-sched-region-blocksโ the max number of blocks in a region that's considered for interblock scheduling ๐งฑmax-pipeline-region-blocksโ the max number of blocks in a region that's considered for pipelining in the selective scheduler ๐ชmax-sched-region-insnsโ the max number of insns in a region that's considered for interblock scheduling ๐ทmax-pipeline-region-insnsโ okay so this is the cap on how many insns a region can have before the selective scheduler even considers pipelining it ๐min-spec-probโ the minimum probability (in percents) that a source block gets reached before interblock speculative scheduling will go for it ๐ฎmax-sched-extend-regions-itersโ how many times the scheduler can loop through the CFG to extend regions ๐ Set it to0and region extensions are switched off totally ๐ โโ๏ธmax-sched-insn-conflict-delayโ the max conflict delay an insn can have and still be eligible for speculative motion ๐sched-spec-prob-cutoffโ the lowest chance of speculation success (in percents) that still gets speculative insns scheduled ๐ฏsched-state-edge-prob-cutoffโ the minimum probability an edge needs before the scheduler bothers saving 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, how deep it digs when hunting for available instructions ๐selsched-max-sched-timesโ how many times one instruction can get scheduled during selective scheduling. This is the cap on how many iterations it's allowed to 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 smallest stage count the swing modulo scheduler will generate ๐ขmax-last-value-rtlโ the max size, counted in RTLs, that the combiner can record in an expression as a pseudo register's last known value ๐max-combine-insnsโ the max number of instructions the RTL combiner will try to combine together ๐งฉinteger-share-limitโ small integer constants can share one data structure, which saves memory and makes things faster โก This sets the biggest value a shared integer constant can have ๐ssp-buffer-sizeโ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectoris on ๐ก๏ธmin-size-for-stack-sharingโ the minimum size of variables that join in on stack slot sharing when you're not optimizing ๐max-jump-thread-duplication-stmtsโ the max number of statements allowed in a block that has to be duplicated when threading jumps ๐งตmax-fields-for-field-sensitiveโ the max number of fields in a structure that get treated in a field sensitive way during pointer analysis ๐ฆprefetch-latencyโ an estimate of how many instructions, on average, run before a prefetch finishes โณ The distance prefetched ahead scales with this number ๐ Cranking it up might 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โ this decides whether the loop array prefetch pass issues software prefetch hints for strides that aren't constant ๐ Sometimes that's a win, but a non-constant stride can make it really hard to tell when the hints actually help ๐ค
Set it to 1 and hints get issued for non-constant strides โ
Set it to 0 and hints only get issued for strides that are known to be constant and sit below prefetch-minimum-stride ๐
โโ๏ธ
prefetch-minimum-strideโ the minimum constant stride, in bytes, before prefetch hints start getting used ๐ If the stride is smaller than this threshold, no prefetch hints get issued ๐ซฅ
This one is a lifesaver for processors with hardware prefetchers ๐ซถ If both kinds of prefetcher are fighting each other, you can use this setting to keep them from clashing. If the hardware prefetchers have a maximum stride they can handle, put that number here so the software prefetchers get used better ๐ง
A value of -1 means there's no threshold at all, so prefetch hints can get issued for any constant stride โพ๏ธ
This setting only matters for strides that are known and constant ๐
destructive-interference-size,constructive-interference-sizeโ these set the values for the C++17 variables"std::hardware_destructive_interference_size"and"std::hardware_constructive_interference_size"๐
The destructive interference size is the minimum recommended offset between two independent objects that are accessed concurrently, in bytes ๐ฅ 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 interference size is typically the small end of that range, and the destructive size is typically the large end ๐
The destructive interference size is meant for layout, so it has ABI impact โ ๏ธ Its default value isn't expected to stay stable, and on some targets it changes with -mtune ๐ญ So using it somewhere ABI stability really matters, like the public interface of a library, is strongly discouraged ๐ซ If you do end up using it there, users can lock the value in place with this option ๐
The constructive interference size is way less sensitive, since it's usually only used in a static_assert to make sure a type fits inside a cache line ๐
See also -Winterference-size ๐
loop-interchange-max-num-stmtsโ the max number of stmts 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 turn on 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 turn on prefetching in a loop ๐use-canonical-typesโ whether the compiler uses the "canonical" type system ๐งฌ This should always be1, since it uses a more efficient internal mechanism for 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 refuses to make arrays bigger than this value times the number of branches in the switch ๐max-partial-antic-lengthโ the max length of the partial antic set computed during tree partial redundancy elimination (-ftree-pre) when you're optimizing at-O3and above ๐ง For some kinds of source code, the enhanced PRE can run away and eat all the memory on the host machine ๐ฑ This parameter caps how long those sets can get, so the runaway behavior can't happen ๐ Setting it to0allows an unlimited set length ๐rpo-vn-max-loop-depthโ the max loop depth that gets value-numbered optimistically ๐ข When the limit gets hit, the innermostrpo-vn-max-loop-depthloops, plus the outermost loop in the loop nest, get value-numbered optimistically, and the remaining ones don't ๐ชsccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries performed while looking for redundancies in loads and stores ๐ If this limit is hit, the search is aborted and the load or store is not considered redundant ๐ The number of queries is algorithmically limited to the number of stores on all paths from the load to the function entry ๐งญira-max-loops-numโ IRA uses regional register allocation by default ๐บ๏ธ If a function has more loops than the number given here, only that many of the most frequently executed loops form regions for regional register allocation ๐ira-max-conflict-table-sizeโ IRA uses a fancy algorithm to compress the conflict table, but for huge functions the table can still eat an excessive amount of memory ๐ฅต If a function's conflict table could be bigger than the size in MB given here, the register allocator switches to a faster, simpler, lower-quality algorithm that doesn't need to build a pseudo-register conflict table ๐๏ธira-loop-reserved-regsโ IRA can be used to evaluate more accurate register pressure in loops, which helps decide when to move loop invariants (see-O3) ๐ This parameter gives the number of available registers reserved for other purposes ๐งธ The default is the best value found through lots of experiments ๐งชira-consider-dup-in-all-altsโ this makes IRA consider matching constraints (duplicated operand numbers) really heavily across all available alternatives for the preferred register class ๐ฆ If it's set to zero, IRA only respects the matching constraint when it's the only available alternative with an appropriate register class ๐ Otherwise, IRA checks all available alternatives for the preferred register class, even after it's found a choice with an appropriate register class, and still respects the qualified matching constraint it found ๐lra-inheritance-ebb-probability-cutoffโ LRA tries to recycle values it already reloaded into registers for later insns, and that trick is called inheritance โจ EBB is the region used for this optimization. This sets the minimal fall-through edge probability, in percent, for pulling a BB into the inheritance EBB in LRA. The default was picked after numerous runs of SPEC2000 on x86-64 ๐loop-invariant-max-bbs-in-loopโ Loop invariant motion can be super expensive, both in compile time and in how much compile-time memory it eats, especially with huge loops ๐ญ Any loop with more basic blocks than this value just won't get loop invariant motion ๐ โโ๏ธloop-max-datarefs-for-datadepsโ Building data dependencies is pricey for very large loops ๐ This caps how many data references in a loop get considered for data dependence analysis. Loops that are bigger than that aren't handled by the optimizations that rely on loop data dependencies ๐ฆmax-vartrack-sizeโ Sets a max number of hash table slots that can be used during variable tracking dataflow analysis for any function ๐ If you go over that while variable tracking at assignments is on, the analysis gets retried without it, after all debug insns are removed from the function. If you're still over the limit without debug insns, var tracking analysis is totally disabled for that function ๐ค Setting this to zero makes it unlimited โพ๏ธmax-vartrack-expr-depthโ Sets a max number of recursion levels when mapping variable names or debug temporaries to value expressions ๐ง It's a trade-off: more compile time for more complete debug info โฑ๏ธ If it's set too low, value expressions that could show up in debug info might get skipped. Setting it higher lets the compiler find fancier debug expressions, but compile time and memory use can grow ๐max-debug-marker-countโ A threshold on how many debug markers (like begin stmt markers) are allowed, so things don't blow up when inlining or expanding to RTL ๐ If a function has more of these gimple stmts than the limit, they get dropped from the inlined copy of the function and from its RTL expansion ๐ซmin-nondebug-insn-uidโ Uids start at this value for nondebug insns ๐ข The range below it is reserved for debug insns created by-fvar-tracking-assignments. But if that reserved range runs out, debug insns can still get (non-overlapping) uids above it ๐ซถipa-sra-ptr-growth-factorโ IPA-SRA only swaps a pointer to an aggregate for one or more new parameters if their combined size is less than or equal to this factor times the size of the original pointer parameter ๐ipa-sra-max-replacementsโ The max pieces of an aggregate that IPA-SRA keeps track of ๐งฉ That also means it's the max number of replacements for a formal parameter ๐sra-max-scalarization-size-Ospeedsra-max-scalarization-size-Osizeโ Both of these are for the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) ๐ฐ They try to swap scalar parts of aggregates for uses of independent scalar variables โจ These params set the max size, in storage units, of an aggregate that's even considered for replacement.sra-max-scalarization-size-Ospeedis for when you're compiling for speed ๐๏ธ, andsra-max-scalarization-size-Osizeis for when you're compiling for size ๐ฆsra-max-propagationsโ The max number of artificial accesses that Scalar Replacement of Aggregates (SRA) will track per local variable, so it can do copy propagation ๐tm-max-aggregate-sizeโ When copying thread-local variables inside a transaction, this sets the size in bytes after which variables get saved with the logging functions instead of save/restore code sequence pairs ๐ This only matters when you're using-fgnu-tm๐graphite-max-nb-scop-paramsโ To avoid exponential chaos in the Graphite loop transforms, the number of parameters in a Static Control Part (SCoP) is capped ๐ โโ๏ธ Set it to zero to lift the cap ๐ A variable whose value isn't known at compile time and is defined outside a SCoP counts as a parameter of that SCoP ๐งฎloop-block-tile-sizeโ Loop blocking and strip mining (turned on with-floop-blockor-floop-strip-mine) strip mine each loop in the loop nest by a given number of iterations ๐ฅ You can change the strip length with this param ๐๏ธipa-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 function ๐ipa-cp-eval-thresholdโ IPA-CP calculates its own score for how profitable cloning is, based on heuristics ๐งฎ It goes ahead with the cloning opportunities whose scores beatipa-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 param ๐ฒipa-cp-profile-count-baseโ When you use-fprofile-use, IPA-CP looks at the measured execution count of a call graph edge at this percentage position in its histogram ๐ That number becomes the basis for its heuristics calculation ๐งipa-cp-recursive-freq-factorโ How many times interprocedural copy propagation expects recursive functions to call themselves ๐ipa-cp-recursion-penaltyโ The percentage penalty that recursive functions get when they're evaluated for cloning ๐ฌipa-cp-single-call-penaltyโ The percentage penalty that functions with 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 in an aggregate ๐ This controls the max number of those values for each parameter ๐ขipa-cp-loop-hint-bonusโ When IPA-CP figures out that 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 will use to describe when loops in a function have known properties ๐ฎipa-max-aa-stepsโ While analyzing function bodies, IPA-CP uses alias analysis to track values pointed to by function parameters ๐ต๏ธโโ๏ธ To keep huge functions from taking forever, it gives up and treats all memory as clobbered after looking atipa-max-aa-stepsstatements that modify memory ๐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 (used to estimate cloning benefit) for the switch's default case ๐ซipa-max-param-expr-opsโ IPA-CP will look 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 thanipa-max-param-expr-ops, it's treated as too complicated and skipped by IPA analysis ๐ โโ๏ธlto-partitionsโ The desired number of partitions made during WHOPR compilation ๐งฉ It should be more than the number of CPUs you're compiling with ๐ปlto-min-partitionโ The size of the minimal partition for WHOPR, in estimated instructions ๐ฃ This stops tiny programs from getting split into way too many partitions ๐lto-max-partitionโ The size of the max partition for WHOPR, in estimated instructions ๐ It gives an upper bound on how big any single partition can get ๐งฑ This is 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โ The max number of namespaces to check for suggestions when C++ name lookup fails for an identifier ๐๐sink-frequency-thresholdโ The max relative execution frequency (in percent) of the target block, compared to a statement's original block, that still allows that statement to be sunk ๐ Bigger numbers mean more aggressive statement sinking ๐ฅ Statements with memory operands get a small positive adjustment, since sinking those is even more profitable ๐max-stores-to-sinkโ The max number of conditional store pairs that can be sunk ๐ณ๏ธ Set it to 0 if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is turned off ๐ซcase-values-thresholdโ The smallest number of different values for which a jump table is better than a tree of conditional branches ๐ณ If it's 0, the machine's default gets used ๐คjump-table-max-growth-ratio-for-sizeโ The max code size growth ratio when expanding into a jump table, in percent ๐ฆ This one applies when you're optimizing for size ๐jump-table-max-growth-ratio-for-speedโ The max code size growth ratio when expanding into a jump table, in percent ๐๏ธ This one applies when you're optimizing for speed ๐จtree-reassoc-widthโ ๐ธ okay so this one sets the max number of instructions that can run in parallel inside a reassociated tree. If you give it a non-zero value, it overrides the target-dependent heuristics that would otherwise be used by default โจsched-pressure-algorithmโ ๐ฆ bestie, this picks between the two implementations of-fsched-pressure. Algorithm 1 is the OG version and is the more likely one to stop instructions from getting reordered. Algorithm 2 is the compromise between algorithm 1's cautious energy and the default scheduler's pretty aggressive approach. It leans harder on having a regular register file and accurate register pressure classes. For the deep dive, check outhaifa-sched.ccin the GCC sources ๐ The default choice depends on the target ๐max-slsr-cand-scanโ ๐ this caps how many existing candidates get looked at when the compiler is 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 the global objects protection, use--param asan-globals=0๐ โโ๏ธasan-stackโ ๐งฑ same vibe, but for stack objects. It's on by default with-fsanitize=address. To skip stack protection, use--param asan-stack=0๐asan-instrument-readsโ ๐ enables buffer overflow detection for memory reads. Also on by default with-fsanitize=address. To disable the memory reads protection, use--param asan-instrument-reads=0โจasan-instrument-writesโ โ๏ธ the writes version of the above. On by default with-fsanitize=address. To turn it off, use--param asan-instrument-writes=0๐ซถasan-memintrinโ ๐ง enables detection for built-in functions. Enabled by default with-fsanitize=address. To disable built-in functions protection, use--param asan-memintrin=0๐asan-use-after-returnโ โฐ enables detection of use-after-return. It's on by default when you use-fsanitize=address. To disable it, use--param asan-use-after-return=0๐
โ ๏ธ Heads up: the check is disabled at run time by default! To turn it on, add"detect_stack_use_after_return=1"to the environment variableASAN_OPTIONS๐ญ
asan-instrumentation-with-call-thresholdโ ๐ if a function being instrumented has memory accesses greater than or equal to this number, the compiler uses callbacks instead of inline checks. Want to skip the inline code entirely? Use--param asan-instrumentation-with-call-threshold=0๐hwasan-instrument-stackโ ๐ enables hwasan instrumentation of statically sized stack-allocated variables. This is on by default with-fsanitize=hwaddressand off by default with-fsanitize=kernel-hwaddress. To disable stack instrumentation, 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 running, tags for stack variables come from a deterministic sequence that starts at a random tag for each frame. If this param is left unset, the same sequence is used but starts at 1 instead. It's enabled by default for-fsanitize=hwaddressand unavailable for-fsanitize=kernel-hwaddress. To disable it, use--param hwasan-random-frame-tag=0๐ฆhwasan-instrument-allocasโ ๐ท enables hwasan instrumentation of dynamically sized stack-allocated variables. On by default with-fsanitize=hwaddress, off by default with-fsanitize=kernel-hwaddress. To skip instrumenting these, use--param hwasan-instrument-allocas=0, and to turn it on, use--param hwasan-instrument-allocas=1๐hwasan-instrument-readsโ ๐ enables hwasan checks on memory reads. Read instrumentation is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To stop checking memory reads, use--param hwasan-instrument-reads=0๐ซงhwasan-instrument-writesโ ๐ enables hwasan checks on memory writes. Write instrumentation is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To stop checking memory writes, use--param hwasan-instrument-writes=0๐ซhwasan-instrument-mem-intrinsicsโ ๐งฉ enables hwasan instrumentation of builtin functions. This is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To turn off instrumentation of builtin functions, use--param hwasan-instrument-mem-intrinsics=0๐ธuse-after-scope-direct-emission-thresholdโ ๐ if a local variable's size in bytes is smaller than or equal to this number, the compiler directly poisons (or unpoisons) shadow memory instead of making run-time callbacks ๐งtsan-distinguish-volatileโ ๐ emits special instrumentation for accesses to volatiles. Very specific, very iconic ๐tsan-instrument-func-entry-exitโ ๐ช emits instrumentation calls to__tsan_func_entry()and__tsan_func_exit()โจmax-fsm-thread-path-insnsโ ๐งต the max number of instructions to copy when duplicating blocks on a finite state automaton jump thread path ๐max-fsm-thread-lengthโ ๐ the max number of basic blocks on a jump thread path ๐threader-debugโ ๐threader-debug=[none|all]turns on verbose dumping of the threader solver. Lots of tea spilled here ๐ซparloops-chunk-sizeโ ๐ง the chunk size of the omp schedule for loops parallelized by parloops ๐parloops-scheduleโ ๐๏ธ the schedule type of the omp schedule for loops parallelized by parloops. Pick fromstatic,dynamic,guided,auto, orruntime๐parloops-min-per-threadโ ๐งต the minimum number of iterations per thread of an innermost parallelized loop for which the parallelized version is preferred over the single-threaded one. Quick note: for a parallelized loop nest, the minimum number of iterations of the outermost loop per thread is two โจmax-ssa-name-query-depthโ ๐ช the max recursion depth when querying properties of SSA names in things like fold routines. One level of recursion means following one use-def chain ๐max-speculative-devirt-maydefsโ ๐ต๏ธ the max number of may-defs analyzed while looking for a must-def that specifies the dynamic type of an object invoking a virtual call. That's the call we might be able to devirtualize speculatively ๐ฆmax-vrp-switch-assertionsโ ๐ the max number of assertions to add along the default edge of a switch statement during VRP ๐evrp-sparse-thresholdโ ๐ชถ the max number of basic blocks before EVRP switches over to a sparse cache ๐งบevrp-modeโ ๐๏ธ specifies the mode Early VRP should operate in ๐ทvrp1-modeโ ๐๏ธ specifies the mode VRP pass 1 should operate in ๐vrp2-modeโ ๐๏ธ specifies the mode VRP pass 2 should operate in ๐ranger-debugโ ๐ specifies the type of debug output to be issued for ranges ๐evrp-switch-limitโ ๐ the max number of switch cases before EVRP just ignores a switch altogether ๐ โโ๏ธunroll-jam-min-percentโ ๐ the min percentage of memory references that must be optimized away for the unroll-and-jam transformation to be considered profitable ๐ฐunroll-jam-max-unrollโ ๐ the max number of times the outer loop gets unrolled by the unroll-and-jam transformation ๐งถmax-rtl-if-conversion-unpredictable-costโ ๐ธ the max permissible cost for the sequence the RTL if-conversion pass would generate for a branch that's considered unpredictable ๐ซmax-variable-expansions-in-unrollerโ ๐ if-fvariable-expansion-in-unrolleris used, this is the max number of times a single variable gets expanded during loop unrolling ๐งฉpartial-inlining-entry-probabilityโ ๐ฏ the max probability of the entry BB of a split region (as a percent of the function's entry BB) that still lets partial inlining happen ๐งmax-tracked-strlensโ ๐งต the max number of strings whose lengths the strlen optimization pass will track ๐gcse-after-reload-partial-fractionโ ๐ the threshold ratio for performing partial redundancy elimination after reload ๐ซถgcse-after-reload-critical-fractionโ ๐ the threshold ratio of critical edges' execution count that permits redundancy elimination 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โ ๐ enables loop epilogue vectorization using a smaller vector size ๐ฆvect-partial-vector-usageโ ๐งฉ controls when the loop vectorizer considers partial vector loads and stores instead of falling back to scalar code. This only matters on targets that support partial vector loads and stores. The levels are:0โ the vectorizer never uses partial vector loads and stores ๐ โโ๏ธ1โ partial vector loads and stores are allowed if vectorization removes the need for the code to iterate ๐2โ partial vector loads and stores are allowed in all loops ๐
vect-inner-loop-cost-factorโ ๐งฎ the max factor the loop vectorizer applies to the cost of statements in an inner loop, relative to the loop being vectorized. The factor used is the max of the estimated number of iterations of the inner loop and this parameter. The default value is 50 ๐avoid-fma-max-bitsโ ๐ซ the max number of bits for which we avoid creating FMAs โจsms-loop-average-count-thresholdโ ๐ a threshold on the average loop count considered by the swing modulo scheduler ๐ฅsms-dfa-historyโ okay so this one sets how many cycles the swing modulo scheduler looks at when it checks for conflicts using the DFA ๐ฅgraphite-allow-codegen-errorsโ decides whether codegen errors count as ICEs (internal compiler errors) when-fcheckingis on ๐sms-max-ii-factorโ a tuning knob for the upper bound the swing modulo scheduler uses when it schedules a loop ๐lra-max-considered-reload-pseudosโ the max number of reload pseudos that get considered while spilling a non-reload pseudo ๐ฆmax-pow-sqrt-depthโ the max depth of sqrt chains allowed 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โ sets a bound on how expensive an expression can be when GCC computes the number of iterations ๐max-isl-operationsโ the max number of isl operations, where0means no limit at all โจgraphite-max-arrays-per-scopโ the max number of arrays allowed per scop ๐max-vartrack-reverse-op-sizeโ the max size of a loc list for which reverse ops are allowed to get added ๐fsm-scale-path-stmtsโ a scale factor applied to the number of statements in a threading path, used when comparing against the number of (scaled) blocks โญuninit-control-dep-attemptsโ the max number of nested calls allowed while hunting for control dependencies during uninitialized variable analysis ๐fsm-scale-path-blocksโ a scale factor applied to the number of blocks in a threading path, used when comparing against the number of (scaled) statements ๐sched-autopref-queue-depthโ a control flag for the hardware autoprefetcher scheduler model. It sets how many lookahead cycles the model peeks into, and at' 'it only turns on 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 same idea for an outer loop, except any instructions in inner loops that directly benefit from versioning don't count toward the total ๐ssa-name-def-chain-limitโ the max number of SSA_NAME assignments GCC will follow when figuring out a property of a variable, like its value. It caps how many iterations or recursive calls GCC makes while 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 done 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 a point hits this, analysis of that point stops ๐งanalyzer-max-constraintsโ the max number of constraints per state ๐analyzer-min-snodes-for-call-summaryโ the minimum number of supernodes a function needs before the analyzer bothers summarizing its effects at call sites โจanalyzer-max-enodes-for-full-dumpโ the max depth of exploded nodes that can show up in a dot dump before the output switches to a less verbose format ๐analyzer-max-recursion-depthโ the max number of times a callsite can show up in a call stack inside the analyzer. Once that's reached, analysis of a call that would recurse deeper gets terminated ๐analyzer-max-svalue-depthโ the max depth of a symbolic value. Anything deeper gets approximated as unknown โญanalyzer-max-infeasible-edgesโ the max number of infeasible edges the analyzer will reject before it declares a diagnostic infeasible ๐gimple-fe-computed-hot-bb-thresholdโ the number of executions a basic block needs before it counts as hot. This one is only used in GIMPLE FE ๐analyzer-bb-explosion-factorโ the max number of'after supernode'exploded nodes per supernode in the analyzer, before analysis gets terminated ๐ฅranger-logical-depthโ the max depth of logical expression evaluation that ranger will look through when it evaluates outgoing edge ranges ๐ซถrelation-block-limitโ the max number of relations the oracle will register in a basic block ๐openacc-kernelsโ picks the mode for handling OpenACCkernelsconstructs. With--param=openacc-kernels=decompose, the constructs get split into parts, a sequence of compute constructs that each get handled on their own. This one is still work in progress. With--param=openacc-kernels=parloops, the constructs get handled en bloc by the parloops pass. This is the current default ๐openacc-privatizationโ picks the mode for OpenACC privatization diagnostics, which show up with-fopt-info-omp-noteand applicable-fdump-tree-*-details. With--param=openacc-privatization=quiet, nothing gets diagnosed, and this is the current default. With--param=openacc-privatization=noisy, the diagnostics do get printed ๐ธ
Heads up, these next ones are only available on AArch64 targets ๐
aarch64-sve-compare-costsโ when vectorizing for SVE, GCC considers using "unpacked" vectors for smaller elements and uses the cost model to pick the cheapest approach. It also uses the cost model to choose between SVE and Advanced SIMD vectorization.- Using unpacked vectors means 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 the float type. When division approximation is enabled, the precision of division scales with this param. The default value is 1.aarch64-double-recp-precisionโ the number of Newton iterations used to calculate the reciprocal for the double type. When division approximation is enabled, the precision of division scales with this param. The default value is 2.aarch64-autovec-preferenceโ forces an ISA selection strategy for auto-vectorization. It accepts values from 0 to 4, inclusive.0โ uses the default heuristics.1โ uses only Advanced SIMD for auto-vectorization.2โ uses only SVE for auto-vectorization.3โ uses both Advanced SIMD and SVE, and prefers Advanced SIMD when the costs are deemed equal.4โ uses both Advanced SIMD and SVE, and prefers SVE when the costs are deemed equal.
The default value is 0.
aarch64-loop-vect-issue-rate-nitersโ some AArch64 CPU tuning weighs both latencies and issue rates when deciding whether a loop should be vectorized with SVE, vectorized with Advanced SIMD, or not vectorized at all. If this param is set ton, GCC won't use this heuristic for loops known to execute in fewer thannAdvanced SIMD iterations.
โจ Program Instrumentation Options โจ
GCC supports a bunch of command-line options that tack runtime instrumentation onto the code it normally generates. One reason to instrument is to collect profiling stats for finding hot spots, doing code coverage analysis, or running profile-guided optimizations. Another kind of instrumentation adds runtime checks that catch programming errors, like invalid pointer dereferences or out-of-bounds array accesses, plus deliberately hostile attacks like stack smashing or C++ vtable hijacking. There's also a general hook that can be used to build other kinds of tracing or function-level instrumentation for debugging or program analysis ๐
-p,-pgโ generates extra code that writes profile information for the analysis programprof(with-p) orgprof(with-pg). You have to use this option when compiling the source files you want data about, and you have to use it when linking too ๐- 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 get instrumented. While the program runs, it records how many times each branch and call is executed, and how many times each one is taken or returns. On targets that support constructors with priority support, profiling 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 can be used for profile-directed optimizations (-fbranch-probabilities) or for test coverage analysis (-ftest-coverage). - Each object file's
auxnameis generated from the name of the output file, if one is explicitly specified and it isn't the final executable. Otherwise, it's the basename of the source file. In both cases any suffix gets removed. For example,foo.gcdafor input filedir/foo.c, ordir/foo.gcdafor output file specified as-o dir/foo.o.
- When the compiled program exits, it saves this data to a file called
--coverageโ used to compile and link code that's instrumented for coverage analysis. It's a synonym for-fprofile-arcs-ftest-coveragewhen compiling, and for-lgcovwhen linking. Check out the docs for those options for more details ๐ฆ- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, add the extra-ftest-coverageoption. You don't need to profile every source file in a program ๐ - Also compile the source files with
-fprofile-abs-pathto create absolute path names in the.gcnofiles. This helps gcov find the correct sources in projects where compilations happen from different working directories ๐ซถ
- Compile the source files with
- Step three, the fun part ๐: link your object files with
-lgcovor-fprofile-arcs. The latter implies the former, so you're basically getting two for one โจ. - Step four, run it ๐โโ๏ธ: run the program on a representative workload to generate the arc profile information. You can repeat this as many times as you want. You can even run concurrent instances of your program, and as long as the file system supports locking, your data files will be updated correctly ๐
. Unless a strict ISO C dialect option is in effect,
forkcalls are detected and handled correctly without double counting ๐ซถ.
Moreover, an object file can be recompiled multiple times, and the matching .gcda file merges as long as the source file and the compiler options haven't changed. Iconic โจ.
- Step five, profile-directed optimizations ๐ฅ: compile the source files again with the same optimization and code generation options, plus
-fbranch-probabilities. - Step six, test coverage ๐ฆ: use
gcovto turn the.gcnoand.gcdafiles into human-readable info. Check the gcov documentation for more details, bestie ๐.
So with -fprofile-arcs, GCC builds a program flow graph for each function in your program, then finds a spanning tree for that graph ๐ณ. Only the arcs that are not on the spanning tree need instrumenting. The compiler adds code to count how many times those arcs get executed. When an arc is the only exit or the only entrance to a block, the instrumentation code can go right into that block. Otherwise, a new basic block has to be created to hold it. Main character energy ๐.
-ftest-coverage
Okay so this one makes a notes file that the gcov code-coverage utility can use to show your program's coverage ๐. Each source file's notes file is called auxname.gcno. For what auxname means and how to actually generate test coverage data, look at the -fprofile-arcs option above ๐ธ. Coverage data matches your source files more closely if you do not optimize ๐.
-fprofile-abs-path
This one is giving organization ๐๏ธ. It automatically converts relative source file names into absolute path names in the .gcno files. That lets gcov find the correct sources in projects where compilations happen from different working directories. No more lost files, bestie ๐ง.
-fprofile-dir=path
This sets the directory where profile data files get searched for, to path ๐. It only affects the profile data generated by -fprofile-generate, -ftest-coverage, and -fprofile-arcs, and the profile data used by -fprofile-use, -fbranch-probabilities, and their related options ๐. Both absolute and relative paths work. By default, GCC uses the current directory as path, so the profile data file lives 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.gcda file and uses that as the name of a .gcda file. See the similar option -fprofile-note ๐ฆ.
When your executable runs in a massive parallel environment, it's recommended to save profiles into different folders ๐. You can do that with variables in path that get exported at run-time:
%pโ process ID.%q{VAR}โ value of environment variableVAR
-fprofile-generate, -fprofile-generate=path
This one turns on the options usually used for instrumenting an application, so you get a profile that's useful for recompiling later with profile feedback based optimization ๐ฅ. You must use -fprofile-generate both when compiling and when linking your program, no skipping ๐
โโ๏ธ.
These options get enabled too: -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 your program based on the collected profile information, use -fprofile-use ๐
.
-fprofile-info-section, -fprofile-info-section=name
This one puts the profile information into 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 generated by -fprofile-arcs gets placed in that section for each translation unit. This option disables the profile information registration through a constructor, and it also disables the profile information processing through a destructor ๐.
This option isn't meant for hosted environments like GNU/Linux. It's for free-standing environments (like embedded systems) with limited resources, which don't support constructors/destructors or C library file I/O ๐งธ.
The linker can collect the input sections into one continuous memory block and define start and end symbols ๐ง . Here's a GNU linker script example that defines a linker output section:
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
Your program can then dump the profiling information registered in this linker set, like this ๐:
#include <gcov.h>
#include <stdio.h>
#include <stdlib.h>
extern const struct gcov_info *__gcov_info_start[];
extern const struct gcov_info *__gcov_info_end[];
static void
filename (const char *f, void *arg)
{
puts (f);
}
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 *
allocate (unsigned length, void *arg)
{
return malloc (length);
}
static void
dump_gcov_info (void)
{
const struct gcov_info **info = __gcov_info_start;
const struct gcov_info **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()
{
dump_gcov_info();
return 0;
}
-fprofile-note=path
If path is specified, GCC saves the .gcno file into the path location ๐. Heads up, bestie: if you combine this with multiple source files, the .gcno file will get overwritten ๐ญ.
-fprofile-prefix-path=path
This one works together with profile-generate=profile_dir and profile-use=profile_dir to tell GCC where the base directory of your built source tree is ๐บ๏ธ. By default, profile_dir holds 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. Then the profile data won't be found during the optimized build ๐. In that setup, -fprofile-prefix-path=path with path pointing at the base directory of the build strips the irrelevant part of the path and keeps every file name relative to the main build directory ๐ธ.
-fprofile-prefix-map=old=new
When compiling files that live in directory old, GCC records profiling information (with --coverage) describing them as if they lived in directory new instead ๐ฆ. See also -ffile-prefix-map.
-fprofile-update=method
This alters the update method for an application instrumented for profile feedback based optimization ๐ง. The method argument should be one of single, atomic, or prefer-atomic. single is useful for single-threaded applications, while atomic prevents profile corruption by emitting thread-safe code ๐งต.
Warning: if an application doesn't properly join all threads (or creates a detached thread), a profile file can still get corrupted ๐จ.
Using prefer-atomic gets transformed into atomic when a target supports it, or into single otherwise ๐. The GCC driver automatically selects prefer-atomic when -pthread is in the command line โจ.
-fprofile-filter-files=regex
Only instruments functions from files whose name matches any of the regular expressions (separated by semi-colons) ๐.
For example, -fprofile-filter-files=main\.c;module.*\.c will instrument only main.c and all C files starting with 'module' ๐.
-fprofile-exclude-files=regex
Only instruments functions from files whose name does not match any of the regular expressions (separated by semi-colons) ๐ซ.
For example, -fprofile-exclude-files=/usr/.* will prevent instrumentation of all files located in the /usr/ folder ๐งน.
-fprofile-reproducible=[multithreaded|parallel-runs|serial]
This controls how reproducible the profile gathered by -fprofile-generate is ๐. That 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 gathered profile is reproducible, as long as the trained program behaves the same way on each invocation of the train run, it isn't multi-threaded, and profile data streaming always happens in the same order ๐ซถ. Profile streaming happens at the end of the program run, but also before the fork function is invoked, so keep that in mind ๐ง .
It's pretty common for execution counts in some parts of programs to depend on things like the length of temporary file names or memory space randomization (which can affect hash-table collision rate) ๐. Non-reproducible parts like that can be annotated with the no_instrument_function function attribute. You can use gcov-dump with -l to dump the gathered data and verify that it's actually reproducible ๐๐.
With -fprofile-reproducible=parallel-runs, the collected profile stays reproducible no matter what order the data gets streamed into the gcda files โจ. This setting lets you run several instances of your instrumented program at once (like with make -j) ๐โโ๏ธ. Ngl there's a trade-off: it lowers the quality of the gathered data, especially for indirect call profiling ๐ญ.
๐ฆ -fsanitize=address
Okay bestie, this one turns on AddressSanitizer, a fast memory error detector ๐ฅ. The memory access instructions get instrumented so it can catch out-of-bounds and use-after-free bugs. This option also turns on -fsanitize-address-use-after-scope. For more deets, check https://github.com/google/sanitizers/wiki/AddressSanitizer. You can tweak the run-time behavior with the ASAN_OPTIONS environment variable ๐
. When ASAN_OPTIONS is set to "help=1", the instrumented program shows you the available options at startup. The list of supported options lives at https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags. This option can't be combined with -fsanitize=thread or -fsanitize=hwaddress ๐.
๐ธ -fsanitize=kernel-address
Enable AddressSanitizer for the Linux kernel ๐ง. More details are at https://github.com/google/kasan.
๐ง -fsanitize=hwaddress
Enable Hardware-assisted AddressSanitizer, which is seriously iconic ๐คฏ. It uses a hardware ability to ignore the top byte of a pointer, so it can detect memory errors with a low memory overhead. The memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs. This option also turns on -fsanitize-address-use-after-scope. See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html for more details. The run-time behavior can be influenced with the HWASAN_OPTIONS environment variable. When it's set to "help=1", the available options show up at startup of the instrumented program. It can't be combined with -fsanitize=thread or -fsanitize=address, and it's currently only available on AArch64.
Note that the only target -fsanitize=hwaddress is currently supported on is AArch64.
๐ -fsanitize=kernel-hwaddress
Enable Hardware-assisted AddressSanitizer for compiling the Linux kernel ๐ง . It's similar to -fsanitize=kernel-address because it's kernel-focused, but it uses an alternate instrumentation method. It's also similar to -fsanitize=hwaddress, but with instrumentation differences that 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 the-fsanitize=hwaddress. Instrumenting the stack and alloca calls is not on by default, but you can still turn it on with the command-line options--param hwasan-instrument-stack=1and--param hwasan-instrument-allocas=1respectively. Using a random frame tag is not implemented for kernel instrumentation.
๐ -fsanitize=pointer-compare
This instruments comparison operations (<, <=, >, >=) with pointer operands โจ. It must be combined with either -fsanitize=kernel-address or -fsanitize=address, and it cannot be combined with -fsanitize=thread.
Note: By default the check is disabled at run time. To enable it, add"detect_invalid_pointer_pairs=2"to the environment variableASAN_OPTIONS. Using"detect_invalid_pointer_pairs=1"only detects invalid operation when both pointers are non-null.
๐ -fsanitize=pointer-subtract
This instruments subtraction with pointer operands ๐ฐ. It must be combined with either -fsanitize=kernel-address or -fsanitize=address, and it cannot be combined with -fsanitize=thread.
Note: By default the check is disabled at run time. To enable it, add"detect_invalid_pointer_pairs=2"to the environment variableASAN_OPTIONS. Using"detect_invalid_pointer_pairs=1"only detects invalid operation when both pointers are non-null.
๐ก๏ธ -fsanitize=shadow-call-stack
Enable ShadowCallStack, a security glow-up that protects programs against return address overwrites (e.g. stack buffer overflows.) ๐ก๏ธ It works by saving a function's return address to a separately allocated shadow call stack in the function prologue, then restoring the return address from that shadow call stack in the function epilogue. Instrumentation only happens in functions that need to save the return address to the stack.
Right now it only supports the aarch64 platform ๐ค. It's specifically designed for Linux kernels that enable the CONFIG_SHADOW_CALL_STACK option. For user space programs, runtime support is not currently provided in libc and libgcc. 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 uses the platform register "x18". This generally means that any code that may run on the same thread as code compiled with ShadowCallStack must be compiled with -ffixed-x18. Otherwise, functions compiled without -ffixed-x18 might clobber "x18" and corrupt the shadow stack pointer ๐ฑ.
Also, because there's no userspace runtime support, code compiled with ShadowCallStack cannot use exception handling. Use -fno-exceptions to turn off exceptions.
See https://clang.llvm.org/docs/ShadowCallStack.html for more details.
๐งต -fsanitize=thread
Enable ThreadSanitizer, a fast data race detector ๐๏ธ. Memory access instructions get instrumented to detect data race bugs. See https://github.com/google/sanitizers/wiki#threadsanitizer for more details. The run-time behavior can be influenced using the TSAN_OPTIONS environment variable. Check https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags for a list of supported options. This option cannot be combined with -fsanitize=address or -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
Enable LeakSanitizer, a memory leak detector ๐ซง. This option only matters for linking executables, and only when the executable is linked against a library that overrides "malloc" and other allocator functions. See https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer for more details. The run-time behavior can be influenced using the LSAN_OPTIONS environment variable. This option cannot be combined with -fsanitize=thread.
๐ -fsanitize=undefined
Enable UndefinedBehaviorSanitizer, a fast undefined behavior detector ๐. Various computations are instrumented to detect undefined behavior at runtime. See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html for more details. The run-time behavior can be influenced using the UBSAN_OPTIONS environment variable. These are the current suboptions:
-fsanitize=shiftโ This checks that the result of a shift operation is not undefined. What exactly counts as undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc. This option has two suboptions,-fsanitize=shift-baseand-fsanitize=shift-exponent.-fsanitize=shift-exponentโ This checks that the second argument of a shift operation is not negative and is smaller than the precision of the promoted first argument.-fsanitize=shift-baseโ If the second argument of a shift operation is within range, this checks that the result of the shift operation is not undefined. Again, what exactly counts as undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc.-fsanitize=integer-divide-by-zeroโ Detects integer division by zero ๐ โโ๏ธ.-fsanitize=unreachableโ With this option, the compiler turns the"__builtin_unreachable"call into a diagnostics message call instead. When the program reaches the"__builtin_unreachable"call, the behavior is undefined ๐.-fsanitize=vla-boundโ This makes the compiler check that the size of a variable length array is positive.-fsanitize=nullโ This enables pointer checking. An application built with this turned on will issue an error message when it tries to dereference a NULL pointer, when a reference (possibly an rvalue reference) is bound to a NULL pointer, or when a method is invoked on an object pointed to by a NULL pointer.-fsanitize=returnโ This enables return statement checking. Programs built with this turned on will issue an error message when the end of a non-void function is reached without actually returning a value. This option works in C++ only.-fsanitize=signed-integer-overflowโ This enables signed integer overflow checking. It checks that the result of+,*, and both unary and binary-does not overflow in signed arithmetic. It also detectsINT_MIN / -1signed division. Keep integer promotion rules in mind, because the following is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ This enables instrumentation of array bounds, so various out-of-bounds accesses get detected. Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented ๐ง.-fsanitize=bounds-strictโ This enables strict instrumentation of array bounds. Most out-of-bounds accesses are detected, including flexible array members and flexible array member-like arrays. Initializers of variables with static storage are not instrumented.-fsanitize=alignmentโ This enables checking of pointer alignment when pointers are dereferenced, when a reference is bound to an insufficiently aligned target, or when a method or constructor is invoked on an insufficiently aligned object ๐.-fsanitize=object-sizeโ This enables instrumentation of memory references using the"__builtin_object_size"function. Various out-of-bounds pointer accesses get detected ๐.-fsanitize=float-divide-by-zeroโ okay so this one catches floating-point division by zero ๐งฎ. Heads up though, it is not turned on by-fsanitize=undefinedlike the other similar options, because dividing floats by zero can be a legit way to get infinities and NaNs ๐ not everything is a bug, bestie.-fsanitize=float-cast-overflowโ this checks float-to-integer conversions and makes sure the result doesn't overflow ๐ซถ. Also not included in-fsanitize=undefined.
โ ๏ธ This one doesn't vibe well with FE_INVALID exceptions enabled, so proceed with caution ๐
-fsanitize=nonnull-attributeโ instruments calls to make sure you're not passing null values into arguments marked with thenonnullfunction attribute ๐ โโ๏ธ-fsanitize=returns-nonnull-attributeโ instruments return statements in functions marked with thereturns_nonnullfunction attribute, so it can catch null values getting returned from them ๐-fsanitize=boolโ instruments loads frombool. If something 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 gets loaded, that's a run-time error ๐จ-fsanitize=vptrโ this one is giving C++ energy ๐. It instruments C++ member function calls, member accesses, and some conversions between pointers to base and derived classes, to verify the referenced object has the correct dynamic type.-fsanitize=pointer-overflowโ instruments pointer arithmetic. If the pointer arithmetic overflows, that's a run-time error ๐จ-fsanitize=builtinโ instruments the arguments to selected builtin functions. If an invalid value gets passed in, you get a run-time error. For example, passing0to__builtin_ctzor__builtin_clzis undefined behavior, and this option will call it out ๐
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 โจ
-fsanitize=all is not allowed, since some sanitizers cannot be used together ๐
-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks ๐งช super useful if you're experimenting with different shadow memory layouts in Kernel AddressSanitizer.-fsanitize-sections=s1,s2,...โ sanitizes global variables in the user-defined sections you pick ๐ si can have wildcards.-fsanitize-recover[=opts]โ this controls error recovery for the sanitizers listed in the comma-separatedoptslist ๐ When recovery is on, the sanitizer tries to keep the program running like nothing happened. That means you can get multiple runtime errors in one run, and the exit code might say success even though errors got reported ๐-fno-sanitize-recover=flips that. Only the first error gets reported, and then the program exits with a non-zero exit code ๐- Right now this only works for
-fsanitize=undefined(and its suboptions, except-fsanitize=unreachableand-fsanitize=return),-fsanitize=float-cast-overflow,-fsanitize=float-divide-by-zero,-fsanitize=bounds-strict,-fsanitize=kernel-addressand-fsanitize=address. - For those sanitizers, recovery is turned on by default, except for
-fsanitize=address, where it's still experimental ๐งช -fsanitize-recover=allenables recovery for every sanitizer that supports it.-fno-sanitize-recover=alldisables recovery for every sanitizer that supports it.
Even if recovery is turned on at compile time, the runtime library has to have it enabled too, or the failures are still fatal ๐ญ The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while AddressSanitizer defaults to 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 sanitizing local variables so it can catch use-after-scope bugs ๐ This option sets-fstack-reusetonone.-fsanitize-undefined-trap-on-errorโ tells the compiler to report undefined behavior using__builtin_trapinstead of alibubsanlibrary routine ๐ฆ The perk is thatlibubsanisn't needed and doesn't get linked in, so this works even in freestanding environments.-fsanitize-coverage=trace-pcโ enables coverage-guided fuzzing instrumentation ๐ It inserts a call to__sanitizer_cov_trace_pcinto every basic block.-fsanitize-coverage=trace-cmpโ enables dataflow-guided fuzzing instrumentation ๐ง It inserts calls to:__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__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_cmp4or__sanitizer_cov_trace_const_cmp8for integral comparisons with one constant operand__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]โ this one is a security queen ๐ It enables code instrumentation of control-flow transfers, checking that the target addresses of control-flow transfer instructions (like indirect function calls, function returns, and indirect jumps) are valid. That stops the flow of control from getting diverted to some unexpected target. It's meant to guard against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP) ๐ก๏ธbranchchecks validity at indirect branch instructions, i.e. call/jmp instructions ๐ธreturnchecks validity when returning from a function ๐ธfullis an alias for bothbranchandreturn๐noneturns instrumentation off ๐ โโ๏ธcheckis for the final link with link-time optimization (LTO). An error gets issued if LTO object files were compiled with different-fcf-protectionvalues. It's ignored at compile time ๐ซ- The macro
__CET__is defined when-fcf-protectionis used. Its first bit is set to 1 forbranch, and its second bit is set to 1 forreturn๐ง - You can use the
nocf_checkattribute to mark which functions and calls should be skipped from instrumentation ๐ - Currently, the x86 GNU/Linux target has an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processors or newer โก
-fharden-comparesโ for every logical test that survives gimple optimizations and is not the condition in a conditional branch (like conditions tested for conditional moves, or stored in boolean variables), it emits extra code to compute and verify the reversed condition. If the results don't match, it calls__builtin_trap๐งฑ Use it with-fharden-conditional-branchesto cover all conditionals.-fharden-conditional-branchesโ for every non-vectorized conditional branch that survives gimple optimizations, it emits extra code to compute and verify the reversed condition, and calls__builtin_trapif the result is unexpected ๐ฐ Use it with-fharden-comparesto cover all conditionals.-fstack-protectorโ emits extra code to check for buffer overflows, like stack smashing attacks ๐ก๏ธ It works by adding a guard variable to functions with vulnerable objects. That includes functions that callalloca, and functions with buffers 8 bytes or larger. The guards get initialized when a function is entered and checked when it exits. If a guard check fails, an error message gets printed and the program exits ๐ Only variables that are actually allocated on the stack count. Optimized-away variables or variables allocated in registers don't.-fstack-protector-allโ same energy as-fstack-protector, except all functions get protected ๐-fstack-protector-strongโ like-fstack-protector, but it covers extra functions too: those with local array definitions, or those with references to local frame addresses ๐ Same rule applies, only variables actually allocated on the stack are considered. Optimized-away variables or variables allocated in registers don't count.-fstack-protector-explicitโ like-fstack-protector, but it only protects functions that have thestack_protectattribute ๐ฏ-fstack-checkโ generates code to verify that you don't go beyond the boundary of the stack ๐ฅ You should specify this if you're running in an environment with multiple threads. You rarely need it in a single-threaded environment, since stack overflow is automatically detected on nearly all systems when there's only one stack ๐
This switch doesn't actually cause checking to be done ๐ญ The operating system or the language runtime has to do that. The switch just generates code that makes sure they see the stack being extended.
You can also tack on a string parameter ๐
no means no checking at all, generic forces the old-style checking, and specific picks the best checking method, which is the same as bare -fstack-check ๐.
Old-style checking is a generic mechanism. It needs zero special target support in the compiler, but it comes with some major drawbacks ๐
- Modified allocation strategy for large objects: they always get allocated dynamically once their size goes over a fixed threshold. ngl this may change the semantics of some code ๐ญ
- Fixed limit on the size of the static frame of functions: when a particular function tops it, stack checking isn't reliable and the compiler issues a warning ๐
- Inefficiency: between the modified allocation strategy and the generic implementation, code performance takes a hit ๐
Also, old-style stack checking is the fallback method for specific if the compiler doesn't have target support added ๐ง
-fstack-check= was made for Ada's needs, to detect infinite recursion and stack overflows ๐ธ. specific is an excellent choice when compiling Ada code โจ. It is not generally enough to protect against stack-clash attacks though, so if you want protection from those, you want -fstack-clash-protection ๐ซถ.
-fstack-clash-protectionโ Generates code to prevent stack clash style attacks ๐ก๏ธ. With this on, the compiler only allocates one page of stack space at a time, and each page gets accessed right after it's allocated. So allocations can't jump over a stack guard page the operating system provides ๐ฆ.
Most targets don't fully support stack clash protection, lowkey sad ๐ญ. But on the targets 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 ๐.
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ Generates code to make sure the stack doesn't grow past a certain value ๐ง. That value is either a register's value or the address of a symbol ๐ฅ. If a bigger stack is needed, a signal gets raised at run time. On most targets the signal goes up before the stack overruns the boundary, so you can catch it without taking any special precautions ๐.
Here's an example vibe: 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 ๐. Heads up, this may only work with the GNU linker โ ๏ธ.
You can override stack limit checking locally by using the no_stack_limit function attribute ๐.
-fsplit-stackโ Generates code to automatically split the stack before it overflows ๐งต. The resulting program has a discontiguous stack, which can only overflow if the program can't allocate any more memory ๐. This is most useful with 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 ๐ป.
When code compiled with -fsplit-stack calls code compiled without -fsplit-stack, there might not be much stack space left for that second code 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 ๐ซง. The gold linker in GNU binutils release 2.21 and later supports this โจ.
-fvtable-verify=[std|preinit|none]โ This one is C++ only ๐ . It turns the security feature on, or off with-fvtable-verify=none. The feature checks at run time, for every virtual call, that the vtable pointer used for the call is valid for the object's type and hasn't been corrupted or overwritten ๐. If an invalid vtable pointer shows up at run time, an error is reported and the program immediately halts ๐.
This option builds run-time data structures at program startup, and those are what verify the vtable pointers ๐ง. The std and preinit values control when those data structures get built, and in both cases it happens before execution reaches main โฐ. -fvtable-verify=std builds them after shared libraries have been loaded and initialized ๐. -fvtable-verify=preinit builds them before shared libraries are loaded and initialized ๐ธ.
If you pass this option several times with different values, none takes the highest priority over both std and preinit, and preinit beats std ๐.
-fvtv-debugโ Used together with-fvtable-verify=stdor-fvtable-verify=preinit, this makes the debug versions of the runtime functions for vtable verification 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 the environment variableVTV_LOGS_DIRif it's defined, or the current working directory otherwise ๐.
Note: this feature appends data to the log file ๐. If you want a fresh log file, delete any existing one first ๐งน.
-fvtv-countsโ This is a debugging flag ๐ง. Paired with-fvtable-verify=stdor-fvtable-verify=preinit, the compiler keeps 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 all of that for each compilation unit ๐. The compiler writes this info 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 ๐งน.
-finstrument-functionsโ Generates instrumentation calls for function entry and exit ๐ญ. Right after a function starts and right before it exits, the following profiling functions get called with the address of the current function and its call site ๐ซ. (On some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site info might not be available to the profiling functions otherwise ๐คทโโ๏ธ.)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
The first argument is the address of the start of the current function, which you can look 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 gets entered and exited ๐ช. That means addressable versions of those functions must be available ๐. If all your uses of a function get expanded inline, this might add extra code size ๐. If you use extern inline in your C code, an addressable version of those functions has to be provided too ๐ซถ. (This is normally the case anyway, but if you get lucky and the optimizer always expands them inline, you might have gotten away without providing static copies ๐.)
A function can be given the attribute no_instrument_function, and then this instrumentation isn't done for it ๐
โโ๏ธ. That's handy for the profiling functions 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-exclude-file-list=file,file,...โ Sets the list of functions excluded from instrumentation (see-finstrument-functions) ๐ซ. If the file containing a function definition matches one of thefileentries, that function doesn't get instrumented ๐. The match is done on substrings: if thefileparameter is a substring of the file name, it counts as a match ๐ค.
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
This excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys ๐ธ.
If, for some reason, you want to include a comma in one of the sym entries, write ,, instead ๐ง. For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quotes around the option) ๐.
-finstrument-functions-exclude-function-list=sym,sym,...โ This is like-finstrument-functions-exclude-file-list, but it 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 (like"_Z4blahRSt6vectorIiSaIiEE") ๐ช. The match is done on substrings: if thesymparameter is a substring of the function name, it's a match ๐. For C99 and C++ extended identifiers, the function name has to be given in UTF-8, not using universal character names ๐.-fpatchable-function-entry=N[,M]โ GeneratesNNOPs right at the beginning of each function, with the function entry point sitting before theMth NOP ๐งฉ. IfMis omitted, it defaults to0, so the function entry points to the address right at the first NOP ๐. Those NOP instructions reserve extra space that you can use to patch in any instrumentation you want at run time, as long as the code segment is writable โ๏ธ. The amount of space is controlled indirectly through the number of NOPs ๐ข. The NOP instruction used corresponds to the one emitted by the internal GCC back-end interfacegen_nopโ๏ธ. This behavior is target-specific and may also depend on the architecture variant and/or other compilation options ๐.
Okay so the starting addresses of these patch areas also get saved for run-time identification ๐. They're collected in the __patchable_function_entries section of the final binary ๐ฆ, and each one is its function entry minus M. Very organized, very giving.
Heads up ๐จ: a __attribute__ ((patchable_function_entry (N,M))) value beats the command-line -fpatchable-function-entry=N,M option, no cap. So you can bump the area size up, or wipe it entirely on one specific function ๐
. And if N=0, no pad location gets recorded at all ๐.
The NOP instructions get tucked in at the function entry address ๐ง. Depending on M, they might even go in before that address, and yes, that includes before the prologue ๐.
The maximum value of N and M is 65535, so don't go past that ๐ซถ.
โจ Options Controlling the Preprocessor โจ
These options are for the C preprocessor ๐ธ, which runs on every C source file before the actual compilation even starts.
If you use -E, the preprocessor just preprocesses and that's it ๐ซง. A few of these options only make sense alongside -E, because they make the output unusable for real compilation ๐.
There are also include search path options over in Directory Options, and the preprocessor diagnostic ones live in Warning Options ๐บ๏ธ.
-D nameโ Predefine name as a macro, with the definition1๐.-D name=definitionโ The definition gets tokenized and processed as if it showed up during translation phase three in a#definedirective. Heads up: embedded newline characters cut the definition short โ๏ธ.- If you're calling the preprocessor from a shell (or something shell-like), you may 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? Write its argument list with surrounding parentheses before the equals sign (if there is one). Parentheses mean stuff to most shells, so quote the option. With
shandcsh,-D'name(args...)=definition'works โจ. -Dand-Uoptions get processed in the order they show up on the command line. All-imacros fileand-include fileoptions get processed after all the-Dand-Uones ๐.
-U nameโ Cancel any earlier definition of name, whether it was built in or came from a-Doption ๐งน.-include fileโ Process file as if#include "file"showed up as the first line of the primary source file. The difference: the first directory searched for file is 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.- With multiple
-includeoptions, the files get included in the order they appear on the command line.
- With multiple
-imacros fileโ Exactly like-include, except any output from scanning file gets tossed. The macros it defines stay defined, so you can snag every macro from a header without processing its declarations ๐งฒ.- All files given with
-imacrosget processed before all the files given with-include.
- All files given with
-undefโ Don't predefine any system-specific or GCC-specific macros. The standard predefined macros still stay defined.-pthreadโ Defines the extra macros needed for the POSIX threads library ๐งต. Use it consistently for both compilation and linking. It's supported on GNU/Linux targets and most other Unix derivatives, plus x86 Cygwin and MinGW targets.-Mโ Instead of spitting out the preprocessed result, output amakerule describing the dependencies of the main source file ๐. That rule has the object file name for the source file, a colon, and the names of all the included files, including any coming from-includeor-imacroscommand-line options.- Unless you specify it explicitly (with
-MTor-MQ), the object file name is the source file name with any suffix swapped for the object file suffix, and any leading directory parts removed. - With lots of included files, the rule gets split into several lines using
\-newline. The rule has no commands. - This option does not suppress the preprocessor's debug output, such as
-dM. To keep that debug output from mixing with the 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 normal. - Passing
-Mto the driver implies-E, and suppresses warnings with an implicit-w.
- Unless you specify it explicitly (with
-MMโ Like-M, but don't mention header files found in system header directories, or header files included (directly or indirectly) from such a header ๐ .- 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, specifies a file to write the dependencies to. If there's no-MFswitch, the preprocessor sends the rules to the same place it would send preprocessed output. When used with the driver options-MDor-MMD,-MFoverrides the default dependency output file. If file is-, the dependencies are written to stdout.-MGโ Used with an option like-Mthat requests dependency generation.-MGassumes missing header files are generated files, and adds them to the dependency list without raising an error ๐คทโโ๏ธ. The dependency filename is taken directly from the#includedirective without prepending any path.-MGalso suppresses preprocessed output, since a missing header file makes that useless. This feature is used in automatic updating of makefiles ๐ ๏ธ.-Mno-modulesโ Disable dependency generation for compiled module interfaces.-MPโ Tells CPP to add a phony target for each dependency other than the main file, causing each one to depend on nothing ๐ฉน. These dummy rules work around the errorsmakegives if you remove header files without updating the Makefile to match. This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ Changes the target of the rule emitted by dependency generation ๐ฏ. By default CPP takes the name of the main input file, deletes any directory components and any file suffix such as.c, and appends the platform's usual object suffix. That result is the target.- An
-MToption sets the target to be exactly the string you specify. - If you want multiple targets, you can specify them as a single argument to
-MT, or use multiple-MToptions.
- An
For example, -MT '$(objpfx)foo.o' might give:
$(objpfx)foo.o: foo.c
-MQ targetโ Same as-MT, but it quotes any characters that are special to Make ๐.-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
The default target is automatically quoted, as if it were given with -MQ.
-MDโ-MDis equivalent to-M -MF file, except that-Eis not implied ๐. The driver figures out file based on whether an-ooption is given. If it is, the driver uses its argument with a suffix of.d. Otherwise, it takes the name of the input file, removes any directory components and suffix, and applies a.dsuffix.- If
-MDis used together with-E, any-oswitch is understood to specify the dependency output file. 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 ๐.
- If
-MMDโ Like-MD, but only mention user header files, not system header files.-fpreprocessedโ Tells the preprocessor that the input file has already been preprocessed ๐ง. This suppresses things like macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives. The preprocessor still recognizes and removes comments, so you can pass a file preprocessed with-Cto the compiler without problems. In this mode the integrated preprocessor is little more than a tokenizer for the front ends.-fpreprocessedis implicit if the input file has one of the extensions.i,.iior.mi. These are the extensions GCC uses for preprocessed files created by-save-temps.
-fdirectives-onlyโ When preprocessing, handle directives, but do not expand macros ๐งฉ. What it does depends on-Eand-fpreprocessed:- With
-E, preprocessing is limited to handling directives such as#define,#ifdef, and#error. Other preprocessor operations, such as macro expansion and trigraph conversion, are not performed. In addition, the-dDoption is implicitly enabled. - With
-fpreprocessed, predefinition of command-line and most builtin macros is disabled. Macros such as__LINE__, which are contextually dependent, are handled normally. This enables compilation of files previously preprocessed with-E -fdirectives-only. - With both
-Eand-fpreprocessed, the rules for-fpreprocessedtake precedence. This enables full preprocessing of files previously preprocessed with-E -fdirectives-only.
- With
-fdollars-in-identifiersโ Accept$in identifiers ๐ต.-fextended-identifiersโ Accept universal character names and extended characters in identifiers. This option is enabled by default for C99 (and later C standard versions) and C++ ๐.-fno-canonical-system-headersโ When preprocessing, do not shorten system header paths with canonicalization.-fmax-include-depth=depthโ Sets the maximum depth of nested#include. The default is200๐.-ftabstop=widthโ Sets the distance between tab stops. This helps the preprocessor report correct column numbers in warnings or errors, even if tabs appear on the line ๐. If the value is less than1or greater than100, the option is ignored. The default is8.-ftrack-macro-expansion[=level]โ okay so this one tracks where tokens come from across macro expansions ๐โจ When a compile error shows up inside a macro, the compiler can show you the whole macro expansion stack, which is so helpful. The catch is that the preprocessor and compiler eat more memory with it on ๐ Thelevelargument lets you pick how precise the tracking is, so you can trade precision for memory if you need to.0turns it off.1is the degraded mode with minimal memory overhead, where every token that comes from expanding an argument of a function-like macro gets the same location.2tracks token locations fully, and it's the most memory-hungry option of the bunch. If you give the option with no argument,leveldefaults to2.
Also, -ftrack-macro-expansion=2 is on by default ๐
-fmacro-prefix-map=old=newโ when you're preprocessing files that live in directoryold, this makes__FILE__and__BASE_FILE__act like the files live in directorynewinstead ๐บ๏ธ This is a fave for turning an absolute path into a relative one (use.fornew), which can lead to more reproducible, location-independent builds ๐ธ It also affects__builtin_FILE()during compilation. See also-ffile-prefix-map.-fexec-charset=charsetโ sets the execution character set, which is what string and character constants get encoded in ๐ The default is UTF-8, andcharsetcan be any encoding your system'siconvlibrary routine supports.-fwide-exec-charset=charsetโ same energy, but for wide string and wide character constants ๐ The default is UTF-32 or UTF-16, whichever matches the width ofwchar_t. Just like-fexec-charset,charsetcan be any encodingiconvsupports, but ngl you'll run into problems with encodings that don't fit exactly inwchar_t๐ญ-finput-charset=charsetโ this sets the input character set, which is used to translate your input file from its own character set into the source character set GCC uses ๐ฆ If the locale doesn't say what to use, or GCC can't read that info from the locale, the default is UTF-8. The locale or this command-line option can override that default, but if they clash, the command-line option wins.charsetcan be any encoding your system'siconvroutine supports.-fpch-depsโ when you're using precompiled headers, this makes the dependency-output flags also list the files the precompiled header depends on ๐ง Without it, only the precompiled header itself gets listed, not the files that were used to build it, since those aren't consulted once a PCH is in use.-fpch-preprocessโ this lets you use a precompiled header together with-E๐ It drops a special#pragma, which looks like#pragma GCC pch_preprocess "filename", into the output to mark where the precompiled header was found, plus its filename. When-fpreprocessedis in use, GCC recognizes that#pragmaand loads the PCH.
This option is off by default, because the preprocessed output is really only good as input to GCC ๐ It gets switched on by -save-temps.
Don't write this #pragma in your own code, but it's safe to edit the filename if the PCH file lives somewhere else now. The filename can be absolute or relative to GCC's current directory.
-fworking-directoryโ turns on linemarkers in the preprocessor output that tell the compiler what the working directory was at preprocessing time ๐ When it's enabled, the preprocessor emits a second linemarker after the initial one, containing the current working directory followed by two slashes. GCC uses that directory, if it shows up in the preprocessed input, as the working directory in some debugging information formats. This is implicitly enabled when debugging info is on, but you can block it with the negated form-fno-working-directory. If-Pis on the command line, this option does nothing, since no#linedirectives get emitted whatsoever ๐ โโ๏ธ-A predicate=answerโ makes an assertion with the predicatepredicateand the answeranswer๐ This form is preferred over the older-A predicate(answer)form, which still works, because it doesn't use shell special characters.-A -predicate=answerโ cancels an assertion with the predicatepredicateand the answeranswer๐ซ-Cโ do not discard comments ๐ฌ All comments get passed through to the output file, except comments inside processed directives, which get deleted along with the directive.
Be prepared for side effects when you use -C, because it makes the preprocessor treat comments as tokens in their own right ๐ For example, a comment at the start of what would be a directive line turns that line into an ordinary source line, since the first token on the line is no longer a #.
-CCโ do not discard comments, including during macro expansion ๐ซถ It's like-C, except comments inside macros also get passed through to the output file wherever the macro is expanded.
On top of the -C side effects, -CC converts all C++-style comments inside a macro into C-style comments. This stops a later use of that macro from accidentally commenting out the rest of the source line ๐ญ
-CC is generally used to support lint comments.
-Pโ inhibits linemarker generation in the preprocessor output ๐งน This can be handy when you're running the preprocessor on something that isn't C code, and the result is going to a program that might get confused by linemarkers.-traditional,-traditional-cppโ tries to imitate pre-standard C preprocessors instead of ISO C ones ๐ฐ๏ธ Check the GNU CPP manual for details.
GCC doesn't otherwise try to act like a pre-standard C compiler, and these options only work with the -E switch, or when you invoke CPP explicitly.
-trigraphsโ supports ISO C trigraphs ๐บ These are three-character sequences, all starting with??, that ISO C defines to stand for single characters. For example,??/stands for\, so'??/n'is a character constant for a newline.
The nine trigraphs and their replacements are:
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] { } # \ ^ | ~
By default GCC ignores trigraphs, but in standard-conforming modes it converts them. See the -std and -ansi options.
-remapโ enables special code to work around file systems that only allow super short file names, like MS-DOS ๐พ-Hโ prints the name of each header file used, along with everything else it normally does ๐ Each name is indented to show how deep it sits in the#includestack. Precompiled header files get printed too, even if they turn out to be invalid. An invalid PCH gets printed with...x, and a valid one gets printed with...!โจ-dlettersโ tells the compiler to make debugging dumps during compilation, as specified byletters๐ฌ The flags documented here are the ones that matter to the preprocessor. Other letters are either read by the compiler proper, or reserved for future GCC versions, so they're silently ignored. If you pick letters whose behavior conflicts, the result is undefined, so maybe don't ๐-dMโ instead of the normal output, you get a list of#definedirectives for all the macros defined during preprocessing, including predefined ones ๐งพ This is a great way to find out what's predefined in your version of the preprocessor. Assuming you have no filefoo.h, this command:
touch foo.h; cpp -dM foo.h
shows all the predefined macros.
If you use -dM without -E, it's interpreted as a synonym for -fdump-rtl-mach ๐คฏ
-dDโ like-dM, except it does not include the predefined macros, and it outputs both the#definedirectives and the result of preprocessing. Both kinds of output go to the standard output file.-dNโ like-dD, but it only emits the macro names, not their expansions ๐ท๏ธ-dIโ outputs#includedirectives in addition to the result of preprocessing ๐-dUโ like-dD, except only macros that get expanded, or whose definedness gets tested in preprocessor directives, are output ๐ฏ The output is delayed until the macro is used or tested, and#undefdirectives are also output for macros that were tested but undefined at that time.
-fdebug-cppโ this one is only useful for debugging GCC ๐ ๏ธ When used from CPP or with-E, it dumps debugging info about location maps. Every token in the output gets preceded by the dump of the map its location belongs to.
When used from GCC without -E, this option does nothing.
-Wp,optionโ lets you bypass the compiler driver and passoptionstraight through to the preprocessor ๐ช Ifoptioncontains commas, it gets split into multiple options at those commas. But lots of options get modified, translated, or interpreted by the compiler driver before they reach the preprocessor, and-Wpforcibly skips that step โ ๏ธ The preprocessor's direct interface is undocumented and subject to change, so whenever possible, avoid-Wpand let the driver handle the options instead.-Xpreprocessor optionโ passesoptionalong as an option to the preprocessor ๐ This is useful 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 ๐
๐ OPTIONS ๐ (continued) ๐
-no-integrated-cppโ okay so, by default GCC does preprocessing as part of tokenizing and parsing your input, all baked in together ๐ If you pass this one, the matching front end (cc1for C,cc1plusfor C++, orcc1objfor Objective-C) gets run twice instead. Once just for preprocessing, and once to actually compile the preprocessed input ๐ซถ This is lowkey useful with-Bor-wrapperif you want an alternate preprocessor, or extra processing of your source between normal preprocessing and compilation โจ-flarge-source-filesโ for when your files are absolutely massive ๐ This tells GCC to expect large source files, but the price is slower compilation and higher memory usage ๐
Normally GCC tracks both column numbers and line numbers in your source, 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 don't include column numbers. Options like -Wmisleading-indentation also stop working at that point, although the compiler prints a note if this happens ๐ Passing -flarge-source-files significantly increases the number of source lines GCC can process before it stops tracking columns ๐ฆ
๐ธ Passing Options to the Assembler ๐ธ
You can pass options to the assembler, bestie ๐ง
-Wa,optionโ passoptionalong as an option to the assembler. Ifoptionhas commas in it, it gets split into multiple options at those commas ๐-Xassembler optionโ passoptionalong to the assembler too. You can use this to supply system-specific assembler options that GCC doesn't recognize ๐
If you want to pass an option that takes an argument, you must use -Xassembler twice: once for the option and once for the argument. No shortcuts here, it's giving strict ๐
๐ Options for Linking ๐
These options come into play when the compiler links object files into an executable output file. They're meaningless if the compiler isn't doing a link step, so don't waste your time on them otherwise ๐ฅฒ
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 and libraries apart by the file contents, not the name ๐ง) If linking happens, these object files are used as input to the linker.-c,-S,-Eโ if any of these is used, the linker doesn't run at all, so object file names should not be used as arguments ๐ซ-flinker-output=typeโ this one controls code generation of the link-time optimizer ๐ By default the linker output is automatically determined by the linker plugin. For debugging the compiler, or if you want incremental linking with a non-LTO object file, it can be useful to control the type manually ๐ ๏ธexecโ code generation produces a static binary. In this case-fpicand-fpieare both disabled ๐dynโ code generation produces a shared library. Here-fpicor-fPICis preserved, but not enabled automatically. This lets you build shared libraries without position-independent code on architectures where that's possible, i.e. on x86 โจpieโ code generation produces an-fpieexecutable. This gets similar optimizations toexec, except-fpieis not disabled if you specified it at compilation time ๐ฆrelโ the compiler assumes incremental linking is happening. The sections holding intermediate code for link-time optimization get merged, pre-optimized, and output to the resulting object file. Also, if-ffat-lto-objectsis specified, binary code is produced for future non-LTO linking. The object file from incremental linking is smaller than a static library made from the same object files, and at link time it also loads faster than a static library, as long as most of the objects in the library get used ๐ธ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 result is better optimized than with link-time optimizations disabled (cross-module inlining happens, yay!), but most of the benefits of whole program optimizations are lost ๐ญ
During the incremental link (by -r), the linker plugin defaults to rel. With current interfaces to GNU Binutils it is, sadly, 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 uses nolto-rel. To keep whole program optimization, it's recommended to link those objects into a static library instead. Alternatively, it's possible to use H.J. Lu's binutils, which support mixed objects ๐ซถ
-fuse-ld=bfdโ use the bfd linker instead of the default linker ๐ง-fuse-ld=goldโ use the gold linker instead of the default linker ๐ง-fuse-ld=lldโ use the LLVM lld linker instead of the default linker ๐ง-fuse-ld=moldโ use the Modern Linker (mold) instead of the default linker ๐ง-llibrary,-l libraryโ search the library namedlibrarywhen linking. (The second alternative, with the library as a separate argument, is only there for POSIX compliance and isn't recommended ๐ โโ๏ธ)
The -l option is passed directly to the linker by GCC, so refer to your linker documentation for the exact details. The general description below applies to the GNU linker ๐ง
The linker searches a standard list of directories for the library. That includes several standard system directories, plus any you specify with -L ๐บ๏ธ
Static libraries are archives of object files, and they 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 gives preference to the shared library, unless the -static option is used ๐
It makes a difference where in the command you write this option, because the linker searches and processes libraries and object files in the order they're specified. So foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded ๐ฑ
-lobjcโ you need this special case of the-loption in order to link an Objective-C or Objective-C++ program ๐-nostartfilesโ don't use the standard system startup files when linking. The standard system libraries are still used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used ๐-nodefaultlibsโ don't use the standard system libraries when linking. Only the libraries you specify get passed to the linker, and options that specify linkage of the system libraries, such as-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, so when this option is specified, those entry points should be supplied through some other mechanism ๐ซ
-nolibcโ don't use the C library, or the system libraries tightly coupled with it, when linking. You'll still link with the startup files,libgcc, or toolchain-provided language support libraries such aslibgnat,libgfortranorlibstdc++, unless options preventing their inclusion are used as well ๐ค This typically removes-lcfrom the link command line, along with the system libraries that normally go with it and become meaningless when a C library is assumed absent. For example,-lpthreador-lmin some configurations. It's intended for bare-board targets where there's genuinely no C library available ๐-nostdlibโ don'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 specify linkage of the system libraries, such as-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, so when this option is specified, those entry points should be supplied through some other mechanism ๐ซ
One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines which GCC uses to overcome shortcomings of particular machines, or special needs for some languages ๐ง
In most cases you still need libgcc.a, even when you want to avoid the other standard libraries. In other words, when you specify -nostdlib or -nodefaultlibs, you should usually specify -lgcc as well ๐ This makes sure you have no unresolved references to internal GCC library subroutines. (An example of such an internal subroutine is "__main", used to make sure C++ constructors get called โจ)
-e entry,--entry=entryโ specify that the program entry point isentry. The argument is interpreted by the linker. The GNU linker accepts either a symbol name or an address ๐ฏ-pieโ produce a dynamically linked position independent executable on targets that support it. For predictable results, you must also specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you specify this linker option ๐ฆ-no-pieโ don't produce a dynamically linked position independent executable ๐ โโ๏ธ-static-pieโ produce a static position independent executable on targets that support it. It's similar to a static executable, but it can be loaded at any address without a dynamic linker ๐ For predictable results, you must also specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you specify this linker option ๐ซถ
Okay bestie, we're still in the linker options ๐๐, so let's keep going!
-pthreadโ Links your program with the POSIX threads library ๐งต. It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. Heads up: on some targets it also sets flags for the preprocessor, so use it consistently for both compilation and linking โจ.-rโ Makes a relocatable object as output. This is also known as partial linking ๐ฆ.-rdynamicโ Passes the flag-export-dynamicto the ELF linker, on targets that support it. This tells the linker to add all symbols, not only the used ones, to the dynamic symbol table ๐. You need it 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 other objects can link with to form an executable ๐. Not every system supports it, so check first! For predictable results, you also need to specify the same set of options used for compilation (-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 was built when the compiler was configured, these options have no effect.
There are a few situations where an app should use the shared libgcc instead of the static one ๐ซถ. The biggest one is when the app wants to throw and catch exceptions across different shared libraries. In that case, 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. C++ programs usually use exceptions, so this is the right move โจ.
If you use the GCC driver to create shared libraries instead, they might not always get linked with the shared libgcc ๐ค. If GCC finds out at configuration time that you have a non-GNU linker, or a GNU linker that doesn't support option --eh-frame-hdr, it links the shared version of libgcc into shared libraries by default. Otherwise, it takes advantage of the linker and optimizes away the linking with the shared version, so it links with the static version of libgcc by default. This lets exceptions propagate through those shared libraries without taking on relocation costs at library load time ๐ฆ.
Heads up: 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 it gets linked with the shared libgcc. Don't skip this one bestie ๐ญ.
-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 isn't used, it links against the shared version. This option tells 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 isn't used, it links against the shared version. This option tells 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 isn't used, it links against the shared version. This option tells 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 isn't used, it links against the shared version. This option tells the GCC driver to link libubsan statically, without necessarily linking other libraries statically ๐ธ.-static-libstdc++โ When theg++program is used to link a C++ program, it normally links against libstdc++ automatically. If libstdc++ is available as a shared library and the-staticoption isn't used, it links against the shared version, and that's normally totally fine ๐ . But sometimes you want to freeze the version of libstdc++ your program uses without going all the way to a fully static link. This option tells theg++driver to link libstdc++ statically, without necessarily linking other libraries statically ๐ง.-symbolicโ Binds references to global symbols when building a shared object. It warns about any unresolved references (unless overridden by the link editor option-Xlinker -z -Xlinker defs). Only a few systems support this one ๐ซฃ.-T scriptโ Usesscriptas the linker script ๐. This works on most systems using the GNU linker. On some targets, like bare-board targets without an operating system, you may need the-Toption when linking to avoid references to undefined symbols.-Xlinker optionโ Passesoptionalong to the linker as an option ๐. Super handy for system-specific linker options that GCC doesn't recognize.
If you want to pass an option that takes a separate argument, you have to use -Xlinker twice: once for the option and once for the argument ๐งฉ. For example, to pass -assert definitions, you must write -Xlinker -assert -Xlinker definitions. Writing -Xlinker "-assert definitions" does not work, because it passes the whole string as a single argument, which isn't what the linker expects ๐.
With the GNU linker, it's usually more convenient to pass arguments to linker options using the option=value syntax instead of separate arguments. For example, you can write -Xlinker -Map=output.map rather than -Xlinker -Map -Xlinker output.map. Other linkers may not support this syntax for command-line options ๐คทโโ๏ธ.
-Wl,optionโ Passesoptionto the linker as an option too ๐. Ifoptioncontains commas, it's split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example,-Wl,-Map,output.mappasses-Map output.mapto the linker. With the GNU linker, you can also get the same effect with-Wl,-Map=output.map๐.-u symbolโ Pretends the symbolsymbolis undefined, which forces the linking of library modules that define it ๐ต๏ธโโ๏ธ. You can use-umultiple times with different symbols to force loading of additional library modules.-z keywordโ-zgets passed directly to the linker, along with the keywordkeyword. Check the documentation for your linker to see 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 directorydirto the list of directories searched for header files during preprocessing ๐. Ifdirbegins with=or$SYSROOT, then that=or$SYSROOTgets replaced by the sysroot prefix. See--sysrootand-isysroot.
Directories specified with -iquote only apply to the quote form of the directive, "#include "file"". Directories specified with -I, -isystem, or -idirafter apply to lookups for both the "#include "file"" and "#include <file>" directives ๐.
You can mix and match any number or combination of these options on the command line to search for headers 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 swap in your own version, since these directories get searched before the standard system header file directories ๐. But don't 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 as the standard system directories ๐ซถ.
If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option gets ignored. The directory is still searched, but as a system directory at its normal position in the system include chain. This makes sure GCC's procedure for fixing buggy system headers and the ordering for the #include_next directive don't get changed by accident ๐ก๏ธ. If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options.
-I-โ Splits the include path ๐ช. This option has been deprecated.
Deprecated alert ๐จ: please use-iquoteinstead for-Idirectories before the-I-, and remove the-I-option.
Any directories specified with -I options before -I- are searched only for headers requested with "#include "file"". They are not searched for "#include <file>". If additional directories are specified with -I options after the -I-, those directories are searched for all #include directives ๐
.
In addition, -I- also stops the compiler from checking the current file's directory first when it hunts for #include "file" ๐ and there is no way to override this effect of -I-. Bestie, choose wisely ๐
-iprefix prefixโ ๐ง sets the prefix that any later-iwithprefixoptions will tack onto. If your prefix is an actual directory, you should include the final/.-iwithprefix dir,-iwithprefixbefore dirโ ๐ธ glues dir onto whatever prefix you set earlier with-iprefixand adds the result to the include search path.-iwithprefixbeforedrops it in the same spot-Iwould, while-iwithprefixputs it where-idirafterwould.-isysroot dirโ ๐ this one is basically--sysroot, but it only applies to header files. The exception is Darwin targets, where it covers both header files and libraries. Peep the--sysrootoption for more info.-imultilib dirโ uses dir as a subdirectory of the directory that holds the target-specific C++ headers.-nostdincโ ๐ซถ skips the standard system directories when looking for header files. Only the stuff you explicitly point at with-I,-iquote,-isystem, and/or-idiraftergets searched, plus the directory of the current file if it applies.-nostdinc++โ skips the C++-specific standard directories when hunting for headers, but still checks the other standard ones. This one is used when building the C++ library.-iplugindir=dirโ sets the directory to search for plugins that get passed with-fplugin=nameinstead of-fplugin=path/name.so. You're not really meant to type this one yourself. Only the driver passes it along ๐ โโ๏ธ-Ldirโ adds dir to the list of directories searched for-l๐บ๏ธ-Bprefixโ ๐๏ธ this tells the compiler where to find its own executables, libraries, include files, and data files.
The compiler driver runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for every program it attempts to run, both with and without machine/version/ for the matching target machine and compiler version.
For each subprogram, the driver first tries the -B prefix, if you gave one. If that name isn't found, or if -B isn't specified at all, it tries two standard prefixes: /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those produces a file that exists, the unmodified program name gets searched for through 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 to 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. If it isn't found by those means either, the file is left out of the link.
Another way to specify a prefix much like the -B prefix is to use the environment variable GCC_EXEC_PREFIX.
As a special kludge, if the path provided by-Bis[dir/]stageN/, whereNis a number in the range 0 to 9, then it is replaced by[dir/]include. This is to help with boot-strapping the compiler.
-no-canonical-prefixesโ ๐ซ don't expand any symbolic links, resolve references to/../or/./, or make the path absolute when generating a relative prefix.--sysroot=dirโ ๐ makes dir the logical root directory for headers and libraries. For example, if the compiler normally looks for headers in/usr/includeand libraries in/usr/lib, it will instead look indir/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 used. So headers might be found indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off adding that suffix.
โจ Options for Code Generation Conventions โจ
These machine-independent options are the boss of how the generated code handles its interface conventions ๐
Most of them have both positive and negative forms, where the negative form of -ffoo is -fno-foo. In the list below, only one of the forms is shown, the one that is not the default. You can figure out the other form by either removing no- or adding it.
-fstack-reuse=reuse-levelโ ๐งน controls stack space reuse for user-declared local/auto variables and compiler-generated temporaries.reuse_levelcan beall,named_vars, ornone.allenables stack reuse for all local variables and temporaries,named_varsenables reuse only for user-defined local variables with names, andnonedisables stack reuse completely. The default value isall.
This option is needed when the program extends the lifetime of a scoped local variable or a compiler-generated temporary beyond the end point 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 for other temporaries or scoped local variables whose live range doesn't overlap with it.
Legacy code that extends local lifetime is likely to break with the stack reuse optimization.
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example:
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 for other temporaries or scoped local variables whose live range does not overlap with it. However, some legacy code relies on the behavior of older compilers, in which temporaries' stack space is not reused, so aggressive stack reuse can lead to runtime errors. This option is used to control the temporary stack reuse optimization.
-ftrapvโ ๐จ generates traps for signed overflow on addition, subtraction, and multiplication operations.-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line results in-fwrapvbeing effective. Note that only active options override, so-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. The options-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line results in-fwrapvbeing effective. Note that only active options override, so-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 which assume pointer overflow is invalid.-fstrict-overflowโ ๐ง implies-fno-wrapv -fno-wrapv-pointer, and when negated, implies-fwrapv -fwrapv-pointer.-fexceptionsโ ๐ enables exception handling and generates the extra code needed to propagate exceptions. For some targets, this implies GCC generates frame unwind information for all functions.
That can produce significant data size overhead, although it does not affect execution.
If you don't specify this option, GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that don't normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++. You may also wish to disable this option if you are compiling older C++ programs that don't use exception handling.
-fnon-call-exceptionsโ ๐ชค generates code that allows trapping instructions to throw exceptions.
This requires platform-specific runtime support that does not exist everywhere.
Moreover, it only allows trapping instructions to throw exceptions, i.e. memory references or floating-point instructions. It does not allow exceptions to be thrown from arbitrary signal handlers such as "SIGALRM". This enables -fexceptions.
-fdelete-dead-exceptions๐ โ okay so this one is pure optimization drama. Instructions that could throw an exception but don't otherwise contribute to what the program does can get optimized away โจ. It doesn't touch calls to functions unless they have thepureorconstattributes. This is turned on by default for the Ada and C++ compilers, since the language specs allow it. Optimization passes that remove dead exceptions are enabled separately at different optimization levels ๐ซถ.-funwind-tables๐ฆ โ similar to-fexceptions, except it only generates the static data that's needed and doesn't change the generated code in any other way. You usually don't have to turn this on yourself, because a 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 is a whole saga. With a recent GNU assembler and C library, C++ uses theSTB_GNU_UNIQUEbinding so that template static data members and static local variables in inline functions stay unique even withRTLD_LOCAL. That's needed to avoid problems where a library used by two differentRTLD_LOCALplugins depends on a definition in one of them and ends up 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๐ โ returnsshortstructandunionvalues 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 exact convention for returning structures in memory depends on the target configuration macros.
Short structures and unions are the ones 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. Only use it to conform to a non-default application binary interface โ ๏ธ.
-freg-struct-return๐ง โ returnsstructandunionvalues in registers when possible. This is more efficient for small structures than-fpcc-struct-returnโญ.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever convention is standard for the target. If there isn't a standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases, we get to choose the standard, and we chose the more efficient register return alternative ๐.
Warning: code compiled with-freg-struct-returnis not binary compatible with code compiled with-fpcc-struct-return. Only 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 ends up equivalent to the smallest integer type that has enough room ๐ธ.
Warning: the -fshort-enums switch makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface ๐ญ.
-fshort-wchar๐ โ overrides the underlying type ofwchar_tto beshort unsigned intinstead of the default for the target. This is handy for building programs that run under WINE ๐ท.
Warning: the -fshort-wchar switch makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface โ ๏ธ.
-fcommon๐ฆ โ in C code, this option controls where global variables defined without an initializer get placed. These are called tentative definitions in the C standard. They're different from declarations using theexternkeyword, which don't allocate any storage ๐.
The default is -fno-common, which means the compiler 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 puts uninitialized global variables in a common block instead. That lets the linker resolve all tentative definitions of the same variable across different compilation units to the same object, or to a non-tentative definition. This behaviour is inconsistent with C++, and on many targets it comes with 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. Quiet mode, activated ๐.-finhibit-size-directive๐ง โ doesn'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 placed far apart in memory. This option is used when compilingcrtstuff.c, so you shouldn't need it for anything else ๐ โโ๏ธ.-fverbose-asm๐ โ puts extra commentary into the generated assembly code so it's easier to read. This is honestly only useful for people who actually need to read the generated assembly, maybe while debugging the compiler itself ๐ค.
-fno-verbose-asm, which is the default, leaves out the extra info and is handy when you want to compare 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 it to (x86_64) assembly via -S and emitting the result direct to stdout via -o - looks like this:
gcc -S test.c -fverbose-asm -Os -o -
That 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 them is subject to change ๐ซถโจ.
-frecord-gcc-switches๐ โ this makes GCC record the command line used to invoke the compiler 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 one is related to-fverbose-asm, but that switch only records info in the assembler output file as comments, so it never reaches the object file ๐ โโ๏ธ. See also-grecord-gcc-switchesfor another way of storing compiler options into the object file ๐.-fpic๐ธ โ generates position-independent code (PIC) suitable for use in a shared library, if the target machine supports it. This code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts. (The dynamic loader isn't part of GCC; it's part of the operating system ๐ฅ๏ธ.) If the GOT size for the linked executable goes over a machine-specific maximum, you get an error message from the linker saying that-fpicdoesn't work. In that case, recompile with-fPICinstead ๐. (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit ๐.)
Position-independent code needs special support, so it only works on certain machines. For the x86, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent ๐ง .
When this flag is set, the macros __pic__ and __PIC__ are defined to 1 ๐.
-fPIC๐ฆ โ if it's supported for the target machine, this emits position-independent code suitable for dynamic linking, and it avoids any limit on the size of the global offset table ๐. This option makes a difference on AArch64, m68k, PowerPC and SPARC ๐ .
Position-independent code needs special support, so it only works on certain machines ๐.
When this flag is set, the macros __pic__ and __PIC__ are defined to 2 โจ.
-fpie,-fPIE: okay bestie, these two are the cousins of-fpicand-fPIC๐ฆ The position-independent code they make can only be linked into executables, so no sneaking it into shared libraries. You usually reach for these when you're compiling something that's going to be linked with the-pieGCC option ๐-fpieand-fPIEboth define the macros__pie__and__PIE__โจ- The macros are set to
1for-fpieand2for-fPIE.
-fno-plt: main character move ๐ Don't use the PLT for external function calls in position-independent code. Instead, load the callee address from the GOT at the call site and branch to it. It's more efficient because it gets rid of PLT stubs and exposes GOT loads to optimizations ๐ฅ- On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in a specific register, this gives the compiler more register allocation freedom ๐ธ
- Lazy binding needs the PLT, so with
-fno-pltall external symbols get resolved at load time. Be aware of that trade-off ๐ - Alternatively, the function attribute
nopltcan 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 ๐
-fno-jump-tables: no jump tables forswitchstatements, even where they'd be more efficient than other strategies ๐ This one is handy alongside-fpicor-fPICwhen you're building code that forms part of a dynamic linker and can't reference the address of a jump table ๐- On some targets, jump tables don't require a GOT, so you won't need this option there ๐
-fno-bit-tests: no bit tests forswitchstatements, even if they'd be more efficient than other code generation strategies ๐-ffixed-reg: treat the register named reg as fixed, so the generated code should never touch it (except maybe as a stack pointer, frame pointer, or some other fixed role) ๐ฆ- reg has to be an actual register name. The accepted names depend on the machine and are defined in the
REGISTER_NAMESmacro in the machine description macro file ๐ - There's no negative form for this one, since it's a three-way choice โจ
- reg has to be an actual register name. 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 the register reg ๐
- It's an error to use this with the frame pointer or stack pointer ๐
- Using it on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results ๐ญ
- No negative form, 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 even be used for temporaries or variables that live across a call ๐ธ- Functions compiled this way save and restore the register reg if they use it ๐ซถ
- It's an error to use this with the frame pointer or stack pointer ๐
- Using it on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results ๐ญ
- Using it on a register where function values may be returned causes a different kind of disaster ๐
- No negative form, since it's a three-way choice โจ
-fpack-struct[=n]: with no value, this packs all structure members together without holes ๐งฉ If you give it a value, which has to be a small power of two, members get packed according to that value as the maximum alignment. Objects whose default alignment requirements are larger than this get output potentially unaligned at the next fitting location ๐
โ ๏ธ Warning: the -fpack-struct switch makes GCC generate code that is not binary compatible with code generated without that switch. It also makes the code suboptimal, so only use it to conform to a non-default application binary interface ๐ญ
-fleading-underscore: this one and its counterpart,-fno-leading-underscore, forcibly change the way C symbols are represented in the object file ๐ง One use is to help link with legacy assembly code ๐ฐ๏ธ
โ ๏ธ Warning: the -fleading-underscore switch makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface, and know that not all targets fully support it ๐
-ftls-model=model: alter the thread-local storage model. model should be one ofglobal-dynamic,local-dynamic,initial-execorlocal-exec๐งต- The choice is subject to optimization. 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 choice is subject to optimization. The compiler might use a more efficient model for symbols that aren't visible outside the translation unit, or if
-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 small piece of code 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 ๐
- Because of that, 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 avoid generating trampolines when it computes that's safe and swap them for descriptors instead ๐ซง- Descriptors are made up of data only, but the generated code has to be prepared 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 handled with 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 ๐ธ
-fvisibility=[default|internal|hidden|protected]: set the default ELF image symbol visibility to the option you pick. Every symbol gets marked with this unless the code overrides it ๐ท Using this can really 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 for any shared objects you distribute ๐ฅ- Despite the name,
defaultalways means public, which means available to be linked against from outside the shared object ๐ซฃ protectedandinternalare pretty useless in real-world usage, so the only other commonly used option ishidden๐- If you don't specify
-fvisibility, the default isdefault, which makes every symbol public ๐ - For a good explanation of why correct ELF symbol visibility is worth it, check out "How To Write Shared Libraries" by Ulrich Drepper, which you can find at
https://www.akkadia.org/drepper/๐ - A superior trick this option makes possible, compared to marking things hidden when the default is public, is to make the default
hiddenand then mark things public. This is the norm with DLLs on Windows. With-fvisibility=hiddenand__attribute__ ((visibility("default")))instead of__declspec(dllexport), you get almost identical semantics with identical syntax. That's a huge win for cross-platform projects ๐ - If you're adding visibility support to existing code,
#pragma GCC visibilitycan help. Wrap the declarations you want to set visibility for with#pragma GCC visibility push(hidden)and#pragma GCC visibility pop๐ง - Keep in mind that symbol visibility is part of the API interface contract. So all new code should always specify visibility when it isn't the default. Declarations only for use within the local DSO should always be explicitly marked
hiddento avoid PLT indirection overheads. Making that clear also helps readability and self-documentation ๐ - Because of ISO C++ specification requirements,
operator newandoperator deletemust always have default visibility ๐ - Headers from outside your project, especially system headers and headers from any other library you use, may not expect to be compiled with a visibility other than the default. You may need to say
#pragma GCC visibility push(default)before including them ๐ซถ externdeclarations aren't affected by-fvisibility, so lots of code can be recompiled with-fvisibility=hiddenwith no modifications ๐- However, that means calls to
externfunctions with no explicit visibility use the PLT. So it's more effective to use__attribute ((visibility))and/or#pragma GCC visibilityto tell the compiler whichexterndeclarations should be treated as hidden ๐ -fvisibilitydoes affect C++ vague linkage entities. For instance, an exception class that's thrown between DSOs must be explicitly marked with default visibility so thetype_infonodes are unified between the DSOs ๐งพ- You can find an overview of these techniques, their benefits, and how to use them at
https://gcc.gnu.org/wiki/Visibilityโจ
- Despite the name,
-fstrict-volatile-bitfieldsโ ๐ Okay bestie, this one is for volatile bit-fields (and other structure fields, though the compiler usually respects those types anyway). Use it when you want each access to be a single access at the width of the field's type, lined up to natural alignment if that's possible. Say your target has memory-mapped peripheral registers that need every access to be 16 bits wide. With this flag you can declare all the peripheral bit-fields asunsigned short(assumingshortis 16 bits on those targets) so GCC uses 16-bit accesses instead of, like, a more efficient 32-bit one ๐
If this option is disabled, the compiler picks the most efficient instruction. In the example above, that might be a 32-bit load, even though it reads bytes with no part of the bit-field in them, or memory-mapped registers unrelated to the one getting updated. ๐ฌ
In some cases, like when the packed attribute is applied to a structure field, it might not be possible to access the field with one read or write that's correctly aligned for the target machine. When that happens, GCC falls back to generating multiple accesses instead of code that will fault or truncate the result at run time. ๐
Note: Due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members. 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 one controls whether any out-of-line instance of the__syncfamily of functions can be used to implement the C++11__atomicfamily of functions. It's enabled by default, so the only useful form is-fno-sync-libcalls. It's used in the implementation of the libatomic runtime library. โจ
โจ GCC Developer Options โจ
okay so this section is for the GCC developers ๐ง It covers command-line options that are mainly for compiler testing, investigating compiler bugs, and looking into compile-time performance problems. That includes options that make debug dumps at various points in compilation, options that print stats 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 compiling and linking, so don't panic if you've never seen them ๐
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 left off, GCC builds a default dump file name by sticking together the base dump file name, a pass number, a phase letter, and the pass name. The base dump file name is the name of the output file the compiler made, if you explicitly specified one and it's not an executable. Otherwise it's the source file name. The pass number comes from the order the passes were registered with the compiler's pass manager. That's usually the same as execution order, BUT passes registered by plugins, target-specific passes, or passes that get registered late are numbered higher than the pass named final, even if they actually run earlier. The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree). The files get created in the directory of the output file. ๐
-fcallgraph-info,-fcallgraph-info=MARKERSโ ๐ธ๏ธ This makes the compiler output callgraph information for the program, one per object file. The info is generated in the common VCG format. You can decorate it with extra per-node and/or per-edge info by adding a list of comma-separated markers. If you specify thesumarker, the callgraph gets decorated with stack usage information, which is equivalent to-fstack-usage. If you specify thedamarker, the callgraph gets decorated with info about dynamically allocated objects. ๐
Heads up: When compiling with-flto, no callgraph information is output along with the object file. At LTO link time,-fcallgraph-infomay generate multiple callgraph information files next to the intermediate LTO output files. ๐
-dletters,-fdump-rtl-pass,-fdump-rtl-pass=filenameโ ๐ท These say "make debugging dumps during compilation at the times specified by the letters." This is how you debug the RTL-based passes of the compiler. ๐ซถ
Some -dletters switches mean something different when you use -E for preprocessing. ๐
You can turn on debug dumps with a -fdump-rtl switch or with some -d option letters. Here's what each possible letter/pass name does when you use it:
-fdump-rtl-alignmentsโ ๐ Dump after branch alignments have been computed.-fdump-rtl-asmconsโ ๐งฉ Dump after fixing RTL statements that have unsatisfied in/out constraints.-fdump-rtl-auto_inc_decโ โ Dump after auto-inc-dec discovery. This pass only runs on architectures that have auto inc or auto dec instructions.-fdump-rtl-barriersโ ๐ง Dump after cleaning up the barrier instructions.-fdump-rtl-bbpartโ โ๏ธ Dump after partitioning hot and cold basic blocks.-fdump-rtl-bbroโ ๐ Dump after block reordering.-fdump-rtl-btl1,-fdump-rtl-btl2โ ๐ฏ These two enable dumping after the two branch target load optimization passes.-fdump-rtl-bypassโ โญ๏ธ Dump after jump bypassing and control flow optimizations.-fdump-rtl-combineโ ๐ง Dump after the RTL instruction combination pass.-fdump-rtl-compgotosโ ๐ฆ Dump after duplicating the computed gotos.-fdump-rtl-ce1,-fdump-rtl-ce2,-fdump-rtl-ce3โ ๐ These enable dumping after the three if conversion passes.-fdump-rtl-cprop_hardregโ ๐ Dump after hard register copy propagation.-fdump-rtl-csaโ ๐ฅ Dump after combining stack adjustments.-fdump-rtl-cse1,-fdump-rtl-cse2โ ๐ These enable dumping after the two common subexpression elimination passes.-fdump-rtl-dceโ ๐๏ธ Dump after the standalone dead code elimination passes.-fdump-rtl-dbrโ ๐ฐ๏ธ Dump after delayed branch scheduling.-fdump-rtl-dce1,-fdump-rtl-dce2โ ๐งน These enable dumping after the two dead store elimination passes.-fdump-rtl-ehโ ๐ก๏ธ Dump after finalization of EH handling code.-fdump-rtl-eh_rangesโ ๐บ๏ธ Dump after conversion of EH handling range regions.-fdump-rtl-expandโ ๐ฑ Dump after RTL generation.-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ โก๏ธ These enable dumping after the two forward propagation passes.-fdump-rtl-gcse1,-fdump-rtl-gcse2โ ๐ These enable dumping after global common subexpression elimination.-fdump-rtl-init-regsโ ๐ Dump after the initialization of the registers.-fdump-rtl-initvalsโ ๐ฌ Dump after the computation of the initial value sets.-fdump-rtl-into_cfglayoutโ ๐ Dump after converting to cfglayout mode.-fdump-rtl-iraโ ๐๏ธ Dump after iterated register allocation.-fdump-rtl-jumpโ ๐ฆ Dump after the second jump optimization.-fdump-rtl-loop2โ ๐ This enables dumping after the RTL loop optimization passes.-fdump-rtl-machโ โ๏ธ Dump after performing the machine dependent reorganization pass, if that pass exists.-fdump-rtl-mode_swโ ๐ Dump after removing redundant mode switches.-fdump-rtl-rnregโ ๐ข Dump after register renumbering.-fdump-rtl-outof_cfglayoutโ ๐ค Dump after converting from cfglayout mode.-fdump-rtl-peephole2โ ๐ฌ Dump after the peephole pass.-fdump-rtl-postreloadโ ๐ง Dump after post-reload optimizations.-fdump-rtl-pro_and_epilogueโ ๐ Dump after generating the function prologues and epilogues.-fdump-rtl-sched1,-fdump-rtl-sched2โ ๐ These enable dumping after the basic block scheduling passes.-fdump-rtl-reeโ โ๏ธ Dump after sign/zero extension elimination.-fdump-rtl-seqabstrโ ๐งฌ Dump after common sequence discovery.-fdump-rtl-shortenโ ๐ฉณ Dump after shortening branches.-fdump-rtl-siblingโ ๐ฏ Dump after sibling call optimizations.-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.-fdump-rtl-smsโ ๐ Dump after modulo scheduling. This pass only runs on some architectures.-fdump-rtl-stackโ ๐ Dump after the conversion from GCC's "flat register file" registers to the x87's stack-like registers. This pass only runs on x86 variants.-fdump-rtl-subreg1,-fdump-rtl-subreg2โ ๐งฒ These enable dumping after the two subreg expansion passes.-fdump-rtl-unshareโ ๐ Dump after all RTL has been unshared.-fdump-rtl-vartrackโ ๐ต๏ธ Dump after variable tracking.-fdump-rtl-vregsโ ๐ช Dump after converting virtual registers to hard registers.-fdump-rtl-webโ ๐ธ๏ธ Dump after live range splitting.-fdump-rtl-regclass,-fdump-rtl-subregs_of_mode_init,-fdump-rtl-subregs_of_mode_finish,-fdump-rtl-dfinit,-fdump-rtl-dfinishโ ๐ซฅ These are defined but always produce empty files. Bestie, don't waste your time on them ๐-da,-fdump-rtl-allโ ๐ฐ Produce all the dumps listed above.-dAโ ๐ท๏ธ Annotate the assembler output with miscellaneous debugging information.-dDโ ๐ Dump all macro definitions, at the end of preprocessing, in addition to the normal output.-dHโ ๐ฅ Produce a core dump whenever an error occurs. ๐ญ-dpโ okay bestie, this one sprinkles a little comment into the assembler output telling you which pattern and alternative got used ๐ง It also prints the length and cost of each instruction ๐-dPโ this dumps the RTL into the assembler output as a comment right before each instruction ๐ฅ It also switches on-dpannotation, so you get both โจ-dxโ no full compile for you! This just generates RTL for a function instead ๐ฆ It's usually paired with-fdump-rtl-expand๐
-fdump-debugโ dumps the debugging info generated during the debug generation phase ๐ธ-fdump-earlydebugโ dumps the debugging info generated during the early debug generation phase ๐-fdump-noaddrโ when you're making debugging dumps, this suppresses address output ๐ It makes it way more doable todiffdumps from compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations ๐-freport-bugโ if an internal compiler error (ICE) happens, this collects and dumps debug info into a temporary file for you ๐ญ-fdump-unnumberedโ in debugging dumps, this suppresses instruction numbers and address output ๐ฆ Super helpful for diffing dumps from different options, especially with and without-g๐-fdump-unnumbered-linksโ when doing debugging dumps (check the-doption above ๐), this suppresses instruction numbers for the links to the previous and next instructions in a sequence ๐ง
-fdump-ipa-switch,-fdump-ipa-switch-optionsโ these control dumping the inter-procedural analysis language tree to a file at various stages ๐ The file name comes from appending a switch-specific suffix to the source file name, and the file is created in the same directory as the output file ๐ The possible dumps are:allโ enables all inter-procedural analysis dumps โจcgraphโ dumps info about call-graph optimization, unused function removal, and inlining decisions ๐inlineโ dumps after function inlining ๐ฅ
On top of that, you can add -optimized, -missed, -note, and -all. They mean the same thing as they do for -fopt-info, and they default to -optimized ๐
For example, -fdump-ipa-inline-optimized-missed will show you the callsites that got inlined, plus the ones that didn't ๐
By default, the dump includes messages about successful optimizations (same as -optimized) along with the low-level details of the analysis ๐ซถ
-fdump-langโ dumps language-specific info. The file name is the source file name with.langappended ๐ฆ-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ these control dumping language-specific info ๐ Theoptionsandfilenamebits work exactly like they do for-fdump-tree๐ซถ Here are the accepted switch values:allโ enables all language-specific dumps ๐classโ dumps class hierarchy info. Virtual table info gets emitted unless 'slim' is specified. This is C++ only ๐moduleโ dumps module info. The options lineno (locations), graph (reachability), blocks (clusters), uid (serialization), alias (mergeable), asmname (Elrond), eh (mapper) & vops (macros) may add extra info. This is C++ only ๐งrawโ dumps the raw internal tree data. This is C++ only ๐
-fdump-passesโ prints the list of optimization passes that your current command-line options turn on and off, straight to stderr ๐ฅ-fdump-statistics-optionโ enables and controls dumping pass statistics into a separate file ๐ The file name is the source file name with a suffix ending in.statisticsappended, and it's created in the same directory as the output file. If you use the-optionform,-statssums the counters over the whole compilation unit, while-detailsdumps every event as the passes generate it. With no option at all, the counters are summed for each function compiled ๐
-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filenameโ these control dumping the intermediate language tree at various stages of processing, into a file ๐ณ If you use the-optionsform,optionsis a list of--separated options that control the dump details. Not every option applies to every dump, and the ones that don't make sense get ignored ๐ The available options are:addressโ prints the address of each node. This usually isn't meaningful because it changes with the environment and source file. Its main job is tying a dump file to a debug environment ๐งasmnameโ ifDECL_ASSEMBLER_NAMEhas been set for a decl, this uses that in the dump instead ofDECL_NAME. It's mainly handy for working backward from mangled names in the assembly file ๐ฅslimโ when dumping front-end intermediate representations, this stops members of a scope or function body from being dumped just because the scope was reached. Those only get dumped when some other path directly reaches them. When dumping pretty-printed trees, it skips the bodies of control structures. When dumping RTL, it prints the RTL in slim (condensed) form instead of the default LISP-like representation ๐rawโ prints a raw representation of the tree. By default, trees get pretty-printed into a C-like representation ๐ธdetailsโ enables more detailed dumps (not every dump option honors it). It also includes info from the optimization passes โจstatsโ enables dumping various statistics about the pass (not every dump option honors it) ๐blocksโ enables showing basic block boundaries (disabled in raw dumps) ๐งฑgraphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a control flow graph representation suitable for viewing with GraphViz, written tofile.passid.pass.dot. Each function in the file is pretty-printed as a subgraph, so GraphViz can render them all in one plot. This only works for RTL dumps right now, and the RTL is always dumped in slim form ๐ฆvopsโ enables showing virtual operands for every statement ๐ซถlinenoโ enables showing line numbers for statements ๐uidโ enables showing the unique ID (DECL_UID) for each variable ๐verboseโ enables showing the tree dump for each statement ๐ehโ enables showing the EH region number holding each statement ๐scevโ enables showing scalar evolution analysis details ๐optimizedโ enables showing optimization info (only available in certain passes) ๐missedโ enables showing missed optimization info (only available in certain passes) ๐noteโ enables other detailed optimization info (only available in certain passes) ๐allโ turns on all options exceptraw,slim,verboseandlineno๐optallโ turns on all optimization options, i.e.,optimized,missed, andnote๐ฅ
To figure out which tree dumps exist, or to find the dump for a pass you care about, follow these steps:
- Invoke GCC with
-fdump-passesand look in the stderr output for the code matching the pass you want. For example, the codestree-evrp,tree-vrp1, andtree-vrp2correspond to the three Value Range Propagation passes. The number at the end tells apart the different invocations of the same pass ๐ง - To turn on creating 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-evrpoption. You can optionally name the dump file. If you don't, GCC creates one as described below ๐ - Find the pass dump in a file whose name has three parts separated by periods: the name of the source file GCC was invoked to compile, a numeric suffix for the pass number followed by the letter
tfor tree passes (or the letterrfor RTL passes), and finally the pass code. For example, the Early VRP pass dump might be in a file namedmyfile.c.038t.evrpin the current working directory. Heads up, though: the numeric codes aren't stable and can change from one version of GCC to another ๐ญ
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ these control optimization dumps from the various optimization passes ๐ซ If you use the-optionsform,optionsis a list of--separated option keywords that pick the dump details and which optimizations to include.
The options split into 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.
Options from each group can be mixed freely since they don't overlap. If there's a conflict, the later options on the command line override the earlier ones โจ
The following options control which kinds of messages get emitted:
optimizedโ prints info when an optimization is successfully applied. It's up to each pass to decide what's relevant. For example, the vectorizer passes print the source location of loops that 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๐
The following option controls the dump verbosity:
The internals keyword is the deep-dive one ๐ค By default, only the "high-level" messages get emitted. This turns on the extra, more detailed messages, which are mostly of interest to GCC developers ๐ ๏ธ
One or more of these keywords can be used to describe a group of optimizations ๐
ipaโ dumps from all the interprocedural optimizations ๐ฆloopโ dumps from all the loop optimizations ๐inlineโ dumps from all the inlining optimizations ๐ธompโ dumps from all OMP (Offloading and Multi Processing) optimizations ๐งvecโ dumps from all the vectorization optimizations ๐optallโ dumps from every optimization ๐ It's a superset of the groups above
If you leave the options out, it defaults to optimized-optall โจ That means you get messages about the successful optimizations from all the passes, minus anything tagged as "internals" ๐
If you give it a filename, the dumps from all the applicable optimizations get concatenated into that file. Otherwise the dump goes to stderr ๐ฅ๏ธ You can use multiple -fopt-info options, but only one of them can include a filename. If other filenames are provided, then all but the first such option get ignored ๐
โโ๏ธ
Heads up ๐จ the output filename gets overwritten when you have multiple translation units. If you want combined output from several translation units, use stderr instead.
Here's the vibe in action ๐ธ In this example, the optimization info goes to stderr:
gcc -O3 -fopt-info
This example:
gcc -O3 -fopt-info-missed=missed.all
outputs the missed optimization report from all the passes into missed.all. And this one:
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
prints info about missed optimization opportunities from the vectorization passes on stderr. Note that -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec. The order of the optimization group names and message types listed after -fopt-info does not matter ๐ซถ
As another example,
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
outputs info about missed optimizations, plus optimized locations, from all the inlining passes into inline.txt ๐ฆ
Finally, consider:
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Okay this one is a conflict ๐ค The two output filenames vec.miss and loop.opt clash, since only one output file is allowed. In this case, only the first option takes effect and the subsequent options are ignored. So only vec.miss is produced, and it contains dumps from the vectorizer about missed opportunities ๐
โจ -fsave-optimization-record
Writes a SRCFILE.opt-record.json.gz file detailing what optimizations were performed, for those 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 ๐ค Think of it as a collection of messages with source file, line number, and column number, plus these extra bits for each message:
- the execution count of the code being optimized, plus metadata about whether it came from actual profile data or was 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 when a function is inlined into several different places (which might themselves be inlined), you can tell the copies apart ๐งฉ
- objects identifying the parts of the message that refer to expressions, statements, or symbol-table nodes, which 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
Also, 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 ๐ง
- For n greater than zero,
-fsched-verboseoutputs the same information as-fdump-rtl-sched1and-fdump-rtl-sched2. - For n greater than one, it also outputs basic block probabilities, detailed ready list information, and unit/insn info.
- For n greater than two, it includes RTL at the abort point, control-flow, and regions info.
- For n over four,
-fsched-verbosealso includes dependence info.
โจ -fenable-kind-pass / -fdisable-kind-pass=range-list
This is a set of options for explicitly disabling and enabling optimization passes ๐ง They're meant for debugging GCC ๐ 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, append a sequential number starting from 1 to the pass name.-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 multiple times, append a sequential number starting from 1 to the pass name. range-list is a comma-separated list of function ranges or assembler names. Each range is a number pair separated by a colon, and it's 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 shows up in the function header of a dump file, and you can dump the pass names with the 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 multiple times, append a sequential number starting from 1 to the pass name.-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 to use these options ๐
# 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
Enables internal consistency checking ๐ง The default depends on the compiler configuration. -fchecking=2 enables further internal consistency checking that 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 ๐ฒ It's also used to place unique stamps in coverage data files and in the object files that produce them. You can use -frandom-seed 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 should be different for every file you compile ๐ซถ
โจ -save-temps
Stores the usual "temporary" intermediate files permanently ๐ They get named as auxiliary output files, as specified under -dumpbase and -dumpdir.
When used with the -x command-line option, -save-temps is sensible enough to avoid overwriting an input source file that has the same extension as an intermediate file ๐ง To get the corresponding intermediate file, rename the source file before using -save-temps.
โจ -save-temps=cwd
Equivalent to -save-temps -dumpdir ./ ๐
โจ -save-temps=obj
Equivalent to -save-temps -dumpdir outdir/, where outdir/ is the directory of the output file specified after the -o option, including any directory separators ๐ If the -o option isn't used, -save-temps=obj behaves like -save-temps=cwd.
โจ -time[=file]
Reports the CPU time taken by each subprocess in the compilation sequence โฑ๏ธ For C source files, that's the compiler proper and the assembler, plus the linker if linking is done.
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 number 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 is 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 before the program name, and the options passed to the program are displayed. That way you can later tell which file was being compiled and with which options ๐
-fdump-final-insns[=file]โ okay so this one dumps the final internal representation (RTL) intofile๐พ. If you leave the optional argument off (orfileis"."), the dump file name gets built by tacking.gkdonto the dump base name. See-dumpbase๐ธ-fcompare-debug[=opts]โ this one is a whole vibe ๐- If no error shows up during compilation, the compiler runs a second time, adding
optsand-fcompare-debug-secondto the arguments for that second run. Both runs dump the final internal representation, and it prints an error if the two dumps don't match ๐ - If you leave off the equal sign, the default
-gtogglegets used โจ - The environment variable
GCC_COMPARE_DEBUG๐, if it's defined, non-empty and nonzero, implicitly turns on-fcompare-debug. If it's defined to a string that starts with a dash, that string becomesopts. Otherwise you get the default-gtoggle๐ซถ -fcompare-debug=, with the equal sign but noopts, is the same as-fno-compare-debug. That turns off the dumping and the second compilation, and it stops evenGCC_COMPARE_DEBUGfrom taking effect ๐- Want full coverage during
-fcompare-debugtesting? SetGCC_COMPARE_DEBUGto-fcompare-debug-not-overridden. GCC rejects that as an invalid option in any real compilation (preprocessing, assembly or linking don't count) ๐ Just want a warning instead? SettingGCC_COMPARE_DEBUGto-w%n-fcompare-debug not overriddenwill do the trick ๐ฆ
- If no error shows up during compilation, the compiler runs a second time, adding
-fcompare-debug-secondโ this one gets passed to the compiler automatically for the second run that-fcompare-debugasks for ๐. It comes with options that silence warnings, and it drops 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.gkextension during that second run, 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 itself ๐ค
-gtoggleโ flips debug info generation ๐. If leaving out this option would generate debug info, it turns it off. Otherwise it turns debug info on at level 2 โญ. Its position on the command line doesn't matter. It takes effect after all the other options are processed, and it only does it once, no matter how many times you give it. It's mainly meant to go with-fcompare-debug๐-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-assignmentsthe same way-gtoggletoggles-g๐ฆ-Qโ makes the compiler print each function name as it gets compiled, and print some statistics about each pass when it's done ๐-ftime-reportโ makes the compiler print some stats about how much time each pass ate when it finishes โฑ๏ธ-ftime-report-detailsโ records the time used by the infrastructure parts separately for each pass ๐-fira-verbose=nโ controls how verbose the dump file for the integrated register allocator is. The default value is5๐ธ. Ifnis greater than or equal to10, the dump output goes tostderrin the same format asnminus10๐-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 for GCC developers who are processing object files in LTO mode (via-flto) ๐งโ๐ป- It's disabled by default ๐ โโ๏ธ
-flto-report-wpaโ same as-flto-report, but it only prints for the WPA phase of link-time optimization ๐ฏ-fmem-reportโ makes the compiler print some stats about permanent memory allocation when it finishes ๐ง-fmem-report-wpaโ makes the compiler print some stats about permanent memory allocation for the WPA phase only ๐ง-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ makes the compiler print some stats about permanent memory allocation either before or after interprocedural optimization ๐-fprofile-reportโ makes the compiler print some stats about how consistent the (estimated) profile is and what effect each individual pass had ๐-fstack-usageโ this one gives you stack usage info for your program, function by function ๐ฅ. The dump file name is made by appending.suto theauxname. Theauxnamecomes from the output file's name if you explicitly specified one and it isn't an executable. Otherwise, it's the basename of the source file ๐. Each entry has three fields:- The name of the function ๐
- A number of bytes ๐ข
- One or more qualifiers:
"static","dynamic","bounded"๐ท๏ธ
The "static" qualifier means the function handles the stack in a fixed way. A set number of bytes gets allocated for the frame when the function starts and released when it exits, and the function doesn't do any other stack adjustments. The second field is that fixed number of bytes ๐งฑ
The "dynamic" qualifier means the function also adjusts the stack inside its body on top of that static allocation. For example, it might push and pop arguments around function calls ๐ข. If "bounded" is also there, the amount of those adjustments has a compile-time bound, and the second field is an upper bound on the total stack the function uses ๐ฏ. If "bounded" isn't there, the adjustments aren't bounded at compile time, and the second field only covers the bounded part ๐
-fstatsโ emits stats about front-end processing at the end of compilation ๐. Only the C++ front end supports this, and the info is mostly only useful to the G++ development team ๐ค-fdbg-cnt-listโ prints the name and the counter upper bound for every debug counter ๐-fdbg-cnt=counter-value-listโ sets the internal debug counter lower and upper bounds ๐๏ธ.counter-value-listis a comma-separated list ofname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]tuples. Each one sets the counter's name and a list of closed intervals. Thelower_boundis optional, and it's 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 filelibrarythat would be used when linking, and then stops ๐๏ธ. With this option, GCC doesn't compile or link anything. It just prints the file name ๐โโ๏ธ-print-multi-directoryโ prints the directory name for the multilib picked by any other switches on the command line ๐. That directory is supposed to exist inGCC_EXEC_PREFIX๐-print-multi-libโ prints the mapping from multilib directory names to the compiler switches that enable them ๐บ๏ธ. The directory name is separated from the switches by;. Each switch starts with@instead of-, and there are no spaces between multiple switches. This is supposed to make shell processing easier ๐-print-multi-os-directoryโ prints the path to the OS libraries for the selected multilib, relative to somelibsubdirectory ๐- If the OS libraries are in the
libsubdirectory and no multilibs are used, this is usually just.๐ - If the OS libraries are in
libsuffixsibling directories, it prints something like../lib64,../libor../lib32๐ - If the OS libraries are in
lib/subdirsubdirectories, it prints something likeamd64,sparcv9orev6๐
- If the OS libraries are in the
-print-multiarchโ prints the path to the OS libraries for the selected multiarch, relative to somelibsubdirectory ๐งฉ-print-prog-name=programโ same vibe as-print-file-name, but it searches for a program likecppinstead ๐-print-libgcc-file-nameโ same as-print-file-name=libgcc.a๐- This is super useful when you use
-nostdlibor-nodefaultlibsbut you still want to link withlibgcc.a๐ซถ. You can do:
- This is super useful when you use
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirsโ prints the name of the configured installation directory, plus a list of the program and library directoriesgccsearches. Then it stops, no extra work ๐ต๏ธโโ๏ธ- This one saves you when
gccthrows the errorinstallation problem, cannot exec cpp0: No such file or directory.๐ญ. To fix it, you either putcpp0and the other compiler components wheregccexpects them, or you set the environment variableGCC_EXEC_PREFIXto the directory where you installed them ๐ฉน. And don't forget the trailing/!
- This one saves you when
-print-sysrootโ prints the target sysroot directory used during compilation ๐บ๏ธ. That's the target sysroot set either at configure time or with the--sysrootoption, possibly with an extra suffix that depends on compilation options. If no target sysroot is specified, it prints nothing ๐คทโโ๏ธ-print-sysroot-headers-suffixโ prints the suffix added to the target sysroot when searching for headers. If the compiler isn't configured with a suffix like that, it gives an error instead. Then it stops, no extra work ๐-dumpmachineโ prints the compiler's target machine, likei686-pc-linux-gnu, and then stops ๐ฅ๏ธ-dumpversionโ prints the compiler version, like3.0,6.3.0or7, and then stops ๐. This is the version used in filesystem paths and specs. Depending on how the compiler was configured, it 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, then stops ๐. This is what gets used when GCC itself is being built ๐ ๏ธ
๐ Machine-Dependent Options
Each target machine GCC supports can have its own options. For example, they let you compile for a particular processor variant or ABI, or control optimizations specific to that machine ๐. By convention, machine-specific option names start with -m ๐.
โจ AArch64 Options โจ
Okay bestie, these options are defined for AArch64 implementations ๐ฆ
-mabi=nameโ pick your data model ๐ The valid picks areilp32, the SysV-like model whereint,long intand pointers are all 32 bits, andlp64, the SysV-like model whereintis 32 bits butlong intand pointers are 64 bits. The default depends on your specific target configuration.
โ ๏ธ Heads up, the LP64 and ILP32 ABIs are not link-compatible ๐ญ You have to compile your whole program with the same ABI and link it with a compatible set of libraries, or it'll be a mess.
-mbig-endianโ generate big-endian code ๐ This is the default when GCC is configured for anaarch64_be-*-*target.-mgeneral-regs-onlyโ only use the general-purpose registers ๐ This stops the compiler from touching floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler.-mlittle-endianโ generate little-endian code ๐ธ This is the default when GCC is configured for anaarch64-*-*target but not anaarch64_be-*-*one.-mcmodel=tinyโ use the tiny code model ๐ง The program and its statically defined symbols have to be within 1MB of each other. Programs can be statically or dynamically linked.-mcmodel=smallโ use the small code model ๐ The program and its statically defined symbols have to be within 4GB of each other. Programs can be statically or dynamically linked. This is the default code model, so you're already in it unless you say otherwise โจ-mcmodel=largeโ use the large code model ๐ It makes no assumptions about addresses and section sizes, which is very main character energy. Programs can only be statically linked. Also,-mcmodel=largeis incompatible with-mabi=ilp32,-fpicand-fPIC, so don't mix them ๐-mstrict-align,-mno-strict-alignโ avoid or allow memory accesses that might not be aligned on a natural object boundary, as the architecture spec describes ๐ฅ-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ omit or keep the frame pointer in leaf functions ๐ฆ Omitting it (the-momit-leaf-frame-pointerbehaviour) is the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generate stack protection code that uses a canary atguard๐ก๏ธ The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register.
With the sysreg choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also tell GCC which system register to use as the base register for reading the canary, and what offset from that base register to read from. There's no default register or offset for this, because it's entirely meant for use within the Linux kernel ๐ง
-mtls-dialect=descโ use TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables. This is the default โจ-mtls-dialect=traditionalโ use traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐-mtls-size=sizeโ set the bit size of immediate TLS offsets. The valid values are12,24,32and48. Heads up, this one needs binutils 2.26 or newer ๐ง-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ turn the workaround for ARM Cortex-A53 erratum number 835769 on or off ๐ฉน The workaround inserts a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions.-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419โ turn the workaround for ARM Cortex-A53 erratum number 843419 on or off ๐ฉน This workaround happens at link time, so this option only passes the matching flag along to the linker.-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ turn the reciprocal square root approximation on or off ๐งฎ This option only does anything if-ffast-mathor-funsafe-math-optimizationsis used too. When it's on, reciprocal square root results drop to about 16 bits of precision for single precision and 32 bits for double precision.-mlow-precision-sqrt,-mno-low-precision-sqrtโ turn the square root approximation on or off ๐งฎ This option only does anything if-ffast-mathor-funsafe-math-optimizationsis used too. When it's on, square root results drop to about 16 bits of precision for single precision and 32 bits for double precision. If you enable it, it also implies-mlow-precision-recip-sqrt.-mlow-precision-div,-mno-low-precision-divโ turn the division approximation on or off โ This option only does anything if-ffast-mathor-funsafe-math-optimizationsis used too. When it's on, division results drop to about 16 bits of precision for single precision and 32 bits for double precision.-mtrack-speculation,-mno-track-speculationโ turn on or off the extra code that tracks speculative execution through conditional branches ๐ต๏ธ The tracking state can then be used by the compiler when it expands calls to"__builtin_speculation_safe_copy", so it can generate a more efficient code sequence.-moutline-atomics,-mno-outline-atomicsโ turn calls to out-of-line helpers for atomic operations on or off ๐งต At runtime, these helpers figure out whether the LSE instructions from ARMv8.1-A can be used. If they can't, they fall back to the load/store-exclusive instructions that are in the base ARMv8.0 ISA.
This option only applies when you're compiling for the base ARMv8.0 instruction set. If you're using a later revision, like -march=armv8.1-a or -march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for -mcpu= when the chosen CPU supports the lse feature. This option is on by default ๐
-march=nameโ pick the target architecture and, optionally, one or more feature modifiers ๐๏ธ This option takes the form-march=arch{+[no]feature}*.
Here's the cheat sheet for the permissible arch values and the features each one turns on by default:
armv8-a(Armv8-A) โ includes by default+fp,+simdarmv8.1-a(Armv8.1-A) โ includes by defaultarmv8-a,+crc,+lse,+rdmaarmv8.2-a(Armv8.2-A) โ includes by defaultarmv8.1-aarmv8.3-a(Armv8.3-A) โ includes by defaultarmv8.2-a,+pautharmv8.4-a(Armv8.4-A) โ includes by defaultarmv8.3-a,+flagm,+fp16fml,+dotprodarmv8.5-a(Armv8.5-A) โ includes by defaultarmv8.4-a,+sb,+ssbs,+predresarmv8.6-a(Armv8.6-A) โ includes by defaultarmv8.5-a,+bf16,+i8mmarmv8.7-a(Armv8.7-A) โ includes by defaultarmv8.6-a,+ls64armv8.8-a(Armv8.8-a) โ includes by defaultarmv8.7-a,+mopsarmv9-a(Armv9-A) โ includes by defaultarmv8.5-a,+sve,+sve2armv8-r(Armv8-R) โ includes by defaultarmv8-r
The value native is available on native AArch64 GNU/Linux and tells the compiler to pick the architecture of the host system. This option has no effect if the compiler can't recognize the host system's architecture,
The permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one wins ๐
GCC uses name to decide what kind of instructions it can emit when generating assembly code. If -march is specified without -mtune or -mcpu also being specified, the code gets tuned to perform well across a range of target processors that implement the target architecture ๐ฏ
-mtune=nameโ pick the target processor that GCC 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,
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-x2, cortex-a510, cortex-a710, ampere1, 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. In other words, it's tuning for Neoverse cores that can run 4 128-bit Advanced SIMD arithmetic instructions a cycle, and an equal number of SVE arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE). It's more general than tuning for one specific core like Neoverse V1, but more specific than the default tuning described below ๐
On native AArch64 GNU/Linux systems, the value native also tunes performance to the host system. This option has no effect if the compiler can't recognize the processor of the host system ๐ฅ๏ธ
If none of -mtune=, -mcpu= or -march= are specified, the code gets tuned to perform well across a range of target processors ๐
This option can't be suffixed with feature modifiers ๐
-mcpu=nameโ pick the target processor, optionally with one or more feature modifiers tacked on the end ๐ง This option takes the form-mcpu=cpu{+[no]feature}*, where the permissible values forcpuare the same as the ones for-mtune. The permissible values forfeatureare documented in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one is used ๐
okay so -mcpu= is doing double duty bestie ๐
the name you pick decides which instructions GCC is allowed to emit when it writes the assembly (same job as -march) AND which chip it tunes the code to run fast on (same job as -mtune). ๐ฅ If you also pass -march or -mtune, those win and override that part of -mcpu.
-mcpu=neoverse-512tvbis the main character of this whole list ๐ It is NOT one specific core. It's a whole squad of Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle. Unless you override it with-march,-mcpu=neoverse-512tvbmakes code that can run on a Neoverse V1 core, because V1 is the first Neoverse core with those properties ๐ฆ And unless you override it with-mtune, it tunes your code the same way-mtune=neoverse-512tvbwould ๐
-moverride=stringโ this lets you override the tuning decisions the back-end makes when you use-mtune=. The syntax, semantics, and accepted values forstringare NOT guaranteed to stay the same across releases ๐ It's only really meant for people developing GCC itself ๐ง-mverbose-cost-dumpโ turns on verbose cost model dumping in the debug dump files ๐ This one is just for debugging the compiler ๐-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ enable or disable PC-relative literal loads โจ With it on, literal pools get accessed with a single instruction and are emitted after each function. The catch is that this caps the maximum size of functions at 1MB ๐ญ It's enabled by default for-mcmodel=tiny.-msign-return-address=scopeโ picks which functions get return address signing ๐ The valid values arenone(turns return address signing off),non-leaf(signs pointers for functions that aren't leaf functions), andall(signs pointers for every function). The default isnone. Heads up: this option is deprecated in favor of-mbranch-protection๐ฅ-mbranch-protection=none|standard|pac-ret[+leaf+b-key]|btiโ picks the branch protection features you want ๐ก๏ธnoneis the default and turns off every type of branch protection.standardturns on ALL of them, and for any feature with extra tuning options it sets that to its standard level.pac-ret[+leaf]turns on return address signing at its standard level, signing functions that save the return address to memory (non-leaf functions basically always do this) using the a-key. Add the optionalleafargument to extend the signing to leaf functions too. Add the optionalb-keyargument to sign with the B-key instead of the A-key.btiturns on the branch target identification mechanism ๐-mharden-sls=optsโ enables compiler hardening against straight line speculation (SLS) ๐ซถoptsis a comma-separated list of the following:retbrandblr. Also,-mharden-sls=allturns on ALL the SLS hardening, and-mharden-sls=noneturns off all of it ๐ธ-msve-vector-bits=bitsโ sets the number of bits in an SVE vector register ๐ It only does anything when SVE is enabled, so don't expect magic without it ๐
GCC does two flavors of SVE codegen, and this is where it gets lowkey technical. "Vector-length agnostic" output works with ANY size of vector register. "Vector-length specific" output lets GCC make assumptions about the vector length when that helps optimization โจ The valid values for bits are scalable, 128, 256, 512, 1024, and 2048. scalable gives you vector-length agnostic output. Right now, -msve-vector-bits=128 ALSO gives vector-length agnostic output, but only for big-endian targets. Every other value makes vector-length specific code. These values might change in future releases, so the only one you should count on for code that's portable across different hardware SVE vector lengths is scalable ๐ญ
The default is -msve-vector-bits=scalable, which makes vector-length agnostic code ๐ง
โจ -march and -mcpu Feature Modifiers โจ
okay now the feature modifiers ๐ฆ You can use any of these with -march and -mcpu, and each one also has an inverse you can write as no plus the feature name.
crcโ enables the CRC extension ๐ It's on by default for-march=armv8.1-a.cryptoโ enables the Crypto extension ๐ This also turns on Advanced SIMD and floating-point instructions.fpโ enables floating-point instructions ๐ It's on by default for every possible value of-marchand-mcpu.simdโ enables Advanced SIMD instructions ๐ฅ This also turns on floating-point instructions. It's on by default for every possible value of-marchand-mcputoo.sveโ enables Scalable Vector Extension instructions ๐ This also turns on Advanced SIMD and floating-point instructions.lseโ enables Large System Extension instructions ๐ It's on by default for-march=armv8.1-a.rdmaโ enables Round Double Multiply Accumulate instructions ๐ It's on by default for-march=armv8.1-a.fp16โ enables the FP16 extension โจ This also turns on floating-point instructions.fp16fmlโ enables the FP16 fmla extension ๐ This also turns on the FP16 extensions and floating-point instructions. It's enabled by default for-march=armv8.4-a. Using this with architectures before Armv8.2-A is NOT supported.rcpcโ enables the RcPc extension ๐ซถ This doesn't change the code GCC generates. It just gets passed along to the assembler, so inline asm statements can use RcPc instructions.dotprodโ enables the Dot Product extension ๐ This also turns on Advanced SIMD instructions.aesโ enables the Armv8-aaesandpmullcrypto extension ๐ธ This also turns on Advanced SIMD instructions.sha2โ enables the Armv8-asha2crypto extension ๐ This also turns on Advanced SIMD instructions.sha3โ enables thesha512andsha3crypto extension ๐ฎ This also turns on Advanced SIMD instructions. Using this with architectures before Armv8.2-A is NOT supported.sm4โ enables thesm3andsm4crypto extension ๐ฆ This also turns on Advanced SIMD instructions. Using this with architectures before Armv8.2-A is NOT supported.profileโ enables the Statistical Profiling extension ๐ This is only to switch the extension on at the assembler level and doesn't affect code generation.rngโ enables the Armv8.5-a Random Number instructions ๐ฒ Same deal: it's only for the assembler and doesn't affect code generation.memtagโ enables the Armv8.5-a Memory Tagging Extensions ๐ท๏ธ Using this with architectures before Armv8.5-A is NOT supported.sbโ enables the Armv8-a Speculation Barrier instruction ๐งฑ This is only for the assembler and doesn't affect code generation. It's enabled by default for-march=armv8.5-a.ssbsโ enables the Armv8-a Speculative Store Bypass Safe instruction ๐ก๏ธ This is only for the assembler and doesn't affect code generation. It's enabled by default for-march=armv8.5-a.predresโ enables the Armv8-a Execution and Data Prediction Restriction instructions ๐ This is only for the assembler and doesn't affect code generation. It's enabled by default for-march=armv8.5-a.sve2โ enables the Armv8-a Scalable Vector Extension 2 โจ This also turns on SVE instructions.sve2-bitpermโ enables SVE2 bitperm instructions ๐ This also turns on SVE2 instructions.sve2-sm4โ enables SVE2 sm4 instructions ๐ This also turns on SVE2 instructions.sve2-aesโ enables SVE2 aes instructions ๐ This also turns on SVE2 instructions.sve2-sha3โ enables SVE2 sha3 instructions ๐ฆ This also turns on SVE2 instructions.tmeโ enables the Transactional Memory Extension ๐งi8mmโ enables 8-bit Integer Matrix Multiply instructions ๐ This also turns on Advanced SIMD and floating-point instructions. It's enabled by default for-march=armv8.6-a. Using this with architectures before Armv8.2-A is NOT supported.f32mmโ enables 32-bit Floating point Matrix Multiply instructions ๐ธ This also turns on SVE instructions. Using this with architectures before Armv8.2-A is NOT supported.f64mmโ enables 64-bit Floating point Matrix Multiply instructions ๐ This also turns on SVE instructions. Using this with architectures before Armv8.2-A is NOT supported.bf16โ enables brain half-precision floating-point instructions ๐ง This also turns on Advanced SIMD and floating-point instructions. It's enabled by default for-march=armv8.6-a. Using this with architectures before Armv8.2-A is NOT supported.ls64โ enables the 64-byte atomic load and store instructions for accelerators ๐ It's enabled by default for-march=armv8.7-a.mopsโ enables the instructions that speed up memory operations like "memcpy", "memmove", "memset" ๐งน It's enabled by default for-march=armv8.8-a.flagmโ enables the Flag Manipulation instructions Extension ๐pauthโ enables the Pointer Authentication Extension ๐
Feature crypto implies aes, sha2, and simd, which implies fp. Going the other way, nofp implies nosimd, which implies nocrypto, noaes and nosha2 ๐ Lots of chain reactions here, bestie ๐ซ
๐ธ Adapteva Epiphany Options ๐ธ
these -m options are defined for Adapteva Epiphany ๐ง
-mhalf-reg-fileโ don't allocate 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โ prefers allocating registers that allow short instruction generation โจ Heads up: this can increase the instruction count, so overall code size might go down OR up ๐คทโโ๏ธ-mbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions ๐ This cost is only a heuristic and isn't guaranteed to give consistent results across releases.-mcmoveโ enables the generation of conditional moves ๐ฆ-mnops=numโ emitsnumNOPs before every other generated instruction ๐
๐ฆ -mno-soft-cmpsf ๐ฆ
-mno-soft-cmpsfโ ๐ For single-precision floating-point comparisons, this one emits anfsubinstruction and tests the flags instead. It's faster than a software comparison โจ, but it can give you incorrect results with NaNs ๐, or when two different small numbers get compared and their difference comes out as zero ๐. The default is-msoft-cmpsf, which is slower but IEEE-compliant ๐ซถ.-mstack-offset=numโ ๐ง Sets the offset between the top of the stack and the stack pointer. A value of8means the eight bytes in the rangesp+0...sp+7can be used by leaf functions without stack allocation ๐. Values other than8or16are untested and unlikely to work ๐ญ. This option also changes the ABI, so compiling a program with a different stack offset than the one the libraries were built with generally does not work ๐จ. It can be useful if you want to check whether a different stack offset gives you better code ๐, but to actually build working programs with one, it's recommended to configure the toolchain with the appropriate--with-stack-offset=numoption ๐.-mno-round-nearestโ ๐ธ Makes the scheduler assume the rounding mode has been set to truncating. The default is-mround-nearest.-mlong-callsโ ๐ If an attribute doesn't say otherwise, this assumes every call might be beyond the offset range of theb/blinstructions. So it loads the function address into a register before making a (otherwise direct) call. This is the default ๐.-mshort-callsโ ๐ฆ If an attribute doesn't say otherwise, this assumes all direct calls are within range of theb/blinstructions, so those instructions get used for direct calls. The default is-mlong-calls.-msmall16โ โจ Assumes addresses can be loaded as 16-bit unsigned values. This 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 it to the mode you predominantly 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 great for compiling libraries or other compilation units you might want to drop into different programs with different prevailing FPU modes ๐. The convenience of a single object file outweighs the extra size and speed overhead of any mode switching that might be needed, compared with a more specific choice of prevailing FPU mode.truncateโ ๐ The mode used for floating-point calculations with truncating (round towards zero) rounding. That includes conversion from floating point to integer.round-nearestโ ๐ The mode used for floating-point calculations with round-to-nearest-or-even rounding.intโ ๐งฎ The mode used to perform integer calculations in the FPU, like 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. This is an ABI change, even though many library function interfaces are unaffected if they don't use SIMD vector modes in places that affect the size and/or alignment of the 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 ๐ฅฒ.-m1reg-regโ ๐ข Specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster โญ. Allowable values forregarer43andr63, which use that register as a fixed register, andnone, which means no register is used for this purpose. The default is-m1reg-none.
๐ AMD GCN Options ๐
These options are defined specifically for the AMD GCN port ๐.
-march=gpu,-mtune=gpuโ ๐ฎ Sets the architecture type or tuning forgpu. Supported values forgpuare:fijiโ ๐๏ธ Compile for GCN3 Fiji devices (gfx803).gfx900โ ๐ฅ Compile for GCN5 Vega 10 devices (gfx900).gfx906โ ๐ Compile for GCN5 Vega 20 devices (gfx906).
-msram-ecc=on,-msram-ecc=off,-msram-ecc=anyโ ๐ก๏ธ Compiles binaries suitable for devices with the SRAM-ECC feature enabled, disabled, or either mode. This feature can be enabled per-process on some devices. The compiled code must match the device mode. The default isany, for devices that support it โจ.-mstack-size=bytesโ ๐งต Specifies how many bytes of stack space will be requested for each GPU thread (wave-front). Beware: there may be many threads and limited memory available ๐ฌ. The size of the stack allocation may also have an impact on run-time performance. The default is32KBwhen using OpenACC or OpenMP, and1MBotherwise ๐.-mxnackโ ๐ฆ Compiles binaries suitable for devices with the XNACK feature enabled. Some devices always require XNACK, and some let the user configure it. The compiled code must match the device mode. The default is-mno-xnack. At present this option is a placeholder for support that is not yet implemented ๐ง.
๐ธ ARC Options ๐ธ
The following options control the architecture variant that code is being compiled for ๐ง.
-mbarrel-shifterโ ๐ Generates instructions supported by the barrel shifter. This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ ๐ Forces a function to be called using thejli_sinstruction. This option is valid only for the ARCv2 architecture.-mcpu=cpuโ ๐ง Sets 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.arc600_normโ ๐งช Compile for ARC 600 CPU withnorminstructions enabled.arc600_mul32x16โ โ๏ธ Compile for ARC 600 CPU withnormand 32x16-bit multiply instructions enabled.arc600_mul64โ โ๏ธ Compile for ARC 600 CPU withnormandmul64-family instructions enabled.arc601_normโ ๐งช Compile for ARC 601 CPU withnorminstructions enabled.arc601_mul32x16โ โ๏ธ Compile for ARC 601 CPU withnormand 32x16-bit multiply instructions enabled.arc601_mul64โ โ๏ธ Compile for ARC 601 CPU withnormandmul64-family instructions enabled.nps400โ ๐ Compile for ARC 700 on NPS400 chip.em_miniโ ๐ชถ Compile for ARC EM minimalist configuration, featuring a reduced register set.
-mdpfp,-mdpfp-compactโ ๐ฏ Generates double-precision FPX instructions, tuned for the compact implementation.-mdpfp-fastโ โก Generates double-precision FPX instructions, tuned for the fast implementation.-mno-dpfp-lrsrโ ๐ซ Disableslrandsrinstructions from using FPX extension aux registers.-meaโ ๐งฎ Generates extended arithmetic instructions. Currently onlydivaw,adds,subs, andsat16are supported. Only valid for-mcpu=ARC700๐ .-mno-mpyโ ๐ Does not generatempy-family instructions for ARC700. This option is deprecated ๐.-mmul32x16โ โ๏ธ Generates 32x16-bit multiply and multiply-accumulate instructions.-mmul64โ โ๏ธ Generatesmul64andmulu64instructions. Only valid for-mcpu=ARC600.-mnormโ ๐งช Generatesnorminstructions. This is the default if-mcpu=ARC700is in effect.-mspfp,-mspfp-compactโ ๐ฏ Generates single-precision FPX instructions, tuned for the compact implementation.-mspfp-fastโ โก Generates single-precision FPX instructions, tuned for the fast implementation.-msimdโ ๐ Enables generation of ARC SIMD instructions via target-specific builtins. Only valid for-mcpu=ARC700.-msoft-floatโ ๐ซฅ This option is ignored; it's only provided for compatibility purposes. Software floating-point code is emitted by default, and this default can be overridden by FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision ๐คทโโ๏ธ.-mswapโ ๐ Generatesswapinstructions.-matomicโ โ๏ธ Enables 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โ โ Enablesdivandreminstructions for ARCv2 cores.
Okay so bestie, the ARC options are where things get spicy ๐ฅ. Some of these are on by default for specific chips, some are deprecated and need to be retired gracefully ๐ฅ, and the multiplier list is basically a menu of hardware vibes ๐
-mcode-densityโ turns on code density instructions for ARC EM โจ. It's already on by default for ARC HS ๐ซถ-mll64โ unlocks double load/store operations for ARC HS cores ๐ช-mtp-regno=regnoโ picks the thread pointer register number ๐งต-mmpy-option=multoโ picks the multiplier design for ARCv2 code ๐ธ. You can passmultoas a string or a number, and the default iswlh1๐. Here's the lineup:0ornoneโ no multiplier at all ๐1orwโ 16x16 multiplier, fully pipelined ๐ฆ. Turns on"mpyw"and"mpyuw".2orwlh1โ 32x32 multiplier, fully pipelined with 1 stage ๐ (this is the default โจ). Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s".3orwlh2โ 32x32 multiplier, fully pipelined with 2 stages ๐. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s".4orwlh3โ two 16x16 multipliers, blocking and sequential ๐ง. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s".5orwlh4โ one 16x16 multiplier, blocking and sequential ๐. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s".6orwlh5โ one 32x4 multiplier, blocking and sequential ๐ซง. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s".7orplus_dmpyโ ARC HS SIMD support ๐ฅ8orplus_macdโ ARC HS SIMD support ๐ฅ9orplus_qmacwโ ARC HS SIMD support ๐ฅ
Heads up, this option is only for ARCv2 cores โ ๏ธ
-mfpu=fpuโ turns on floating-point hardware extensions for ARCv2 cores ๐ฆ. These are the validfpuvalues:fpusโ single-precision floating-point โจfpudโ double-precision floating-point ๐. Single-precision is switched on too. Not available for ARC EM ๐fpudaโ double-precision using the double-precision assist instructions ๐ธ. Single-precision is also on. ARC EM only.fpuda_divโ same double-precision assist vibes asfpuda๐ธ, plus the single-precision, square-root, and divide extensions. ARC EM only.fpuda_fmaโ same double-precision assist vibes asfpuda๐ธ, plus single-precision and fused multiply and add. ARC EM only.fpuda_allโ same double-precision assist vibes asfpuda๐ธ, and all single-precision extensions are on. ARC EM only.fpus_divโ single-precision, plus square-root and divide ๐งฎfpud_divโ double-precision, plus square-root and divide. This one includesfpus_div. Not available for ARC EM ๐fpus_fmaโ single-precision, plus fused multiply and add ๐fpud_fmaโ double-precision, plus fused multiply and add. This one includesfpus_fma. Not available for ARC EM ๐fpus_allโ every single-precision floating-point extension ๐fpud_allโ every single- and double-precision floating-point extension. Not available for ARC EM ๐
-mirq-ctrl-saved=register-range, blink, lp_countโ picks which general-purpose registers the processor auto saves and restores on interrupt entry and exit ๐ซถ. Theregister-rangeis two registers joined by a dash. It always starts at"r0", and the upper limit is the"fp"register.blinkandlp_countare optional. This option only works for ARC EM and ARC HS cores ๐-mrgf-banked-regs=numberโ sets how many registers get copied into the second register bank when a fast interrupt fires ๐จ. Fast interrupts are the ones at the highest priority level,P0. They only savePCandSTATUS32so there are no memory transactions on entry or exit ๐ง. Use this when you're running fast interrupts on an ARC V2 family processor. Allowed values are4,8,16, and32๐-mlpc-width=widthโ sets the width of the"lp_count"register ๐. Valid widths are8,16,20,24,28, and32bits. The default is locked at 32 bits ๐. If the width is less than 32, the compiler won't turn your loops into the zero-delay loop mechanism unless it knows"lp_count"can actually hold the loop counter value ๐. Depending on the width, the compiler and run-time library might still use the loop mechanism for other stuff. This option also defines the macro"__ARC_LPC_WIDTH__"with the value ofwidthโจ-mrf16โ tells the compiler to generate code for a 16-entry register file ๐ท. This also defines the"__ARC_RF16__"preprocessor macro ๐ซง-mbranch-indexโ lets the compiler use"bi"or"bih"instructions to build jump tables ๐ฆ
๐ง Passed to the assembler too
These options get handed down to the assembler, and they also define preprocessor macro symbols. Double duty, iykyk ๐
-mdsp-packaโ passed to the assembler to turn on the DSP Pack A extensions โจ. Also sets the__Xdsp_packapreprocessor symbol. This option is deprecated ๐ฅ-mdvbfโ passed to the assembler to turn on the dual Viterbi butterfly extension ๐ฆ. Also sets the__Xdvbfpreprocessor symbol. This option is deprecated ๐ฅ-mlockโ passed to the assembler to turn on the locked load/store conditional extension ๐. Also sets the__Xlockpreprocessor symbol-mmac-d16โ passed to the assembler ๐งต. Also sets the__Xxmac_d16preprocessor symbol. This option is deprecated ๐ฅ-mmac-24โ passed to the assembler ๐งต. Also sets the__Xxmac_24preprocessor symbol. This option is deprecated ๐ฅ-mrtscโ passed to the assembler to turn on the 64-bit time-stamp counter extension instruction โฐ. Also sets the__Xrtscpreprocessor symbol. This option is deprecated ๐ฅ-mswapeโ passed to the assembler to turn on the swap byte ordering extension instruction ๐. Also sets the__Xswapepreprocessor symbol-mtelephonyโ passed to the assembler to turn on dual- and single-operand instructions for telephony ๐. Also sets the__Xtelephonypreprocessor symbol. This option is deprecated ๐ฅ-mxyโ passed to the assembler to turn on the XY memory extension ๐ง . Also sets the__Xxypreprocessor symbol
๐ Assembly annotations
These ones control how your assembly code gets annotated ๐
-misizeโ annotates assembler instructions with estimated addresses ๐-mannotate-alignโ explains what alignment considerations led to deciding whether an instruction is short or long ๐ง
๐ Passed to the linker
-marclinuxโ passed to the linker to use the"arclinux"emulation ๐ง. This is on by default in tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling isn't requested โจ-marclinux_profโ passed to the linker to use the"arclinux_prof"emulation ๐. This is on by default in tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is requested ๐
๐ Shaping the generated code
-mlong-callsโ generates calls as register indirect calls, so you get the full 32-bit address range ๐-mmedium-callsโ don't use anything less than a 25-bit addressing range for calls ๐. That's the offset an unconditional branch-and-link instruction gets. Conditional execution of function calls is suppressed so the 25-bit range can be used, instead of the 21-bit range you'd get with conditional branch-and-link. This is the default for tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets ๐-G numโ puts definitions of externally-visible data in a small data section, as long as that data is no bigger thannumbytes ๐งธ. The defaultnumis4for any ARC configuration, or8when you have double load/store operations ๐-mno-sdataโ nosdatareferences get generated ๐ . This is the default for tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets-mvolatile-cacheโ volatile references use ordinarily cached memory accesses ๐๏ธ. This is the default ๐-mno-volatile-cacheโ enables cache bypass for volatile references ๐โโ๏ธ
๐๏ธ Fine-tuning the codegen
-malign-callโ does nothing at all ๐ซ . It's only kept around for backward compatibility-mauto-modify-regโ enables pre/post modify with register displacement ๐ฆ-mbbit-peepholeโ enables bbit peephole2 ๐-mno-brccโ disables a target-specific pass inarc_reorgthat would generate compare-and-branch ("brcc") instructions ๐ซ. It doesn't affect those instructions when they're driven by the combiner pass ๐ซถ-mcase-vector-pcrelโ uses PC-relative switch case tables so case table shortening can happen ๐. This is the default for-Osโจ-mcompact-casesiโ enables the compact"casesi"pattern ๐งฉ. This is the default for-Os, and it's only available for ARCv1 cores. This option is deprecated ๐ฅ-mno-cond-execโ disables the ARCompact-specific pass that generates conditional execution instructions ๐ โโ๏ธ
Okay so the ARC conditional execution thing is a whole mood ๐
Delay slot scheduling, operand numbers, literal sizes, instruction lengths, and conditional execution support all bump into each other, so the target-independent pass that generates conditional execution is often lacking ๐ญ. That's why the ARC port keeps a special pass that goes hunting for more conditional execution opportunities after register allocation, branch shortening, and delay slot scheduling are done โจ. It generally, but not always, improves performance and code size, at the cost of extra compilation time, so there's an option to switch it off ๐. If call instructions are going over their allowable offset range because they got conditionalized, bestie, consider using -mmedium-calls instead ๐ซถ
-mearly-cbranchsiโ Enables pre-reload use of the"cbranchsi"pattern ๐ฅ-mexpand-adddiโ Expands"adddi3"and"subdi3"at RTL generation time into"add.f","adc"etc. ngl this one is deprecated ๐-mindexed-loadsโ Enables indexed loads. Lowkey problematic, because some optimizers then assume indexed stores exist, and they really don't ๐-mlraโ Enables Local Register Allocation ๐ฆ It's still experimental for ARC, so by default the compiler uses standard reload (i.e.-mno-lra) ๐-mlra-priority-noneโ Doesn't indicate any priority for target registers ๐ธ-mlra-priority-compactโ Indicates target register priority forr0..r3/r12..r15๐-mlra-priority-noncompactโ Reduces target register priority forr0..r3/r12..r15โจ-mmillicodeโ When optimizing for size (using-Os), prologues and epilogues that have to save or restore a large number of registers are often shortened by calling a special function in libgcc. That's a millicode call ๐ง These calls can cause performance issues, and/or linking issues when you link in a nonstandard way, so this option lets you turn millicode call generation on or off ๐-mcode-density-frameโ Enables the compiler to emitenterandleaveinstructions. These are only valid for CPUs with the code-density feature ๐-mmixed-codeโ Does nothing. It's only here for backward compatibility ๐ซ-mq-classโ Deprecated, bestie. Enables q instruction alternatives. This is the default for-Os๐-mRcqโ Enables Rcq constraint handling. Most short code generation depends on this, and it's the default ๐-mRcwโ Enables Rcw constraint handling. Most ccfsm condexec mostly depends on this, and it's the default ๐-msize-level=levelโ Fine-tunes size optimization with regards to instruction lengths and alignment. The recognized values forlevelare:0โ No size optimization. Deprecated, and treated like1๐ฅ1โ Short instructions are used opportunistically โญ2โ In addition, alignment of loops and of code after barriers is dropped ๐ธ3โ In addition, optional data alignment is dropped, and the optionOsis enabled ๐ฅ
This defaults to 3 when -Os is in effect. Otherwise, when this isn't set, the behavior is equivalent to level 1 ๐ซถ
-mtune=cpuโ Sets instruction scheduling parameters forcpu, overriding anything implied by-mcpu=๐
Supported values for cpu are:
ARC600โ Tunes for ARC600 CPU ๐งARC601โ Tunes for ARC601 CPU ๐ฆARC700โ Tunes for ARC700 CPU with standard multiplier block ๐ARC700-xmacโ Tunes for ARC700 CPU with XMAC block โจARC725Dโ Tunes for ARC725D CPU ๐ARC750Dโ Tunes for ARC750D CPU ๐
-mmultcost=numโ The cost to assume for a multiply instruction, with4being equal to a normal instruction ๐งฎ-munalign-prob-threshold=probabilityโ Does nothing. Preserved for backward compatibility ๐
The following options are maintained for backward compatibility, but they're now deprecated and will be removed in a future release. Not the vibe, so don't start new code with them ๐ โโ๏ธ
-margonautโ Obsolete FPX ๐-mbig-endian,-EBโ Compiles code for big-endian targets. Using these is now deprecated ๐ญ Big-endian code is supported by configuring GCC to build"arceb-elf32"and"arceb-linux-uclibc"targets, for which big endian is the default ๐-mlittle-endian,-ELโ Compiles code for little-endian targets. Using these is now deprecated ๐ญ Little-endian code is supported by configuring GCC to build"arc-elf32"and"arc-linux-uclibc"targets, for which 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-xmacforcpuare replaced byARC600,ARC601,ARC700andARC700-xmacrespectively ๐-multcost=numโ Replaced by-mmultcost๐
๐ฆ ARM Options ๐ฆ
These -m options are defined for the ARM port, so if you're targeting ARM, these are your people ๐ซถ
-mabi=nameโ Generates code for the specified ABI. Permissible values are:apcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt๐-mapcs-frameโ Generates a stack frame that complies with the ARM Procedure Call Standard for all functions, even if that isn't strictly necessary for the code to run correctly ๐งฑ Specifying-fomit-frame-pointerwith this option causes stack frames not to be generated for leaf functions. The default is-mno-apcs-frame. Deprecated ๐-mapcsโ A synonym for-mapcs-frame, and also deprecated ๐-mthumb-interworkโ Generates code that supports calling between the ARM and Thumb instruction sets. Without this option, on pre-v5 architectures, the two instruction sets can't be reliably used inside one program ๐ฌ The default is-mno-thumb-interwork, since slightly larger code is generated when-mthumb-interworkis specified. In AAPCS configurations this option is meaningless ๐คทโโ๏ธ-mno-sched-prologโ Prevents the reordering of instructions in the function prologue, or the merging of those instructions with the instructions in the function's body. This means all functions start with a recognizable set of instructions (or in fact one of a choice from a small set of different function prologues), and that info can be used to locate the start of functions inside an executable piece of code ๐ The default is-msched-prolog.-mfloat-abi=nameโ Specifies which floating-point ABI to use. Permissible values are:soft,softfpandhard๐ง
Specifying soft makes GCC generate output containing library calls for floating-point operations. softfp allows code generation using hardware floating-point instructions, but still uses the soft-float calling conventions. hard allows generation of floating-point instructions and uses FPU-specific calling conventions ๐
The default depends on the specific target configuration. Note that the hard-float and soft-float ABIs are not link-compatible. You must compile your entire program with the same ABI, and link with a compatible set of libraries.
โ ๏ธ Hard-float and soft-float ABIs are not link-compatible. Compile your whole program with the same ABI, and link with a compatible set of libraries, or it's a total mess ๐
-mgeneral-regs-onlyโ Generates code that uses only the general-purpose registers. This prevents the compiler from using floating-point and Advanced SIMD registers, but it won't impose any restrictions on the assembler ๐ฟ-mlittle-endianโ Generates code for a processor running in little-endian mode. This is the default for all standard configurations ๐-mbig-endianโ Generates code for a processor running in big-endian mode. The default is to compile code for a little-endian processor ๐-mbe8,-mbe32โ When linking a big-endian image, selects between BE8 and BE32 formats. The option has no effect for little-endian images and is ignored. The default depends on the selected target architecture. For ARMv6 and later architectures the default is BE8; for older architectures the default is BE32. BE32 format has been deprecated by ARM ๐-march=name[+extension...]โ Specifies the name of the target ARM architecture. GCC uses this name to determine what kind of instructions it can emit when generating assembly code. This option can be used in conjunction with, or instead of, the-mcpu=option โจ
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 ๐
Additionally, the following architectures, which lack support for the Thumb execution state, are recognized but support is deprecated: armv4 ๐ฅ
Many of the architectures support extensions. You can add these by appending +extension to the architecture name. Extension options are processed in order and capabilities accumulate. An extension will also enable any necessary base extensions it depends on. For example, the +crypto extension will always enable the +simd extension ๐งฉ The exception to the additive construction is for extensions prefixed with +no...: these extensions disable the specified option and any other extensions that may depend on the presence of that extension ๐ซ
For example, -march=armv7-a+simd+nofp+vfpv4 is equivalent to writing -march=armv7-a+vfpv4, since the +simd option is entirely disabled by the +nofp option that follows it ๐ง
Most extension names are generically named, but their effect depends on the architecture they're applied to. For example, the +simd option can be applied to both armv7-a and armv8-a architectures, but it will enable 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 not mentioned do not support any extensions ๐
okay bestie, the ARM list keeps going and it's giving main character energy ๐ these are the architectures and the extra bits you can bolt on with +. ๐ง
armv5te,armv6,armv6j,armv6k,armv6kz,armv6t2,armv6z,armv6zk๐ธ these all share the extras listed below, so you're basically getting the same fit in a bunch of colourways+fpโ the VFPv2 floating-point instructions, lowkey iconic. You can also write+vfpv2and it means the exact same thing ๐+nofpโ switches the floating-point instructions off ๐ โโ๏ธ
armv7โ the common subset shared by ARMv7-A, ARMv7-R and ARMv7-M, so it's the girl-group version of the family ๐+fpโ the VFPv3 floating-point instructions, with 16 double-precision registers ๐+vfpv3-d16works as an alias here. Heads up though: the base ARMv7-M doesn't support floating-point, but it does vibe with both ARMv7-A and ARMv7-R โจ+nofpโ turns the floating-point instructions off ๐
armv7-a๐ฆ the full glam version, with a whole buffet of extras+mpโ the multiprocessing extension ๐ซถ+secโ the security extension, very protective energy ๐+fpโ the VFPv3 floating-point instructions with 16 double-precision registers.+vfpv3-d16can be used as an alias ๐+simdโ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions.+neonand+neon-vfpv3are both aliases for this one ๐ฅ+vfpv3โ the VFPv3 floating-point instructions, but now with 32 double-precision registers ๐+vfpv3-d16-fp16โ VFPv3 floating-point with 16 double-precision registers, plus the half-precision floating-point conversion operations โจ+vfpv3-fp16โ VFPv3 floating-point with 32 double-precision registers, plus those same half-precision 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โ Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions, with the half-precision conversion operations included ๐ง+neon-vfpv4โ Advanced SIMD (Neon) v2 and VFPv4 floating-point instructions ๐+nosimdโ switches off the Advanced SIMD instructions. Floating-point is still on, though, so don't panic ๐ โโ๏ธ+nofpโ switches off the floating-point and Advanced SIMD instructions ๐
armv7veโ the extended ARMv7-A architecture, with support for virtualization. Very put-together ๐ธ+fpโ the VFPv4 floating-point instructions with 16 double-precision registers.+vfpv4-d16can be used as an alias ๐+simdโ Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions.+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โ VFPv3 with 16 double-precision registers, plus the half-precision conversion operations ๐+vfpv3-fp16โ VFPv3 with 32 double-precision registers, plus the half-precision 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โ Advanced SIMD (Neon) v1 plus VFPv3 floating-point instructions.+neon-vfpv3can be used as an alias ๐ง+neon-fp16โ Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions, with the half-precision conversion operations ๐+nosimdโ disables the Advanced SIMD instructions, but floating point stays on ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐
armv8-a๐ the ARMv8 era has entered the chat+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. Full clear-out ๐+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 a package 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,armv8.3-a๐ these two share the extras below+fp16โ the half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions ๐ฅ+fp16fmlโ the half-precision floating-point fmla extension. This also enables the half-precision floating-point extension, plus Advanced SIMD and floating-point instructions ๐+simdโ the ARMv8.1-A Advanced SIMD and floating-point instructions ๐ธ+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions ๐+dotprodโ enables the Dot Product extension. This also turns on 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๐ธ the glow-up continues+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-point fmla extension ๐ฅ+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions. This also 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-point fmla extension ๐ฅ+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions. This also 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๐ the latest and greatest on this list+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-point fmla extension ๐ฅ+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions. This also 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โ okay the 8-bit Integer Matrix Multiply instructions ๐งฎ are so giving. This also enables Advanced SIMD and floating-point instructions too โจ+bf16โ the Brain half-precision floating-point instructions ๐ง bestie, this one also turns on Advanced SIMD and floating-point instructions ๐
๐ armv7-r
+fp.spโ the single-precision VFPv3 floating-point instructions ๐ธ+vfpv3xdworks as an alias for this one, so no stress if you see that name somewhere.+fpโ the VFPv3 floating-point instructions with 16 double-precision registers ๐ฅ+vfpv3-d16can be used as an alias for this extension.+vfpv3xd-d16-fp16โ single-precision VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐ฆ+vfpv3-d16-fp16โ VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐+nofpโ disables the floating-point extension ๐ซ+idivโ the ARM-state integer division instructions โ+noidivโ disables the ARM-state integer division extension ๐
๐ธ armv7e-m
+fpโ the single-precision VFPv4 floating-point instructions โจ+fpv5โ the single-precision FPv5 floating-point instructions ๐+fp.dpโ the single- and double-precision FPv5 floating-point instructions ๐+nofpโ disables the floating-point extensions ๐ซ
๐ฆ armv8.1-m.main
+dspโ the DSP instructions ๐+mveโ the M-Profile Vector Extension (MVE) integer instructions ๐+mve.fpโ the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions. Main character energy ๐ฅ+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 you give in the options, in the range 0 to 7 ๐ง
๐ง 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 you give 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. Big sacrifice, no cap ๐
-march=native makes the compiler auto-detect the architecture of the build computer ๐ช. Lowkey it's only supported on GNU/Linux, and not every architecture gets recognized. If the auto-detect doesn't work out, the option just has no effect ๐ฅฒ
๐ -mtune=name
This option tells GCC which target ARM processor to tune the performance of the code for ๐
. For some ARM implementations you can get better performance by using this option โจ. Permissible names are: arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi, arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, ares, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-r52plus, cortex-m0, cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m55, cortex-x1, 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, xgene1.
Also, this option can tell GCC to tune the performance of the code for a big.LITTLE system ๐คธ. Permissible names are: cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a72.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55.
-mtune=generic-arch tells GCC to tune the performance for a blend of processors within architecture arch ๐. The goal is code that runs well on the current most popular processors, balancing the optimizations that help some CPUs in the range while avoiding the performance pitfalls of other CPUs. Just know the effects of this option may change in future GCC versions as CPU models come and go ๐ซ .
-mtune permits the same extension options as -mcpu, but the extension options do not affect the tuning of the generated code ๐.
-mtune=native makes the compiler auto-detect the CPU of the build computer ๐. Lowkey it's only supported on GNU/Linux, and not every architecture gets recognized. If the auto-detect doesn't work out, the option has no effect ๐.
๐
-mcpu=name[+extension...]
This specifies the name of the target ARM processor ๐. GCC uses this name to figure out the target ARM architecture (as if you'd used -march) and the ARM processor type to tune for (as if you'd used -mtune). If you use this option together with -march or -mtune, those options take precedence over the matching part of this option ๐ซถ.
A lot of the supported CPUs have optional architectural extensions ๐งฉ. When that's the case, the extensions are normally enabled by default. If implementations that lack the extension exist, you can use the extension syntax to disable the extensions that have been left out ๐
. For floating-point and Advanced SIMD (Neon) instructions, you also have to think about the -mfloat-abi and -mfpu options: floating-point and Advanced SIMD instructions will only be used if -mfloat-abi is not set to soft, and any setting of -mfpu other than auto will override the available floating-point and SIMD extension instructions ๐ฅ.
For example, cortex-a9 comes in three major configurations: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD ๐ธ. The default is to enable all the instructions, but the extensions +nosimd and +nofp can be used to disable just the SIMD, or both the SIMD and floating-point instructions, respectively ๐.
Permissible names for this option are the same as the ones for -mtune ๐.
The following extension options are common to the listed CPUs ๐ฆ:
+nodspโ disables the DSP instructions oncortex-m33,cortex-m35p๐+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-m33andcortex-m35p. Ongeneric-armv7-a,cortex-a5,cortex-a7,cortex-a8,cortex-a9,cortex-a12,cortex-a15,cortex-a17,cortex-a15.cortex-a7,cortex-a17.cortex-a7,cortex-a32,cortex-a35,cortex-a53andcortex-a55, it disables the floating-point and SIMD instructions ๐ซ+nofp.dpโ disables the double-precision component of the floating-point instructions oncortex-r5,cortex-r7,cortex-r8,cortex-r52,cortex-r52plusandcortex-m7๐+nosimdโ disables the SIMD (but not floating-point) instructions ongeneric-armv7-a,cortex-a5,cortex-a7andcortex-a9๐ซ+cryptoโ enables the cryptographic instructions oncortex-a32,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,exynos-m1,xgene1,cortex-a57.cortex-a53,cortex-a72.cortex-a53,cortex-a73.cortex-a35,cortex-a73.cortex-a53andcortex-a75.cortex-a55๐
Also, the generic-armv7-a pseudo target defaults to VFPv3 with 16 double-precision registers โจ. It supports these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16, 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 makes the compiler auto-detect the CPU of the build computer ๐. Lowkey it's only supported on GNU/Linux, and not every architecture gets recognized. If the auto-detect doesn't work out, the option has no effect ๐ฅฒ.
๐ -mfpu=name
This specifies what floating-point hardware (or hardware emulation) is available on the target ๐ฅ. 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 ๐ซถ.
okay so the setting auto is the default and it's lowkey special ๐
It tells the compiler to pick the floating-point and Advanced SIMD instructions based on -mcpu and -march ๐ฆ
bestie, if the floating-point hardware you picked includes the NEON extension (e.g. -mfpu=neon), GCC's auto-vectorization pass won't generate floating-point operations unless you also specify -funsafe-math-optimizations ๐ญ The reason is that NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic (denormal values get treated as zero), so using NEON instructions may lead to a loss of precision ๐ Not a vibe.
You can also set the fpu name at function level using the target("fpu=") function attributes or pragmas โจ
-mfp16-format=nameโ Pick the format for the__fp16half-precision float type ๐ธ Your options arenone,ieee, andalternative. The default isnone, which means__fp16isn't defined at all ๐-mstructure-size-boundary=nโ This rounds up the size of every structure and union to a multiple of the number of bits you give it ๐ Allowed values are8,32and64. The default changes depending on your toolchain, and for the COFF targeted toolchain it's8. A value of64only works if the underlying ABI supports it ๐ซถ
A bigger number can give you faster, more efficient code, but it can also make your program bigger ๐ Different values are potentially incompatible, too. Code compiled with one value can't necessarily work with code or libraries compiled with another if they swap info through structures or unions ๐ญ
This option is deprecated. ๐
-mabort-on-noreturnโ Generates a call to the functionabortat the end of anoreturnfunction. It runs if the function tries to return ๐ง
-mlong-calls,-mno-long-callsโ Okay, so-mlong-callsmakes the compiler do function calls by loading the function's address into a register first, then doing a subroutine call on that register ๐ You need this if the target function lives outside the 64-megabyte addressing range of the offset-based subroutine call instruction ๐
Even with this switch on, not every call becomes a long call ๐ The heuristic is that static functions, functions with the short_call attribute, functions inside the scope of a #pragma no_long_calls directive, and functions whose definitions were already compiled within the current compilation unit are not turned into long calls. The exceptions are weak function definitions, functions with the long_call attribute or the section attribute, and functions inside the scope of a #pragma long_calls directive. Those are always turned into long calls ๐
This feature is not enabled by default. -mno-long-calls restores the default behavior, and so does putting the function calls inside a #pragma long_calls_off directive ๐ฆ Also note these switches have zero effect on how calls via function pointers are generated ๐
-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 is responsible for initializing this register with an appropriate value before execution begins ๐ซถ-mpic-register=regโ Picks the register used for PIC addressing ๐ For the standard PIC base case, the default is any suitable register the compiler determines. For the single PIC base case, the default isR9if the target is EABI based or stack-checking is enabled, and otherwise it'sR10๐ธ-mpic-data-is-text-relativeโ Assumes the displacement between the text and data segments is fixed at static link time ๐ง This lets you use PC-relative addressing to access data known to be in the data segment. For non-VxWorks RTP targets it's enabled by default. If you disable it on those targets, it turns on-msingle-pic-baseby default instead ๐ฅ-mpoke-function-nameโ Writes the name of each function into the text section, right before the function prologue ๐งโโ๏ธ The generated code looks 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 do a stack backtrace, code can look at 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 by configuring GCC with the--with-mode=stateconfigure option ๐
You can also override ARM and Thumb mode for each function with the target("thumb") and target("arm") function attributes or pragmas ๐
-mflip-thumbโ Switches ARM/Thumb modes on alternating functions ๐ This is only here 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 doesn't 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 ๐ฟ (Again, a leaf function is one that doesn't 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, which switches to Thumb mode before running the rest of the function ๐ This lets these functions get 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 via function pointers (including virtual functions) run correctly, whether or not the target code was compiled for interworking ๐ธ There's a small overhead when executing a function pointer if you turn this on ๐ข This option is not valid in AAPCS configurations either, since interworking is enabled by default there ๐-mtp=nameโ Picks the access model for the thread local storage pointer ๐งต The valid models are:soft, which generates calls to__aeabi_read_tpcp15, which fetches the thread pointer fromcp15directly (supported in the arm6k architecture)auto, which uses the best available method for the selected processor
The default setting is auto โจ
-mtls-dialect=dialectโ Picks the dialect for accessing thread local storage ๐ง Two dialects are supported,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 require new assembler, linker and library support ๐ ๏ธ Initial and local exec TLS models are unaffected by this option and always use the original scheme ๐ซถ-mword-relocationsโ Only generates absolute relocations on word-sized values (i.e.R_ARM_ABS32) ๐งฑ This is enabled by default on targets (uClinux, SymbianOS) where the runtime loader imposes this restriction, and when-fpicor-fPICis specified. This option conflicts with-mslow-flash-dataโ ๏ธ-mfix-cortex-m3-ldrdโ Some Cortex-M3 cores can cause data corruption whenldrdinstructions with overlapping destination and base registers 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โ Enables (or disables) the mitigation for an erratum on Cortex-A57 that affects the AES cryptographic instructions ๐ It's enabled by default when-mcpu=cortex-a57is specified ๐-mfix-cortex-a72-aes-1655431,-mno-fix-cortex-a72-aes-1655431โ Same deal, but for the erratum on Cortex-A72 that affects the AES cryptographic instructions ๐ It's enabled by default when-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 is set in the generated object file to either true or false, depending on this option ๐ท๏ธ If unaligned access is enabled, the preprocessor symbol __ARM_FEATURE_UNALIGNED is also defined ๐
-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 the inline assembler is using unified asm syntax ๐งฉ The default is currently off, which implies divided syntax ๐ This option has no impact on Thumb2, but that may change in future releases of GCC ๐ Divided syntax should be considered deprecated ๐ญ-mrestrict-itโ Restricts generation of IT blocks so they conform to the rules of ARMv8-A ๐ IT blocks can only contain a single 16-bit instruction from a select set of instructions ๐ง This option is on by default for ARMv8-A Thumb mode ๐-mprint-tune-infoโ okay bestie, this one prints the CPU tuning info as a comment inside the assembler file โจ It's really only for the compiler's own regression testing, so you won't need it for regular code ๐ It's disabled by default.-mverbose-cost-dumpโ turns on verbose cost model dumping in the debug dump files ๐ It's a compiler-debugging tool, so it's very compiler-dev energy ๐ง-mpure-codeโ no constant data gets stashed in code sections ๐ซ And when you're compiling for ELF object format, every text section gets the ELF processor-specific section attributeSHF_ARM_PURECODE๐ This one is only available when generating non-pic code for M-profile targets, so it's not for everyone ๐-mcmseโ generates secure code following the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification" ๐ You can find that spec athttps://developer.arm.com/documentation/ecm0359818/latest/.-mfix-cmse-cve-2021-35465โ mitigates a potential security issue with the "VLLDM" instruction on some M-profile devices when you're using CMSE (CVE-2021-365465) ๐ก๏ธ This one is on by default when-mcpu=is used withcortex-m33,cortex-m35porcortex-m55. If you want to turn the mitigation off, use-mno-fix-cmse-cve-2021-35465.-mstack-protector-guard=guard,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard๐ง The supported locations areglobal(a global canary) ortls(a canary you can reach through the TLS register). The-mstack-protector-guard-offset=option goes with-fstack-protector-guard=tls, and it's not for user-land code ๐-mfdpic,-mno-fdpicโ selects the FDPIC ABI, which uses 64-bit function descriptors to represent pointers to functions ๐ When the compiler is configured forarm-*-uclinuxfdpiceabitargets, this option is on by default and implies-fPIEif none of the PIC/PIE-related options is provided. On other targets, it only enables the FDPIC-specific code generation features, so you should explicitly provide the PIC/PIE-related options as needed.
Note that static linking is not supported, because it would still involve the dynamic linker when the program self-relocates. If that behaviour is acceptable to you, use -static and -Wl,-dynamic-linker options.
The opposite-mno-fdpicoption is useful (and required) to build the Linux kernel using the same (arm-*-uclinuxfdpiceabi) toolchain as the one used to build the userland programs ๐
โจ AVR Options โจ
These options are defined for AVR implementations, so they're strictly for AVR chips ๐
-mmcu=mcuโ picks the Atmel AVR instruction set architecture (ISA) or MCU type ๐ The default for this option isavr2.
GCC supports the following AVR devices and ISAs:
avr2โ "Classic" devices with up to 8 KiB of program memory.- mcu =
attiny22,attiny26,at90s2313,at90s2323,at90s2333,at90s2343,at90s4414,at90s4433,at90s4434,at90c8534,at90s8515,at90s8535.
- mcu =
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.
- mcu =
avr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory.- mcu =
at76c711,at43usb355.
- mcu =
avr31โ "Classic" devices with 128 KiB of program memory.- mcu =
atmega103,at43usb320.
- mcu =
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.
- mcu =
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,ata6285,ata6286,ata6289,ata6612c,at90pwm1,at90pwm2,at90pwm2b,at90pwm3,at90pwm3b,at90pwm81.
- mcu =
avr5โ "Enhanced" devices with 16 KiB up to 64 KiB of program memory. This is a big one, bestie ๐ธ- 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,ata5795,ata5790,ata5790n,ata5791,ata6613c,ata6614q,ata5782,ata5831,ata8210,ata8510,ata5702m322,at90pwm161,at90pwm216,at90pwm316,at90can32,at90can64,at90scr100,at90usb646,at90usb647,at94k,m3000.
- mcu =
avr51โ "Enhanced" devices with 128 KiB of program memory.- mcu =
atmega128,atmega128a,atmega128rfa1,atmega128rfr2,atmega1280,atmega1281,atmega1284,atmega1284p,atmega1284rfr2,at90can128,at90usb1286,at90usb1287.
- mcu =
avr6โ "Enhanced" devices with a 3-byte PC, i.e. with more than 128 KiB of program memory ๐ฆ- mcu =
atmega256rfr2,atmega2560,atmega2561,atmega2564rfr2.
- mcu =
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.
- mcu =
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,attiny417,attiny804,attiny806,attiny807,attiny814,attiny816,attiny817,attiny1604,attiny1606,attiny1607,attiny1614,attiny1616,attiny1617,attiny3214,attiny3216,attiny3217,atmega808,atmega809,atmega1608,atmega1609,atmega3208,atmega3209,atmega4808,atmega4809.
- mcu =
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.
- mcu =
avrxmega5โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory, plus more than 64 KiB of RAM ๐- mcu =
atxmega64a1,atxmega64a1u.
- mcu =
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.
- mcu =
avrxmega7โ "XMEGA" devices with more than 128 KiB of program memory and more than 64 KiB of RAM.- mcu =
atxmega128a1,atxmega128a1u,atxmega128a4u.
- mcu =
avrtinyโ "TINY" Tiny core devices with 512 B up to 4 KiB of program memory ๐- mcu =
attiny4,attiny5,attiny9,attiny10,attiny20,attiny40.
- mcu =
avr1โ this ISA is implemented by the minimal AVR core and is supported for assembler only ๐- mcu =
attiny11,attiny12,attiny15,attiny28,at90s1200.
- mcu =
-mabsdataโ assumes that all data in static storage can be accessed byLDS/STSinstructions โจ This option only has an effect on reduced Tiny devices like ATtiny40. See also the "absdata" AVR Variable Attributes,variable attribute.-maccumulate-argsโ accumulates outgoing function arguments, and acquires/releases the needed stack space for them once, in the function prologue/epilogue ๐ Without this option, outgoing arguments are pushed before calling a function and popped afterwards.
Popping the arguments after the function call can be expensive on AVR, so accumulating the stack space might lead to smaller executables, because arguments don't need to be removed from the stack after each such function call ๐ซถ
This option can lead to reduced code size for functions that make several calls to functions that get their arguments on the stack, like calls to 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โ functions prologues/epilogues are expanded as calls to appropriate subroutines, so your code size gets smaller ๐ง-mdouble=bitsโ โจ bestie, this one sets the size (in bits) of the "double" type ๐. The only possible values forbitsare32and64๐ธ. Whether a specific value is allowed depends on the--with-double=and--with-long-double=configure options ๐ง (seehttps://gcc.gnu.org/install/configure.html#avr), and the same goes for the default values of those options ๐.-mlong-double=bitsโ same energy, but for the "long double" type ๐. The possible values are32and64again, and it's the same deal with the configure options and their defaults ๐ .-mgas-isr-prologuesโ ๐ฆ ISRs (interrupt service routines) 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"no_gccisr"function attribute from AVR Function Attributes ๐. It's switched on by default when optimization is on (but not with-Og, see@pxref{Optimize Options}), and only if GNU Binutils supports PR21683 (https://sourceware.org/PR21683) ๐ฅ.-mint8โ ๐ this one tells the compiler to assumeintis an 8-bit integer. That changes the sizes of every type: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes. Smaller code size, yay! ๐ง
โ ๏ธ Heads up, bestie: -mint8 does not conform to the C standards. It shrinks the code, but the types won't behave like the standard says they should ๐.
-mmain-is-OS_taskโ ๐ don't save registers inmain. It does the same thing as slapping the AVR Function Attributes"OS_task"attribute ontomain๐ . It's switched on by default when optimization is on โจ.-mn-flash=numโ ๐ tells the compiler to assume the flash memory isnumtimes 64 KiB big ๐ง.-mno-interruptsโ ๐ โโ๏ธ the generated code is not compatible with hardware interrupts. The upside is that the code size gets smaller ๐ธ.-mrelaxโ ๐ฆ okay so this tries to swapCALLorJMPinstructions for the shorterRCALLorRJMPinstructions, when that's possible ๐. Setting-mrelaxjust adds the--mlink-relaxoption to the assembler's command line and the--relaxoption to the linker's command line ๐ซถ.
Jump relaxing is done by the linker, because jump offsets aren't known until the code is located ๐ง . So the assembler code the compiler generates is the same, but the instructions in the executable may end up different from the ones in the assembler code ๐คฏ.
Relaxing must be turned on if linker stubs are needed. Check out the section on "EIND" and linker stubs below ๐.
-mrmwโ ๐ assume the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLATโจ.-mshort-callsโ ๐ธ assume thatRJMPandRCALLcan target the whole program memory ๐ง.
This option is used internally for multilib selection. It's not an optimization option, so you don't need to set it by hand ๐.
-msp8โ ๐ treat the stack pointer register as an 8-bit register, i.e. assume the high byte of the stack pointer is zero. Generally, you don't need to set this one by hand ๐ .
This option is used internally by the compiler to select and build multilibs for the architectures avr2 and avr25. These architectures mix devices with and without SPH ๐งฉ. For any setting other than -mmcu=avr2 or -mmcu=avr25, the compiler driver adds or removes this option from the compiler proper's command line, because the compiler then knows whether the device or architecture has an 8-bit stack pointer (and therefore no SPH register) or not ๐ฅ.
-mstrict-Xโ ๐ use the address registerXthe way the hardware intends ๐. That meansXis only used in 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, where const is small and non-negative (const < 64), into a register Rn looks like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-mtiny-stackโ ๐ฆ only change the lower 8 bits of the stack pointer โจ.-mfract-convert-truncateโ ๐ allow truncation instead of rounding towards zero for fractional fixed-point types ๐ .-nodevicelibโ ๐ โโ๏ธ don't link against AVR-LibC's device specific librarylib<mcu>.a๐.-nodevicespecsโ ๐ง don't add-specs=device-specs/specs-mcuto the compiler driver's command line ๐ซถ. This means you take responsibility for giving the subprocesses (compiler proper, assembler and linker) the right command line options ๐. You have to supply your own device specs file with-specs=path-to-specs-file, and there's no more need for-mmcu=mcu๐.
This option can also replace the older way of doing custom device-specs files. That one needed -B some-path to point at a directory containing a folder named device-specs, which contained a specs file named specs-mcu, where mcu was set by -mmcu=mcu ๐ธ.
-Waddr-space-convertโ โ ๏ธ warn about conversions between address spaces when the resulting address space isn't contained in the incoming address space ๐.-Wmisspelled-isrโ ๐ฅ warn if the ISR is misspelled, i.e. written without the__vectorprefix. This one 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 program memory, there's a special function register called "EIND" ๐. It serves as the most significant part of the target address when EICALL or EIJMP instructions are used ๐.
Indirect jumps and calls on these devices are handled like this by the compiler, and they come with some limitations ๐ซถ:
- The compiler never sets
EIND๐ โโ๏ธ. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or it might readEINDdirectly to emulate an indirect call/jump using aRETinstruction ๐ง. - The compiler assumes
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 jumps to such a stub, and the stub contains a direct jump to the desired address ๐ฆ.
- Linker relaxation must be turned on so the linker generates the stubs correctly in all situations. See the compiler option
-mrelaxand the linker option--relax๐. There are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message ๐. - The default linker script is arranged for code with
EIND = 0. If your code is supposed to work withEIND != 0, you need a custom linker script to place the sections whose names start with.trampolinesinto the segment whereEINDpoints to ๐ฅ. - The startup code from libgcc never sets
EIND. Heads up that startup code is a blend of code from libgcc and AVR-LibC. For the impact of AVR-LibC onEIND, see the AVR-LibC user manual athttp://nongnu.org/avr-libc/user-manual/๐. - It's totally legit for user-specific startup code to set up
EINDearly, for example with initialization code in the section.init3๐. That code runs before the general startup code that initializes RAM and calls constructors, but after the bit of AVR-LibC startup code that setsEINDto the segment where the vector table 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:
- The address of a label is taken by means of the
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The final location of that label is in a code segment outside the segment where the stubs are located ๐.
- The compiler emits 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 this 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 has to 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 โจ
Some AVR devices support memories larger than the 64 KiB range that can be accessed with 16-bit pointers ๐. To access memory locations outside this 64 KiB range, the content of a RAMP register is used as the high part of the address ๐ง . The X, Y and Z address registers are concatenated with the RAMPX, RAMPY and RAMPZ special function registers, respectively, to get a wide address ๐ฆ. Similarly, RAMPD is used together with direct addressing ๐.
- The startup code initializes the
RAMPspecial function registers with zero ๐ซถ. - If a named address space (see AVR Named Address Spaces) other than generic or
__flashis used, thenRAMPZis set as needed before the operation ๐ฅ. - If the device supports RAM bigger than 64 KiB and the compiler has to change
RAMPZto pull off an operation,RAMPZgets reset to zero afterward. ๐งน - If the device has a specific
RAMPregister, the ISR prologue/epilogue saves and restores that SFR and sets it to zero, just in case the ISR code might (implicitly) use it. ๐ก๏ธ - > โ ๏ธ RAM larger than 64 KiB is not supported by GCC for AVR targets. If you use inline assembler to read from locations outside the 16-bit address range and change one of the
RAMPregisters, you must reset it to zero after the access. Do not skip this, bestie. ๐
โจ AVR Built-in Macros โจ
GCC defines a bunch of built-in macros so your code can check whether certain features are there or not. Almost any 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, see 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=mcu option. ๐ฆ The possible values are:
mcu="avr2"โ2mcu="avr25"โ25mcu="avr3"โ3mcu="avr31"โ31mcu="avr35"โ35mcu="avr4"โ4mcu="avr5"โ5mcu="avr51"โ51mcu="avr6"โ6mcu="avrtiny"โ100mcu="avrxmega2"โ102mcu="avrxmega3"โ103mcu="avrxmega4"โ104mcu="avrxmega5"โ105mcu="avrxmega6"โ106mcu="avrxmega7"โ107
If mcu specifies a device, this built-in macro is set accordingly. For example, with -mmcu=atmega8 the macro is defined to 4. ๐ธ
__AVR_Device__
Setting -mmcu=device defines this built-in macro, which reflects the device's name. For example, -mmcu=atmega8 defines __AVR_ATmega8__, and -mmcu=attiny261a defines __AVR_ATtiny261A__, etc. ๐ง
The built-in macro names follow the scheme __AVR_Device__, where Device is the device name as it appears in the AVR user manual. The difference between Device in the built-in macro and device in -mmcu=device is that the latter is always lowercase. ๐ค
If device is not a device but only a core architecture like avr51, this macro is not defined. ๐
__AVR_DEVICE_NAME__
Setting -mmcu=device defines this built-in macro to the device's name. For example, with -mmcu=atmega8 the macro is defined to "atmega8". โจ
If device is not a device but only a core architecture like avr51, this macro is not defined. ๐
__AVR_XMEGA__
The device or architecture belongs to the XMEGA family of devices. ๐
__AVR_HAVE_ELPM__
The device has the ELPM instruction. ๐ฅ
__AVR_HAVE_ELPMX__
The device has the ELPM Rn,Z and ELPM Rn,Z+ instructions. ๐
__AVR_HAVE_MOVW__
The device has the MOVW instruction, which performs 16-bit register-to-register moves. ๐ฆ
__AVR_HAVE_LPMX__
The device has the LPM Rn,Z and LPM Rn,Z+ instructions. ๐
__AVR_HAVE_MUL__
The device has a hardware multiplier. โญ
__AVR_HAVE_JMP_CALL__
The device has the JMP and CALL instructions. 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 the EIJMP and EICALL instructions. This is the case for devices with more than 128 KiB of program memory. It also means the program counter (PC) is 3 bytes wide. ๐ง
__AVR_2_BYTE_PC__
The program counter (PC) is 2 bytes wide. This is the case for devices with up to 128 KiB of program memory. ๐ซถ
__AVR_HAVE_8BIT_SP__ and __AVR_HAVE_16BIT_SP__
The compiler treats the stack pointer (SP) register as an 8-bit or 16-bit register, respectively. The definition of these macros is affected by -mtiny-stack. ๐
__AVR_HAVE_SPH__ and __AVR_SP8__
The device has the SPH (high part of stack pointer) special function register, or has an 8-bit stack pointer, respectively. The definition of these macros is affected by -mmcu=, and in the cases of -mmcu=avr2 and -mmcu=avr25, also by -msp8. ๐ญ
__AVR_HAVE_RAMPD__, __AVR_HAVE_RAMPX__, __AVR_HAVE_RAMPY__, and __AVR_HAVE_RAMPZ__
The device has the RAMPD, RAMPX, RAMPY, or RAMPZ special function register, respectively. ๐
__NO_INTERRUPTS__
This macro reflects the -mno-interrupts command-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 are SBRS, SBRC, SBIS, SBIC, and CPSE. The second macro is only defined if __AVR_HAVE_JMP_CALL__ is also set. ๐
โโ๏ธ
__AVR_ISA_RMW__
The device has Read-Modify-Write instructions (XCH, LAC, LAS, and LAT). ๐
__AVR_SFR_OFFSET__=offset
Instructions that can address I/O special function registers directly, like IN, OUT, SBI, etc., may use a different address than an instruction that accesses RAM, like LD or STS. This offset depends on the device architecture, and it has to be subtracted from the RAM address to get the respective I/O address. ๐งฎ
__AVR_SHORT_CALLS__
The -mshort-calls command-line option is set. ๐
__AVR_PM_BASE_ADDRESS__=addr
Some devices support reading from flash memory by means of LD* instructions. The flash memory is seen in the data address space at an offset of __AVR_PM_BASE_ADDRESS__. If this macro is not defined, this feature is not available. If it is defined, the address space is linear and there is no need to put .rodata into RAM. This is handled by the default linker description file, and it is currently available for avrtiny and avrxmega3. Even more convenient, there is no need to use address spaces like __flash or features like the progmem attribute and pgm_read_*. ๐ฅฐ
__WITH_AVRLIBC__
The compiler is configured to be used together with AVR-Libc. See the --with-avrlibc configure 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 the -mdouble= option. ๐
__DEFAULT_DOUBLE__
The size in bits of double if -mdouble= is not set. To test the layout of double in a program, use the built-in macro __SIZEOF_DOUBLE__. ๐
__HAVE_LONG_DOUBLE32__, __HAVE_LONG_DOUBLE64__, __HAVE_LONG_DOUBLE_MULTILIB__, and __DEFAULT_LONG_DOUBLE__
Same as above, but for long double instead of double. ๐ซ
__WITH_DOUBLE_COMPARISON__
This reflects the --with-double-comparison={tristate|bool|libf7} configure option (https://gcc.gnu.org/install/configure.html#avr), and it is defined to 2 or 3. ๐ท
__WITH_LIBF7_LIBGCC__, __WITH_LIBF7_MATH__, and __WITH_LIBF7_MATH_SYMBOLS__
These reflect the --with-libf7={libgcc|math|math-symbols} configure option (https://gcc.gnu.org/install/configure.html#avr). ๐ถ
๐ฆ Blackfin Options ๐ฆ
-mcpu=cpu[-sirevision]โ This picks the target Blackfin processor. Right now, 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, orbf592. ๐ฅ
The optional sirevision picks the silicon revision of the target Blackfin processor, and any workarounds for that revision get enabled. If sirevision is none, no workarounds are enabled. If it is any, all workarounds for the targeted processor are enabled. The __SILICON_REVISION__ macro is defined to two hexadecimal digits representing the major and minor numbers of the silicon revision. If sirevision is none, __SILICON_REVISION__ is not defined. If sirevision is any, __SILICON_REVISION__ is defined to be 0xffff. If this optional sirevision is not used, GCC assumes the latest known silicon revision of the targeted Blackfin processor. ๐
GCC defines a preprocessor macro for the specified cpu. For the bfin-elf toolchain, this option causes the hardware BSP provided by libgloss to be linked in if -msim is not given. ๐ง
Without this option, bf532 is used as the processor by default. ๐ธ
๐ Note that support forbf561is incomplete. Forbf561, only the preprocessor macro is defined.
-msimโ Specifies that the program will be run on the simulator. This causes the simulator BSP provided by libgloss to be linked in. This option only has an effect for thebfin-elftoolchain. Certain other options, such as-mid-shared-libraryand-mfdpic, imply-msim. ๐ฅ๏ธ-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions. This skips the instructions that save, set up, and restore frame pointers, and it frees up an extra register in leaf functions. ๐-mspecld-anomalyโ When enabled, the compiler makes sure the generated code does not contain speculative loads after jump instructions. If this option is used,__WORKAROUND_SPECULATIVE_LOADSis defined. ๐ ๏ธ-mno-specld-anomalyโ Don't generate extra code to prevent speculative loads from happening. ๐ โโ๏ธ-mcsync-anomalyโ When enabled, the compiler makes sure the generated code does not containCSYNCorSSYNCinstructions too soon after conditional branches. If this option is used,__WORKAROUND_SPECULATIVE_SYNCSis defined. ๐ซง-mno-csync-anomalyโ Don't generate extra code to preventCSYNCorSSYNCinstructions from happening too soon after a conditional branch. ๐ซ-mlow64kโ When enabled, the compiler is free to take advantage of the knowledge that the entire program fits into the low 64k of memory. ๐ง-mno-low64kโ Assume that the program is arbitrarily large. This is the default. ๐ฆ-mstack-check-l1โ Does stack checking using information placed into L1 scratchpad memory by the uClinux kernel. ๐-mid-shared-libraryโ Generates code that supports shared libraries via the library ID method. This allows for execute-in-place and shared libraries in an environment without virtual memory management. This option implies-fPIC. With abfin-elftarget, this option implies-msim. ๐-mno-id-shared-libraryโ Generates code that doesn't assume ID-based shared libraries are being used. This is the default. ๐-mleaf-id-shared-libraryโ okay so this one has GCC generate code that works with ID-based shared libraries (the library ID method), but it assumes your library or executable won't link against any other ID shared libraries. The payoff is that the compiler can use faster code for jumps and calls. ๐๏ธโจ-mno-leaf-id-shared-libraryโ the opposite energy ๐ 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โ sets the identification number of the ID-based shared library you're compiling.0gives 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โ lets the data segment live in a different area of memory from the text segment. This allows execute in place in an environment without virtual memory management, by getting rid of relocations against the text section. ๐ง-mno-sep-dataโ assumes the data segment follows the text segment. This is the default, so you're already set ๐-mlong-calls,-mno-long-callsโ this tells the compiler to do function calls by loading the function's address into a register first, 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 version of the subroutine call instruction. It's not on by default, and-mno-long-callsputs you back to default. Also, these switches have no effect on how function calls through function pointers get generated, so don't expect them to do anything there ๐ซ-mfast-fpโ links with the fast floating-point library. It relaxes some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN), all for the sake of performance. โก-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally. It has no effect without-mfdpic. ๐ธ-mmulticoreโ builds a standalone application for multicore Blackfin processors. It uses proper start files and link scripts that support multicore, and it defines the macro"__BFIN_MULTICORE". This one can only be used with-mcpu=bf561[-sirevision]. It can pair with-mcoreaor-mcorebfor the one-application-per-core programming model. Without either of those, you get the single-application/dual-core model, where the main function of Core B should be named"coreb_main". If you skip this option entirely, the single-core application programming model is used. ๐-mcoreaโ builds a standalone application for Core A of BF561 in the one-application-per-core model. Proper start files and link scripts support Core A, and the macro"__BFIN_COREA"gets defined. This only works together with-mmulticore. ๐ฆ-mcorebโ builds a standalone application for Core B of BF561 in the one-application-per-core model. Proper start files and link scripts support Core B, and the macro"__BFIN_COREB"gets defined. When you use this,"coreb_main"replaces"main". This only works together with-mmulticore. ๐-msdramโ builds a standalone application for SDRAM. Proper start files and link scripts put the app into SDRAM, and the macro"__BFIN_SDRAM"gets defined. Heads up: the loader should initialize SDRAM before loading the application ๐ง-micplbโ assumes 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โ specifies the name of the target architecture. GCC uses this name to figure out what kinds of instructions it's allowed to emit when generating assembly code. Permissible names arec62x, c64x, c64x+, c67x, c67x+, c674x. ๐-mbig-endianโ generates code for a big-endian target.-mlittle-endianโ generates code for a little-endian target. This is the default ๐ซถ-msimโ picks startup files and a linker script that suit the simulator. ๐งช-msdata=defaultโ puts small global and static data in the.neardatasection, which is pointed to by registerB14. Small uninitialized global and static data goes in the.bsssection, which sits right next to.neardata. Small read-only data goes in the.rodatasection. For big chunks of data, the matching sections are.fardata,.farand.const. ๐ฆ-msdata=allโ puts all data, not just the small stuff, into the sections reserved for small data, and uses addressing relative to theB14register to get at it. ๐-msdata=noneโ makes no use of the sections reserved for small data, and uses absolute addresses to access all data. All initialized global and static data goes in the.fardatasection, and all uninitialized data goes in the.farsection. All constant data goes in the.constsection. ๐ฐ
โจ CRIS Options โจ
These options are defined specifically for the CRIS ports ๐
-march=architecture-type,-mcpu=architecture-typeโ generates code for the architecture you pick. The choices arev3,v8andv10, which are for ETRAX 4, ETRAX 100, and ETRAX 100 LX respectively. The default isv0, except forcris-axis-linux-gnu, where the default isv10. ๐งฉ-mtune=architecture-typeโ tunes everything that applies to the generated code for the architecture you pick, except the ABI and the set of available instructions. The choices are the same as for-march=architecture-type. ๐๏ธ-mmax-stack-frame=nโ warns when a function's stack frame goes overnbytes. โ ๏ธ-metrax4,-metrax100โ these are synonyms for-march=v3and-march=v8, respectively. ๐-mmul-bug-workaround,-mno-mul-bug-workaroundโ works around a bug in themulsandmuluinstructions, for CPU models where it applies. This one's disabled by default. ๐-mpdebugโ turns on CRIS-specific verbose debug-related info in the assembly code. It also turns off the#NO_APPformatted-code indicator that gets sent to the assembler at the start of the assembly file. ๐-mcc-initโ doesn't use condition-code results from previous instructions. It always emits compare and test instructions before condition codes get used. ๐งผ-mno-side-effectsโ doesn'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 (the no- ones) arrange, or un-arrange, for the stack frame, individual data and constants to be aligned for the maximum single data access size of the chosen CPU model. The default is 32-bit alignment. ABI details like structure layout are not affected by these options. ๐-m32-bit,-m16-bit,-m8-bitโ similar to the stack, data and const align options above, these arrange for the stack frame, writable data and constants to all be 32-bit, 16-bit or 8-bit aligned. The default is 32-bit alignment. ๐ฏ-mno-prologue-epilogue,-mprologue-epilogueโ with-mno-prologue-epilogue, the normal function prologue and epilogue that set up the stack frame are left out, and no return instructions or return sequences get generated.
Use -mno-prologue-epilogue only together with visual inspection of the compiled code, bestie ๐ญ No warnings or errors get generated when call-saved registers need to be saved, or when storage for local variables needs to be allocated.
-mno-gotplt,-mgotpltโ with-fpicand-fPIC,-mno-gotpltmeans don't generate instruction sequences that load addresses for functions from the PLT part of the GOT, and-mgotpltmeans do generate them. Other architectures normally just call the PLT, so this is a CRIS thing. The default is-mgotplt. ๐ท-melfโ a legacy no-op option, only recognized with thecris-axis-elfandcris-axis-linux-gnutargets. ๐ฆ-mlinuxโ a legacy no-op option, only recognized with thecris-axis-linux-gnutarget. ๐ฆ-simโ recognized forcris-axis-elf. It links with input-output functions from a simulator library. Code, initialized data and zero-initialized data get allocated consecutively. ๐ฅ๏ธ-sim2โ like-sim, but it passes linker options to put initialized data at0x40000000and zero-initialized data at0x80000000. ๐
โจ CR16 Options โจ
These options are defined specifically for the CR16 ports ๐
-mmacโ enables the use of multiply-accumulate instructions. It's disabled by default. โ๏ธโ-mcr16cplus,-mcr16cโ generates code for the CR16C or CR16C+ architecture. CR16C+ is the default. ๐ฑ-msimโ links the librarylibsim.a, which is compatible with the simulator. This only applies to the ELF compiler. ๐งช-mint32โ chooses 32-bit wide integer type. ๐ข-mbit-opsโ generates"sbit"/"cbit"instructions for bit manipulations. ๐ฏ-mdata-model=modelโ chooses a data model. The choices arenear,farormedium.mediumis the default. Heads up though,farisn't valid with-mcr16c, because the CR16C architecture doesn't support the far data model ๐
โจ C-SKY Options โจ
GCC supports these options when compiling for C-SKY V2 processors ๐
-march=archโ specifies the C-SKY target architecture. Valid values forarchareck801, ck802, ck803, ck807, and ck810. The default isck810. โญ-mcpu=cpuโ specifies the C-SKY target processor. 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, and ck810ftv. That is a lot of chips, the way they're all lined up ๐ญ๐ฅ-mbig-endian,-EB,-mlittle-endian,-ELโ okay bestie, these pick your byte order ๐ง-mbig-endian(or-EB) gives you big-endian code, and-mlittle-endian(or-EL) gives you little-endian. Little-endian is the default, so you're already slaying if you don't touch these โจ-mfloat-abi=nameโ this one lets you pick your floating-point ABI ๐ฆ The valid vibes aresoft,softfp, andhard.softmakes GCC generate output full of library calls for floating-point operations.softfplets the code use hardware floating-point instructions, but it still sticks with the soft-float calling conventions.hardlets the code use floating-point instructions and the FPU-specific calling conventions.
The default depends on your specific target configuration. Also, 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, or it's a whole mess.
-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, these turn on (or off) generation of double-precision float instructions ๐ This is the default except when compiling for CK803.-mfdivdu,-mno-fdivduโ when-mhard-floatis in effect, these enable the"frecipd","fsqrtd", and"fdivd"instructions ๐ฅ This is the default except when compiling for CK803.-mfpu=fpuโ choose your floating-point processor ๐ This one can only be used with-mhard-float. The values forfpuare:fpv2_sf, which is the same as-mno-double-float -mno-fdivdufpv2, which is the same as-mdouble-float -mno-divdufpv2_divd, which is the same as-mdouble-float -mdivdu
-melrw,-mno-elrwโ enable (or disable) the extended"lrw"instruction โจ This defaults to on for CK801 and off for everything else.-mistack,-mno-istackโ enable interrupt stack instructions. The default is off ๐
The-mistackoption is required if you want to handle the"interrupt"and"isr"function attributes. No-mistack, no handling, bestie.
-mmpโ enable multiprocessor instructions ๐ง The default is off.-mcpโ enable coprocessor instructions ๐ The default is off.-mcacheโ enable coprocessor instructions ๐ The default is off.-msecurityโ enable C-SKY security instructions ๐ The default is off.-mtrustโ enable 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โ generate divide instructions ๐ The default is off.-msmart,-mno-smartโ generate code for Smart Mode, which only uses registers numbered 0-7 so you can use 16-bit instructions ๐ฆ This one is ignored for CK801, where this is already the required behavior, and it defaults to on for CK802. For other targets the default is off.-mhigh-registers,-mno-high-registersโ generate code using the high registers numbered 16-31 ๐ This option isn't supported on CK801, CK802, or CK803, but it's enabled by default for other processors.-manchor,-mno-anchorโ generate code using global anchor symbol addresses โญ-mpushpop,-mno-pushpopโ generate code using"push"and"pop"instructions ๐ธ This defaults to on.-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ generate code using"stm"and"ldm"instructions ๐ This one isn't supported on CK801, but it's enabled by default on other processors.-mconstpool,-mno-constpoolโ create constant pools in the compiler instead of handing that job off to the assembler ๐ง This is the default and it's required for correct code generation on CK801 and CK802. On other processors it's optional.-mstack-size,-mno-stack-sizeโ emit".stack_size"directives for each function in the assembly output ๐ This defaults to off.-mccrt,-mno-ccrtโ generate code for the C-SKY compiler runtime instead of libgcc ๐ This defaults to off.-mbranch-cost=nโ set the branch costs to roughly"n"instructions โจ The default is 1.-msched-prolog,-mno-sched-prologโ permit scheduling of function prologue and epilogue sequences ๐ Heads up, this can give you code that isn't compliant with the C-SKY V2 ABI prologue requirements, and that code can't be debugged or backtraced ๐ It's disabled by default.-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 doesn't make "fat" object files. Instead, it makes an object file for the single architecture that GCC was built to target. Apple's GCC on Darwin does make "fat" files when you use multiple -arch options. It does this by running the compiler or linker multiple times and then joining the results together with lipo ๐
The subtype of the file (like ppc7400, ppc970, or i686) is decided by the flags that specify the ISA GCC is targeting, like -mcpu or -march. If you want to override that, the -force_cpusubtype_ALL option can do it ๐ฅ
The Darwin tools act differently when they run into 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 literally cannot 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 example, trying to put a ppc970 object file in a ppc7400 library is a no-go. The linker for executables, ld, quietly gives the executable the most restrictive subtype of any of its input files ๐คซ
-Fdirโ add the framework directorydirto the head of the list of directories searched for header files ๐ These directories get interleaved with the ones from-Ioptions, and they're scanned in a left-to-right order.
A framework directory is a directory with frameworks in it. A framework is a directory that ends in .framework and has a Headers and/or PrivateHeaders directory sitting directly inside it. The name of a framework is the name of that directory excluding 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 live in the same framework. A subframework should not have the same name as a framework, and a warning gets issued if you break that rule โ ๏ธ Right now a subframework can't have subframeworks of its own, but the mechanism might 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 gets treated as a system directory ๐ธ The main difference is that with-iframework, the compiler doesn't warn about constructs inside header files found viadir. This option is only valid for the C family of languages ๐-gusedโ emit debugging information for symbols that are used ๐ For the stabs debugging format, this enables-feliminate-unused-debug-symbols. This is ON by default.-gfullโ emit debugging information for all symbols and types ๐ง-mmacosx-version-min=versionโ sets the earliest version of MacOS X that this executable will run on, which isversion๐ Typical values ofversioninclude10.1,10.2, and10.3.9.
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โ enable kernel development mode ๐ง The-mkerneloption sets-static,-fno-common,-fno-use-cxa-atexit,-fno-exceptions,-fno-non-call-exceptions,-fapple-kext,-fno-weak, and-fno-rtti, where applicable. This mode also sets-mno-altivec,-msoft-float,-fno-builtin, and-mlong-branchfor PowerPC targets ๐-mone-byte-boolโ overrides the defaults for"bool"so thatsizeof(bool)==1๐ By default,sizeof(bool)is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86, so this option has no effect 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 it may mean you have to recompile all the other modules in your program, including the system libraries. Only use this switch to conform to a non-default data model.
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ generate code that's good for fast turnaround development ๐ฅ This lets things like GDB dynamically load.ofiles into programs that are already running ๐ฆ-findirect-dataand-ffix-and-continueare only provided for backwards compatibility.-all_loadโ loads all members of static archive libraries ๐ฆ Seeman ld(1)for more information.-arch_errors_fatalโ makes errors about files with the wrong architecture fatal ๐-bind_at_loadโ marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched ๐ง-bundleโ produces a Mach-o bundle format file ๐ Seeman ld(1)for more information.-bundle_loader executableโ specifies the executable that will load the build output file being linked ๐ซถ Seeman ld(1)for more information.-dynamiclibโ when you pass this, GCC produces a dynamic library instead of an executable when linking, using the Darwinlibtoolcommand ๐-force_cpusubtype_ALLโ gives GCC's output file theALLsubtype, instead of the one controlled by-mcpuor-marchโญ-allowable_client client_nameโ Darwin linker flag that takes a client_name ๐-client_nameโ Darwin linker flag ๐ฆ-compatibility_versionโ Darwin linker flag ๐ธ-current_versionโ Darwin linker flag โจ-dead_stripโ Darwin linker flag ๐-dependency-fileโ Darwin linker flag ๐ง-dylib_fileโ Darwin linker flag ๐-dylinker_install_nameโ Darwin linker flag ๐-dynamicโ Darwin linker flag ๐ฅ-exported_symbols_listโ Darwin linker flag ๐-filelistโ Darwin linker flag ๐-flat_namespaceโ Darwin linker flag ๐ซถ-force_flat_namespaceโ Darwin linker flag ๐-headerpad_max_install_namesโ Darwin linker flag ๐ฆ-image_baseโ Darwin linker flag ๐ผ๏ธ-initโ Darwin linker flag ๐ฑ-install_nameโ Darwin linker flag ๐ชช-keep_private_externsโ Darwin linker flag ๐-multi_moduleโ Darwin linker flag ๐งฉ-multiply_definedโ Darwin linker flag ๐ฏ-multiply_defined_unusedโ Darwin linker flag ๐-noall_loadโ Darwin linker flag ๐-no_dead_strip_inits_and_termsโ Darwin linker flag ๐-nofixprebindingโ Darwin linker flag ๐ ๏ธ-nomultidefsโ Darwin linker flag ๐ญ-noprebindโ Darwin linker flag ๐ซ-noseglinkeditโ Darwin linker flag ๐ชก-pagezero_sizeโ Darwin linker flag ๐-prebindโ Darwin linker flag ๐ง-prebind_all_twolevel_modulesโ Darwin linker flag ๐ท-private_bundleโ Darwin linker flag ๐ซง-read_only_relocsโ Darwin linker flag ๐-sectalignโ Darwin linker flag ๐-sectobjectsymbolsโ Darwin linker flag ๐งพ-whyloadโ Darwin linker flag ๐ค-seg1addrโ Darwin linker flag ๐-sectcreateโ Darwin linker flag ๐-sectobjectsymbolsโ Darwin linker flag, yes it's listed twice in the original ๐-sectorderโ Darwin linker flag ๐๏ธ-segaddrโ Darwin linker flag ๐-segs_read_only_addrโ Darwin linker flag ๐-segs_read_write_addrโ Darwin linker flag โ๏ธ-seg_addr_tableโ Darwin linker flag ๐-seg_addr_table_filenameโ Darwin linker flag ๐๏ธ-seglinkeditโ Darwin linker flag ๐ช-segprotโ Darwin linker flag ๐ก๏ธ-segs_read_only_addrโ Darwin linker flag, listed again here too ๐-segs_read_write_addrโ Darwin linker flag, listed again here too ๐-single_moduleโ Darwin linker flag โ๏ธ-staticโ Darwin linker flag ๐ฟ-sub_libraryโ Darwin linker flag ๐ช-sub_umbrellaโ Darwin linker flag โ๏ธ-twolevel_namespaceโ Darwin linker flag 2๏ธโฃ-umbrellaโ Darwin linker flag โ๏ธ-undefinedโ Darwin linker flag โ-unexported_symbols_listโ Darwin linker flag ๐-weak_reference_mismatchesโ Darwin linker flag ๐ธ๏ธ-whatsloadedโ Darwin linker flag ๐
Okay so all of these get passed straight through to the Darwin linker ๐ฆ, and the Darwin linker man page is where you'll find the full deets ๐.
โจ DEC Alpha Options ๐
These -m options are defined for the DEC Alpha implementations, so if you're on Alpha, these are your girls ๐
-mno-soft-float,-msoft-floatโ Okay so-mno-soft-floatuses the hardware floating-point instructions, and-msoft-floatsays don't use them ๐ . With-msoft-float, functions inlibgcc.ahandle the floating-point operations instead. Unless they get swapped out for routines that emulate floating-point operations, or get compiled to call such emulation routines, these routines issue floating-point operations themselves ๐. 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. Also, Alpha implementations without floating-point operations are still required to have floating-point registers ๐ง.-mfp-reg,-mno-fp-regsโ-mfp-regmakes the code use the floating-point register set, and-mno-fp-regsmakes it skip that set ๐ธ.-mno-fp-regsimplies-msoft-float. When the floating-point register set isn't used, floating-point operands are passed in integer registers as if they were integers, and floating-point results are passed in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value that gets called by code compiled with-mno-fp-regsmust also be compiled with that option ๐. A typical use is building a kernel that doesn't use, and hence doesn't need to save and restore, any floating-point registers ๐ฅ.-mieeeโ The Alpha architecture has floating-point hardware built for maximum performance, and it's mostly IEEE compliant, but full compliance needs a little software help ๐ซถ. This option generates fully IEEE-compliant code, except the inexact-flag isn't maintained (see below). When it's on, the preprocessor macro"_IEEE_FP"gets defined during compilation. The 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 foralpha-linux-gnu, unless-ffinite-math-only(which is part of the-ffast-mathset) is specified, because the software functions in the GNU libc math libraries generate denormalized numbers, NaNs, and infs (all of which will cause a program toSIGFPEwhen it attempts 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. In addition to"_IEEE_FP","_IEEE_FP_EXACT"is defined as a preprocessor macro. On some Alpha implementations the resulting code may run significantly slower than the default, and since there's very little code that depends on the inexact-flag, you should normally not specify this option ๐ . Other Alpha compilers call it-ieee_with_inexact.-mfp-trap-mode=trap-modeโ This controls which floating-point-related traps are enabled ๐ชค. Other Alpha compilers call this option-fptm trap-mode. The trap mode can be set to one of four values:nโ This is 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 too.suโ Likeu, but the instructions are marked as safe for software completion (see the Alpha architecture manual for details).suiโ Likesu, but inexact traps are enabled too.
-mfp-rounding-mode=rounding-modeโ This selects the IEEE rounding mode ๐. Other Alpha compilers call this option-fprm rounding-mode. Therounding-modecan 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 thefpcr,dcorresponds to round towards plus infinity ๐.
-mtrap-precision=trap-precisionโ In the Alpha architecture, floating-point traps are imprecise ๐ต. That means without software assistance it's impossible to recover from a floating trap, and program execution normally needs 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 a level 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โ This option marks the generated code as IEEE conformant ๐. You must not use it 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 construct it from smaller constants in two or three instructions. If it cannot, it outputs the constant as a literal and generates code to load it from the data segment at run time ๐ฆ. Use this option to require GCC to construct 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. Being a shared library itself, it must relocate itself in memory before it can find the variables and constants in its own data segment ๐ง.-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ These indicate whether GCC should generate code to use the optional BWX, CIX, FIX and MAX instruction sets ๐๏ธ. The default is to use the instruction sets supported by the CPU type specified via the-mcpu=option, or that of the CPU on which GCC was built if none is specified.-mfloat-vax,-mfloat-ieeeโ-mfloat-vaxmakes the code use VAX F and G floating-point arithmetic instead of IEEE single and double precision, and-mfloat-ieeemakes it not do that ๐ฆ.-mexplicit-relocs,-mno-explicit-relocsโ Older Alpha assemblers provided no way to generate symbol relocations except via assembler macros, and those macros don't allow optimal instruction scheduling ๐๏ธ. GNU binutils as of version 2.12 supports a new syntax that lets the compiler explicitly mark which relocations should apply to which instructions. This option is mostly useful for debugging, since GCC detects the capabilities of the assembler when it is built and sets the default accordingly.-msmall-data,-mlarge-dataโ When-mexplicit-relocsis in effect, static data is accessed via gp-relative relocations ๐. When-msmall-datais used, objects 8 bytes long or smaller are placed in a small data area (the".sdata"and".sbss"sections) and are accessed via 16-bit relocations off of the$gpregister. This limits the size of the small data area to 64KB, but lets the variables be accessed directly via a single instruction โก. The default is-mlarge-data. With this option the data area is limited to just below 2GB. Programs that require more than 2GB of data must use"malloc"or"mmap"to allocate the data in the heap instead of in the program's data segment ๐พ. When generating code for shared libraries,-fpicimplies-msmall-dataand-fPICimplies-mlarge-data.-msmall-text,-mlarge-textโ When-msmall-textis used, the compiler assumes the code of the entire program (or shared library) fits in 4MB, and is thus reachable with a branch instruction ๐ฆ. When-msmall-datais used, the compiler can assume that all local symbols share the same$gpvalue, and thus reduce the number of instructions required for a function call from 4 to 1 โจ. The default is-mlarge-text.-mcpu=cpu_typeโ okay so this one sets the instruction set and the instruction scheduling parameters for machine typecpu_type๐ You can pass either the EV style name or the matching chip number. GCC has scheduling parameters for the EV4, EV5 and EV6 family, and it picks the default instruction set from whichever processor you name. If you don't name a processor type, GCC defaults to the processor the compiler was built on ๐ง
Supported values for cpu_type are:
ev4,ev45,21064โ schedules as an EV4 and has no instruction set extensions ๐ธev5,21164โ schedules as an EV5 and has no instruction set extensions ๐ธev56,21164aโ schedules as an EV5 and supports the BWX extension ๐pca56,21164pc,21164PCโ schedules as an EV5 and supports the BWX and MAX extensions ๐ev6,21264โ schedules as an EV6 and supports the BWX, FIX, and MAX extensions โจev67,21264aโ schedules as an EV6 and supports the BWX, CIX, FIX, and MAX extensions ๐
Native toolchains also support the value native, which picks the best architecture option for the host processor. -mcpu=native has no effect if GCC doesn't recognize the processor ๐ซถ
-mtune=cpu_typeโ this one only touches the instruction scheduling parameters forcpu_type. The instruction set stays exactly the same โจ
Native toolchains also support the value native, which picks the best architecture option for the host processor. -mtune=native has no effect if GCC doesn't recognize the processor ๐ฆ
-mmemory-latency=timeโ this sets the latency the scheduler should assume for typical memory references as seen by the application. Honestly this number is highly dependent on the memory access patterns the application uses and the size of the external cache on the machine ๐ง
Valid options for time are:
numberโ a decimal number representing clock cycles ๐ขL1,L2,L3,mainโ the compiler has estimates of clock cycles for "typical" EV4 & EV5 hardware for the Level 1, 2 & 3 caches (also called Dcache, Scache, and Bcache), as well as for main memory. Note thatL3is only valid for EV5 ๐ฅบ
โจ eBPF Options โจ
-mframe-limit=bytesโ this sets the hard limit for frame sizes, in bytes ๐ Right now the value you pass should be less than or equal to32767. It defaults to whatever limit is imposed by the version of the Linux kernel being targeted ๐ง-mkernel=versionโ this is the minimum kernel version that will run your compiled program. GCC uses it to decide which instructions to use, which kernel helpers to allow, etc. ๐ง Currently, version can be one of4.0,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,4.10,4.11,4.12,4.13,4.14,4.15,4.16,4.17,4.18,4.19,4.20,5.0,5.1,5.2,latestandnative-mbig-endianโ generate code for a big-endian target ๐-mlittle-endianโ generate code for a little-endian target. This is the default ๐-mjmpextโ enables generation of extra conditional-branch instructions. It's enabled for CPU v2 and above ๐ฆ-mjmp32โ enables 32-bit jump instructions. It's enabled for CPU v3 and above ๐ธ-malu32โ enables 32-bit ALU instructions. It's enabled for CPU v3 and above ๐-mcpu=versionโ this picks which version of the eBPF ISA to target. Newer versions may not be supported by all kernels, so be careful ๐ The default isv3.
Supported values for version are:
v1โ the first stable eBPF ISA, with no special features or extensions ๐v2โ supports the jump extensions, as in-mjmpextโจv3โ all features of v2, plus:-<32-bit jump operations, as in -mjmp32>-<32-bit ALU operations, as in -malu32>
-mco-reโ enables BPF Compile Once - Run Everywhere (CO-RE) support. It requires and is implied by-gbtf๐-mno-co-reโ disables BPF Compile Once - Run Everywhere (CO-RE) support. BPF CO-RE support is enabled by default when generating BTF debug information for the BPF target ๐ โโ๏ธ-mxbpfโ generates code for an expanded version of BPF, which relaxes some of the restrictions imposed by the BPF architecture ๐ฅ-<Save and restore callee-saved registers at function entry and exit, respectively.>
๐ธ FR30 Options ๐ธ
These options are defined specifically for the FR30 port ๐ง
-msmall-modelโ uses the small address space model. This can produce smaller code, but it does assume that all symbolic values and addresses fit into a 20-bit range ๐ฃ-mno-lsimโ assumes runtime support has 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โ specifies that the program will run on the simulator. This causes an alternate runtime startup and library to be linked ๐ฎ
๐ You must not use this option when generating programs that will run on real hardware. You have to provide your own runtime library for whatever I/O functions are needed.
-mlraโ enables Local Register Allocation. This is still experimental for FT32, so by default the compiler uses standard reload ๐งช-mnodivโ don't usedivandmodinstructions ๐ซ-mft32bโ enables use of 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โ use only 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 insns ๐-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โ selects the FDPIC ABI, which uses function descriptors to represent pointers to functions. Without any PIC/PIE-related options, it implies-fPIE. With-fpicor-fpie, it assumes GOT entries and small data are within a 12-bit range from the GOT base address; with-fPICor-fPIE, GOT offsets are computed with 32 bits. With abfin-elftarget, this option implies-msim๐งฉ-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally. It has no effect without-mfdpic. It's enabled by default if you're optimizing for speed and compiling for shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is on the command line ๐-mTLSโ assumes a large TLS segment when generating thread-local code ๐งต-mtlsโ doesn't assume a large TLS segment when generating thread-local code ๐ชก-mgprel-roโ enables the use of "GPREL" relocations in the FDPIC ABI for data known to be in read-only sections. It's enabled by default, except for-fpicor-fpie. Even though it may help make the global offset table smaller, it trades 1 instruction for 4. With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols, and it avoids the need for a GOT entry for the referenced symbol, so it's more likely to be a win. If it isn't,-mno-gprel-rocan be used to disable it ๐งฎ-multilib-library-picโ links with the (library, not FD) pic libraries. It's implied by-mlibrary-pic, as well as by-fPICand-fpicwithout-mfdpic. You should never have to use it explicitly ๐ โโ๏ธ-mlinked-fpโ follows the EABI requirement of always creating a frame pointer whenever a stack frame is allocated. This option is enabled by default and can be disabled with-mno-linked-fp๐ผ๏ธ-mlong-callsโ uses indirect addressing to call functions outside the current compilation unit. This lets the functions be placed anywhere within the 32-bit address space ๐-malign-labelsโ tries to align labels to an 8-byte boundary by inserting NOPs into the previous packet. This option only has an effect when VLIW packing is enabled. It doesn't create new packets; it just adds NOPs to existing ones ๐-mlibrary-picโ generates position-independent EABI code ๐ซถ-macc-4โ use only the first four media accumulator registers 4๏ธโฃ-macc-8โ use all eight media accumulator registers 8๏ธโฃ-mpackโ packs VLIW instructions ๐ฆ-mno-packโ don't pack VLIW instructions ๐ซ-mno-eflagsโ don't mark ABI switches ine_flags๐ณ๏ธ-mcond-moveโ enables the use of conditional-move instructions (default) ๐ธ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-cond-moveโ disables the use of conditional-move instructions ๐ โโ๏ธ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-msccโ enables the use of conditional set instructions (default) โจ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-sccโ disables the use of conditional set instructions ๐ โโ๏ธ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mcond-execโ enables the use of conditional execution (default) ๐ฆ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-cond-execโ disables the use of conditional execution ๐ โโ๏ธ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mvliw-branchโ okay so this one runs a pass that packs branches into VLIW instructions ๐ซถ It's on by default. This switch is mainly for debugging the compiler and will probably get removed in a future version ๐-mno-vliw-branchโ the opposite! Skips the pass that packs branches into VLIW instructions. Also mostly a debugging switch that will likely be removed in a future version ๐-mmulti-cond-execโ turns on optimization of"&&"and"||"in conditional execution โจ It's the default. Also debugging-only and likely to be removed someday ๐ฅ-mno-multi-cond-execโ turns that optimization off for"&&"and"||"in conditional execution. Debugging-only, likely removed later ๐ง-mnested-cond-execโ enables nested conditional execution optimizations. Default, obviously ๐ Debugging-only, will probably be removed later too-mno-nested-cond-execโ disables nested conditional execution optimizations. Debugging-only, likely removed in a future version ๐-moptimize-membarโ removes redundant"membar"instructions from the compiler-generated code. It's on by default, so you get the glow-up automatically ๐-mno-optimize-membarโ disables that automatic removal of redundant"membar"instructions from the generated code. Your membars stay put ๐ธ-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 ๐
These -m options are defined for GNU/Linux targets, bestie ๐ง
-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. It's the default on*-*-linux-*android*targets, so it's giving main character energy ๐ฑ- When compiling, this option enables
-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐ซถ - When linking, it makes the GCC driver pass Android-specific options to the linker ๐
- Finally, it causes the preprocessor macro
"__ANDROID__"to be defined โจ
- When compiling, this option enables
-tno-android-ccโ disables the compilation effects of-mandroid. So it does not enable-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐ โโ๏ธ-tno-android-ldโ disables the linking effects of-mandroid, so the linker just gets standard Linux linking options ๐ฃ
๐ฆ H8/300 Options ๐ฆ
These -m options are defined for the H8/300 implementations, so if you're doing that, here's the tea โ
-mrelaxโ shortens some address references at link time, when it's possible. It uses the linker option-relaxto do it ๐ช-mhโ generates code for the H8/300H ๐ซ-msโ generates code for the H8S ๐-mnโ generates code for the H8S and H8/300H in the normal mode. You have to use this with either-mhor-ms, no skipping ๐ซถ-ms2600โ generates code for the H8S/2600. This one must be used together with-ms๐-mexrโ the extended registers get stored on the stack before a function with the monitor attribute runs. This is the default option โจ It's only valid for H8S targets, so keep that in mind ๐-mno-exrโ the extended registers do not get stored on the stack before a function with the monitor attribute runs. The default option here is-mno-exr, and it's again 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. The H8/300H and H8S normally align longs and floats on 4-byte boundaries, but-malign-300pushes them to 2-byte boundaries instead. It has no effect on the H8/300 ๐ธ
๐ท HPPA Options ๐ท
These -m options are defined for the HPPA family of computers. Let's get into it ๐ง
-march=architecture-typeโ generates code for the architecture you pick. The choices for architecture-type are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors. If you're unsure which one is yours, check out/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.0, respectively ๐-mcaller-copiesโ the caller copies function arguments that get passed by hidden reference. Use this one with care, because it isn't compatible with the default 32-bit runtime ๐ฌ That said, only aggregates larger than eight bytes get passed by hidden reference, and this option gives you better compatibility with OpenMP ๐ซถ-mjump-in-delayโ this is ignored. It's only here for compatibility purposes ๐-mdisable-fpregsโ stops floating-point registers from being used in any manner. This is necessary for compiling kernels that do lazy context switching of floating-point registers ๐ง If you use this option and then try to do floating-point operations, the compiler aborts ๐-mdisable-indexingโ stops the compiler from using indexing address modes. This dodges some rather obscure problems when compiling MIG generated code under MACH ๐งฉ-mno-space-regsโ generates code that assumes the target has no space registers. This lets GCC make faster indirect calls and use unscaled index address modes โก- Code like this is suitable for level 0 PA systems and kernels ๐ฅ๏ธ
-mfast-indirect-callsโ generates code that assumes calls never cross space boundaries, so GCC can emit code that does faster indirect calls ๐โโ๏ธ- This option does not work in the presence of shared libraries or nested functions โ
-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use. This is super useful when compiling kernel code ๐ A register range is written as two registers separated by a dash, and you can separate multiple ranges with a comma ๐-mlong-load-storeโ generates 3-instruction load and store sequences, which the HP-UX 10 linker sometimes needs. This is equivalent to the+koption on the HP compilers ๐ซถ-mportable-runtimeโ uses the portable calling conventions HP proposed for ELF systems ๐-mgasโ enables the use of assembler directives that only GAS understands ๐-mschedule=cpu-typeโ schedules code according to the constraints for the machine type cpu-type. The choices are700 7100,7100LC,7200,7300and8000. Check/usr/lib/sched.modelson an HP-UX system to find the right scheduling option for your machine ๐ The default scheduling is8000โจ-mlinker-optโ enables the optimization pass in the HP-UX linker. Heads up though, 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 ๐-msoft-floatโ generates output that contains library calls for floating point ๐งฎ
โ ๏ธ Warning, bestie: the requisite libraries are not available for all HPPA targets. Normally the facilities of the machine's usual C compiler are used, but that can't be done directly in cross-compilation. You'll have to make your own arrangements to provide suitable library functions for cross-compilation ๐ซ
-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐งต- You also need to compile
libgcc.a, the library that comes with GCC, with-msoft-floatfor this to work ๐
-msioโ generates the predefine"_SIO"for server IO. The default is-mwsio, which generates the predefines"__hp9000s700","__hp9000s700__"and"_WSIO"for workstation IO. These options are available under HP-UX and HI-UX ๐ฅ๏ธ-mgnu-ldโ uses options specific to GNU ld. This passes-sharedto ld when building a shared library. It's the default when GCC is configured (explicitly or implicitly) with the GNU linker ๐ง This option doesn't change which ld gets called. It only changes what parameters get passed to that ld. The ld that's called is decided by the--with-ldconfigure option, GCC's program search path, and finally the user'sPATH๐บ๏ธ You can print the linker GCC uses withwhichgcc -print-prog-name=ld``. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*๐-mhp-ldโ uses options specific to HP ld. This passes-bto ld when building a shared library, and passes+Accept TypeMismatchto ld on all links ๐ซถ It's the default when GCC is configured (explicitly or implicitly) with the HP linker ๐ Just like-mgnu-ld, this doesn't affect which ld is called, only the parameters. That's decided by the--with-ldconfigure option, GCC's program search path, and finally the user'sPATH๐งญ Print the linker withwhichgcc -print-prog-name=ld. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*--hpux` ๐ธ-mlong-callsโ generates code that uses long call sequences. This makes sure a call can always reach linker-generated stubs ๐งฉ By default, long calls are only generated when the distance from the call site to the beginning of the function or translation unit (depending on the case) goes over a predefined limit set by the branch type being used. The limits for normal calls are7,600,000and240,000bytes, for PA 2.0 and PA 1.X architectures respectively. Sibcalls are always limited at240,000bytes ๐- Distances are measured from the beginning of functions when using
-ffunction-sections, or when using-mgasand-mno-portable-runtimetogether under HP-UX with the SOM linker ๐ - Honestly, it's usually not desirable to use this option because it degrades performance ๐ฉ But it may be useful in large applications, especially when partial linking is used to build the application ๐ซถ
- Distances are measured from the beginning of functions when using
The types of long calls used depend on what the assembler and linker can do, plus the kind of code being generated. Systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, should barely notice the impact ๐ง. But on 32-bit ELF systems in pic code, an indirect call gets used instead, and it's quite long ๐ญ
-munix=unix-stdโ Sets up the compiler predefines and picks a startfile for the UNIX standard you choose ๐ . The options are93,95and98.93works on every HP-UX version.95needs HP-UX 10.10 or later, and98needs HP-UX 11.11 or later. By default you get93on HP-UX 10.00,95on HP-UX 10.10 through 11.00, and98on HP-UX 11.11 and up.
-munix=93 gives you the same predefines as GCC 3.3 and 3.4. -munix=95 adds predefines for "XOPEN_UNIX" and "_XOPEN_SOURCE_EXTENDED", plus the startfile unix95.o. -munix=98 adds predefines for "_XOPEN_UNIX", "_XOPEN_SOURCE_EXTENDED", "_INCLUDE__STDC_A1_SOURCE" and "_INCLUDE_XOPEN_SOURCE_500", plus the startfile unix98.o.
Heads up, bestie: this option changes the interfaces of various library routines, and it also affects how the C library behaves ๐ฌ So you need to be extra careful with it.
Library code that's meant to work with more than one UNIX standard has to test, set and restore the variable "__xpg4_extended_mask" as needed. Most GNU software doesn't do this, so don't expect it ๐
-nolibdldโ Stops the driver from adding the link options that searchlibdld.slwhen you use-staticon HP-UX 10 and later ๐-staticโ Here's the tea โ The HP-UX version ofsetlocaleinlibcdepends onlibdld.sl, and there's no archive version oflibdld.sl. So when you pass-static, you need special link options to sort this out.
On HP-UX 10 and later, the GCC driver adds the link options it needs to link with libdld.sl whenever you use -static. This makes the resulting binary dynamic. On the 64-bit port, the linkers make dynamic binaries by default anyway. If you don't want the driver adding these link options, use -nolibdld ๐
-threadsโ Adds multithreading support using 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 for the Intel IA-64 architecture ๐
-mbig-endianโ Generates code for a big-endian target. This is the default on HP-UX.-mlittle-endianโ Generates code for a little-endian target. This is the default on AIX5 and GNU/Linux.-mgnu-as,-mno-gnu-asโ Generates code for the GNU assembler, or doesn't. Generating it is the default.-mgnu-ld,-mno-gnu-ldโ Generates code for the GNU linker, or doesn't. Generating it is the default.-mno-picโ Generates code that doesn't use a global pointer register. The result is not position independent code, and it breaks the IA-64 ABI ๐-mvolatile-asm-stop,-mno-volatile-asm-stopโ Generates (or doesn't) a stop bit right before and after volatile asm statements ๐-mregister-names,-mno-register-namesโ Generates (or doesn't) thein,loc, andoutregister names for the stacked registers. This might make the assembler output easier to read ๐-mno-sdata,-msdataโ Disables (or enables) optimizations that use the small data section. This can be handy for working around optimizer bugs ๐-mconstant-gpโ Generates code that uses one 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 inline divides of floating-point values using the minimum latency algorithm.-minline-float-divide-max-throughputโ Generates inline divides of floating-point values using the maximum throughput algorithm.-mno-inline-float-divideโ Doesn't generate inline code for divides of floating-point values.-minline-int-divide-min-latencyโ Generates inline divides of integer values using the minimum latency algorithm.-minline-int-divide-max-throughputโ Generates inline divides of integer values using the maximum throughput algorithm.-mno-inline-int-divideโ Doesn't generate inline code for divides of integer values.-minline-sqrt-min-latencyโ Generates inline square roots using the minimum latency algorithm.-minline-sqrt-max-throughputโ Generates inline square roots using the maximum throughput algorithm.-mno-inline-sqrtโ Doesn't generate inline code forsqrt.-mfused-madd,-mno-fused-maddโ Does (or doesn't) generate code using 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 might be useful when you're not using the GNU assembler.-mearly-stop-bits,-mno-early-stop-bitsโ Lets stop bits go earlier than right before the instruction that triggered them. This can improve instruction scheduling, but it doesn't always ๐คทโโ๏ธ-mfixed-range=register-rangeโ Generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use. This is useful when compiling kernel code ๐งฉ You give a register range as two registers separated by a dash, and you can list several ranges separated by commas.-mtls-size=tls-sizeโ Sets the bit size of immediate TLS offsets. The valid values are14,22, and64.-mtune=cpu-typeโ Tunes instruction scheduling for a particular CPU. The valid values areitanium,itanium1,merced,itanium2, andmckinley๐ฏ-milp32,-mlp64โ Generates code for a 32-bit or 64-bit environment. The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits. These are HP-UX specific flags ๐ฅ๏ธ-mno-sched-br-data-spec,-msched-br-data-specโ Disables (or enables) data speculative scheduling before reload. This producesld.ainstructions and the matching check instructions (ld.c/chk.a). The default is disabled.-msched-ar-data-spec,-mno-sched-ar-data-specโ Enables (or disables) data speculative scheduling after reload. This producesld.ainstructions and the matching check instructions (ld.c/chk.a). The default is enabled.-mno-sched-control-spec,-msched-control-specโ Disables (or enables) control speculative scheduling. This only works during region scheduling, which means before reload. It produces theld.sinstructions and the matching check instructionschk.s. The default is disabled.-msched-br-in-data-spec,-mno-sched-br-in-data-specโ Enables (or disables) speculative scheduling of instructions that depend on the data speculative loads before reload. This only does anything with-msched-br-data-specenabled. The default is enabled.-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ Enables (or disables) speculative scheduling of instructions that depend on the data speculative loads after reload. This only does anything with-msched-ar-data-specenabled. The default is enabled.-msched-in-control-spec,-mno-sched-in-control-specโ Enables (or disables) speculative scheduling of instructions that depend on the control speculative loads. This only does anything with-msched-control-specenabled. The default is enabled.-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ When enabled, data-speculative instructions only get scheduled if there are no other choices at the moment. This makes data speculation much more conservative. The default is disabled.-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ When enabled, control-speculative instructions only get scheduled if there are no other choices at the moment. This makes control speculation much more conservative. The default is disabled.-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ When enabled, speculative dependencies are considered when computing instruction priorities. This makes speculation a bit more conservative. The default is disabled.-msched-spec-ldcโ Uses a simple data speculation check. This option is on by default โ-msched-control-spec-ldcโ Uses a simple check for control speculation. This option is on by default โ-msched-stop-bits-after-every-cycleโ Places a stop bit after every cycle when scheduling. This option is on by default โ-msched-fp-mem-deps-zero-costโ Assumes that floating-point stores and loads aren't likely to conflict when placed into the same instruction group. This option is disabled by default.-msel-sched-dont-check-control-specโ Generates checks for control speculation in selective scheduling. This flag is disabled by default.-msched-max-memory-insns=max-insnsโ Limits the number of memory insns per instruction group, giving lower priority to later memory insns that try to schedule in the same group. This is often handy for avoiding cache bank conflicts ๐ง The default value is1.-msched-max-memory-insns-hard-limitโ Turns the limit set bymsched-max-memory-insnsinto a hard limit, so no more than that number of memory insns can go in one instruction group. Otherwise the limit is "soft": non-memory operations are preferred once the limit is reached, 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 okay bestie ๐ turns on the divide and modulus instructions ๐งฎโจ no cap they're a whole vibe.
-mmultiply-enabledโ enables the multiply instructions ๐ฆ-msign-extend-enabledโ enables the sign extend instructions ๐ธ-muser-enabledโ enables user-defined instructions ๐ง
โจ M32C Options โจ
-mcpu=nameโ pick the CPU you're generating code for ๐ thenamecan ber8cfor the R8C/Tiny series,m16cfor the M16C (up to /60) series,m32cmfor the M16C/80 series, orm32cfor the M32C/80 series ๐-msimโ tells GCC the program will run on the simulator ๐ฎ this links in an alternate runtime library that supports stuff like file I/O ๐ > โ ๏ธ bestie, DO NOT use this for programs running on real hardware!! ๐ญ you need to bring your own runtime library for whatever I/O functions you need ๐ซถ-memregs=numberโ sets how many memory-based pseudo-registers GCC uses during code generation ๐ง they act like real registers, so it's a tradeoff between fitting code into registers and the performance hit of using memory instead ๐ every module in your program has to be compiled with the same value ๐ and since 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 one's the default ๐-mmodel=smallโ assumes all objects live in the lower 16MB of memory ๐ธ so their addresses can be loaded with the"ld24"instruction, and all subroutines are reachable with the"bl"instruction ๐ง this is the default โจ
The addressability of a particular object can be set with the "model" attribute ๐
-mmodel=mediumโ assumes objects may be anywhere in the 32-bit address space ๐ GCC generates"seth/add3"instructions to load their addresses, and all subroutines are still reachable with the"bl"instruction ๐ซถ-mmodel=largeโ assumes objects may be anywhere in the 32-bit address space AND subroutines may not be reachable with"bl"๐ฑ GCC generates"seth/add3"to load addresses and the much slower"seth/add3/jl"sequence for calls ๐ข-msdata=noneโ disables the small data area ๐ variables go into".data",".bss", or".rodata"(unless the"section"attribute is specified) ๐ this is the default ๐
The small data area is made of the ".sdata" and ".sbss" sections ๐ง you can explicitly put objects there 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 tonumbytes into the small data or BSS sections โญ instead of the normal data or BSS sections ๐ the defaultnumis8๐ the-msdataoption has to be set tosdataorusefor this to do anything ๐ซ
All modules should be compiled with the same -G num value ๐ซถ using different values might or might not work ๐คทโโ๏ธ if it doesn't, the linker gives an error message---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โ does not enforce 32-byte alignment for loops ๐ โโ๏ธ this is the default ๐-missue-rate=numberโ issuesnumberinstructions per cycle โกnumbercan only be1or2๐ข-mbranch-cost=numberโ sets the branch cost ๐ธnumbercan only be1or2๐ข if it's1, branches are preferred over conditional code ๐ฟ if it's2, the opposite applies ๐-mflush-trap=numberโ specifies the trap number used to flush the cache ๐งน the default is12๐ valid numbers are between0and15inclusive ๐ข-mno-flush-trapโ says the cache cannot be flushed by using a trap ๐ซ-mflush-func=nameโ specifies the name of the operating system function to call to flush the cache ๐งผ the default is_flush_cache๐ but a function call is only used if a trap isn't available ๐ซค-mno-flush-funcโ says there is no OS function for flushing the cache ๐ โโ๏ธ
โจ M680x0 Options โจ
These are the -m options defined for M680x0 and ColdFire processors ๐ฅ๏ธ the defaults depend on which architecture was selected when the compiler was configured ๐ ๏ธ 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,archcan be68000,68010,68020,68030,68040,68060orcpu32๐ ColdFire architectures are picked by Freescale's ISA classification, and the options areisaa,isaaplus,isabandisac๐
GCC defines a macro "__mcfarch__" whenever it's generating code for a ColdFire target ๐ง the arch in that macro is one of the -march arguments above โจ
When you use -march and -mtune together, you get code that runs on a 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 within the limits set by-marchand-mcpu๐ต the M680x0 microarchitectures are68000,68010,68020,68030,68040,68060andcpu32๐ the ColdFire microarchitectures arecfv1,cfv2,cfv3,cfv4andcfv4e๐ซถ
You can also use -mtune=68020-40 for code that needs to run pretty well on 68020, 68030 and 68040 targets ๐งก -mtune=68020-60 is similar but also includes 68060 targets ๐ these two 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 -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 the range ๐
GCC also defines the macro "__muarch__" when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments above ๐ฆ
-m68000-mc68000โ generates output for a 68000 ๐ธ this is the default when the compiler is configured for 68000-based systems ๐ it's equivalent to-march=68000โจ
Use this 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 have to be emulated in software on the 68060 ๐ โโ๏ธ use it if your 68060 doesn't have code to emulate those instructions ๐ซ
-mcpu32โ generates output for a CPU32 ๐ธ this is the default when the compiler is configured for CPU32-based systems ๐ it's equivalent to-march=cpu32โจ
Use this for microcontrollers with a CPU32 or CPU32+ core, including the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360 ๐งธ
-m5200โ generates output for a 520X ColdFire CPU ๐ฅ๏ธ this is the default when the compiler is configured for 520X-based systems ๐ it's equivalent to-mcpu=5206, but it's deprecated in favour of that option ๐
Use this for microcontrollers with a 5200 core, including the MCF5202, MCF5203, MCF5204 and MCF5206 ๐งธ
-m5206eโ generates output for a 5206e ColdFire CPU ๐ฅ๏ธ this option is deprecated now, so use the equivalent-mcpu=5206einstead ๐-m528xโ Okay bestie, this one generates code for the ColdFire 528X family ๐ฆ. It's deprecated now, so use-mcpu=528xinstead ๐ .-m5307โ Generates output for a ColdFire 5307 CPU ๐ธ. Also deprecated, so-mcpu=5307is the move โจ.-m5407โ Generates output for a ColdFire 5407 CPU ๐. Deprecated too, so go with-mcpu=5407๐ซถ.-mcfv4eโ Generates output for a ColdFire V4e family CPU, like the 547x/548x chips ๐ฅ. This includes hardware floating-point instructions. It's the same as-mcpu=547x, and it's deprecated in favor of that one ๐ .-m68020-40โ Generates output for a 68040 but skips all the new instructions ๐. The result runs pretty efficiently on a 68020/68881, a 68030, or a 68040. The code does use the 68881 instructions, which get emulated on the 68040 ๐ง. This is equivalent to-march=68020 -mtune=68020-40.-m68020-60โ Generates output for a 68060 and also skips the new instructions ๐. Same deal: it runs pretty efficiently on a 68020/68881, a 68030, or a 68040. The code uses the 68881 instructions, which get emulated on the 68060 ๐. This is equivalent to-march=68020 -mtune=68020-60.-mhard-float,-m68881โ Turns on floating-point instructions โญ. This is the default for the 68020 and up, and for ColdFire devices with an FPU. It defines the macro__HAVE_68881__on M680x0 targets and__mcffpu__on ColdFire targets ๐.-msoft-floatโ Skips floating-point instructions and uses library calls instead ๐. This is the default for 68000, 68010, and 68832 targets. It's also the default for ColdFire devices that don't have an FPU ๐.-mdiv,-mno-divโ Lets you choose whether to generate ColdFire hardware divide and remainder instructions ๐ฅ. If you use-marchwithout-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 whatever you set with-mcpu. For example, the default is "off" for-mcpu=5206and "on" for-mcpu=5206eโจ.
When this option is enabled, GCC defines the macro __mcfhwdiv__ ๐ฆ.
-mshortโ Treats type "int" as 16 bits wide, just like "short int" ๐ธ. Parameters passed on the stack also get aligned to a 16-bit boundary, even on targets that normally promote to 32-bit ๐ซถ.-mno-shortโ Does not treat type "int" as 16 bits wide. This is the default ๐ .-mnobitfield,-mno-bitfieldโ Skips the bit-field instructions ๐ โโ๏ธ. The-m68000,-mcpu32, and-m5200options all imply-mnobitfield๐.-mbitfieldโ Uses the bit-field instructions ๐ง. The-m68020option implies-mbitfield, and this is the default if you're using a configuration designed for a 68020 โจ.-mrtdโ Switches to a different function-calling convention ๐. Functions that take a fixed number of arguments return with the "rtd" instruction, which pops their arguments as it returns. This saves one instruction in the caller, since the caller doesn't need to pop the arguments ๐.
This calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler ๐.
You also have to provide function prototypes for every function that takes a variable number of arguments, including "printf". If you skip them, GCC generates incorrect code for calls to those functions ๐.
Seriously incorrect code results if you call a function with too many arguments. Normally, extra arguments are harmlessly ignored, but with this option they aren't ๐ญ.
The "rtd" instruction is supported by the 68010, 68020, 68030, 68040, 68060, and CPU32 processors, but not by the 68000 or 5200 ๐ .
The default is -mno-rtd.
-malign-int,-mno-align-intโ Controls whether GCC aligns "int", "long", "long long", "float", "double", and "long double" variables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐. Aligning on 32-bit boundaries makes code run somewhat faster on processors with 32-bit busses, but it costs more memory ๐ฆ.
Warning: if you use -malign-int, GCC aligns structures containing those types differently than most published application binary interface specifications for the m68k. Lowkey a big deal, so watch out ๐ญ.
-mpcrelโ Uses the pc-relative addressing mode of the 68000 directly, instead of a global offset table ๐ง. Right now this option implies-fpic, which allows at most a 16-bit offset for pc-relative addressing ๐ธ.-fPICisn't currently supported with-mpcrel, though it could be supported for 68020 and higher processors ๐ซถ.-mno-strict-align,-mstrict-alignโ-mno-strict-alignmeans GCC does not assume the system handles unaligned memory references, and-mstrict-alignmeans it does assume that ๐ .-msep-dataโ Generates code that lets the data segment live in a different area of memory from the text segment ๐. This allows execute-in-place in an environment without virtual memory management ๐. This option implies-fPICโจ.-mno-sep-dataโ Generates code that assumes the data segment follows the text segment. This is the default ๐.-mid-shared-libraryโ Generates code that supports shared libraries through the library ID method ๐ฆ. This lets you do execute-in-place and shared libraries in an environment without virtual memory management ๐ง. This option implies-fPIC๐.-mno-id-shared-libraryโ Generates code that doesn't assume ID-based shared libraries are being used. This is the default ๐ .-mshared-library-id=nโ Sets the identification number of the ID-based shared library being compiled ๐ธ. Using 0 gives you more compact code. Other values force that number onto the current library, but that's no more space- or time-efficient than leaving this option out ๐.-mxgot,-mno-xgotโ When generating position-independent code for ColdFire,-mxgotgenerates code that works even if the GOT has more than 8192 entries ๐ฅ. This code is larger and slower than code generated without the option. On M680x0 processors you don't need this option, since-fPICis enough ๐ .
GCC normally uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker report an error 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 generated with -mxgot is less efficient, since it takes 4 instructions to fetch the value of a global symbol ๐.
Some linkers, including newer versions of the GNU linker, can create multiple GOTs and sort GOT entries ๐. If you have one of those, you should only need -mxgot when compiling a single object file that accesses more than 8192 GOT entries. Very few do ๐.
These options have no effect unless GCC is generating position-independent code โจ.
-mlong-jump-table-offsetsโ Uses 32-bit offsets in "switch" tables ๐ง. The default is 16-bit offsets ๐.
MCore Options
These are the -m options defined for the Motorola M*Core processors ๐ธ.
-mhardlit,-mno-hardlitโ Inlines constants into the code stream if it can be done in two instructions or fewer ๐.-mdiv,-mno-divโ Uses the divide instruction ๐ฅ. It's enabled by default ๐ .-mrelax-immediate,-mno-relax-immediateโ Allows arbitrary-sized immediates in bit operations ๐ฆ.-mwide-bitfields,-mno-wide-bitfieldsโ Always treats bit-fields as "int"-sized ๐ซถ.-m4byte-functions,-mno-4byte-functionsโ Forces all functions to be aligned to a 4-byte boundary ๐.-mcallgraph-data,-mno-callgraph-dataโ Emits callgraph information ๐ง.-mslow-bytes,-mno-slow-bytesโ Prefers word access when reading byte quantities ๐.-mlittle-endian,-mbig-endianโ Generates code for a little-endian target ๐.-m210,-m340โ Generates code for the 210 processor โญ.-mno-lsimโ Assumes runtime support has 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 ๐. Large 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โจ.
MeP Options
-mabsdiffโ Enables the"abs"instruction, which gives you the absolute difference between two registers ๐ฆ.-mall-optsโ Enables all the optional instructions: average, multiply, divide, bit operations, leading zero, absolute difference, min/max, clip, and saturation ๐ฅ.-maverageโ Enables the"ave"instruction, which computes the average of two registers ๐ซถ.-mbased=nโ Puts variables of sizenbytes or smaller in the".based"section by default ๐ธ. Based variables use the$tpregister as a base register, and the".based"section has a 128-byte limit ๐ง.-mbitopsโ Enables the bit operation instructions: bit test ("btstm"), set ("bsetm"), clear ("bclrm"), invert ("bnotm"), and test-and-set ("tas") ๐.-mc=nameโ Selects which section constant data gets placed in ๐ .namecan betiny,near, orfar๐.-mclipโ Enables the"clip"instruction ๐. Heads up,-mclipisn't useful unless you also provide-mminmax๐.-mconfig=nameโ Selects one of the built-in core configurations ๐. Each MeP chip has one or more modules, and each module has a core CPU plus a variety of coprocessors, optional instructions, and peripherals. The "MeP-Integrator" tool, which is not part of GCC, provides these configurations through this option. Using this option is the same as using all the corresponding command-line options ๐. The default configuration isdefaultโจ.-mcopโ Enables the coprocessor instructions. By default this is a 32-bit coprocessor ๐ฆ. The coprocessor is normally enabled through the-mconfig=option ๐ซถ.-mcop32โ Enables the 32-bit coprocessor's instructions ๐ฅ.-mcop64โ Enables the 64-bit coprocessor's instructions ๐โจ.
-mivc2 Enables IVC2 scheduling. IVC2 is a 64-bit VLIW coprocessor.
Okay bestie, so -mivc2 turns on IVC2 scheduling ๐ฆ and IVC2 is a 64-bit VLIW coprocessor (a whole coprocessor, not just a vibe) โจ
-mdc Causes constant variables to be placed in the ".near" section.
-mdc puts constant variables into the ".near" section ๐ธ
-mdiv Enables the "div" and "divu" instructions.
-mdiv unlocks the "div" and "divu" instructions ๐
-meb Generate big-endian code.
-meb means big-endian code, no cap ๐ซถ
-mel Generate little-endian code.
-mel gives you little-endian code ๐
-mio-volatile Tells the compiler that any variable marked with the "io" attribute is to be considered volatile.
-mio-volatile tells the compiler that anything with the "io" attribute is treated as volatile ๐ฅ iykyk
-ml Causes variables to be assigned to the ".far" section by default.
-ml sends variables to the ".far" section by default ๐
-mleadz Enables the "leadz" (leading zero) instruction.
-mleadz enables the "leadz" (leading zero) instruction ๐ง
-mm Causes variables to be assigned to the ".near" section by default.
-mm makes variables default to the ".near" section ๐
-mminmax Enables the "min" and "max" instructions.
-mminmax enables the "min" and "max" instructions โญ
-mmult Enables the multiplication and multiply-accumulate instructions.
-mmult turns on the multiplication and multiply-accumulate instructions ๐
-mno-opts Disables all the optional instructions enabled by -mall-opts.
-mno-opts disables all the optional instructions that -mall-opts turned on ๐
-mrepeat Enables the "repeat" and "erepeat" instructions, used for low- overhead looping.
-mrepeat enables the "repeat" and "erepeat" instructions, which are used for low-overhead looping ๐ฆ
-ms Causes all variables to default to the ".tiny" section. Note that there is a 65536-byte limit to this section. Accesses to these variables use the %gp base register.
-ms makes all variables default to the ".tiny" section ๐ Heads up, bestie: this section has a 65536-byte limit โ ๏ธ and accesses to these variables use the %gp base register.
-msatur Enables the saturation instructions. Note that the compiler does not currently generate these itself, but this option is included for compatibility with other tools, like "as".
-msatur enables the saturation instructions โจ Note that the compiler doesn't currently generate these itself, but the option is included for compatibility with other tools, like "as" ๐ซถ
-msdram Link the SDRAM-based runtime instead of the default ROM-based runtime.
-msdram links the SDRAM-based runtime instead of the default ROM-based runtime ๐ธ
-msim Link the simulator run-time libraries.
-msim links the simulator run-time libraries ๐ง
-msimnovec Link the simulator runtime libraries, excluding built-in support for reset and exception vectors and tables.
-msimnovec links the simulator runtime libraries but leaves out the built-in support for reset and exception vectors and tables ๐
-mtf Causes all functions to default to the ".far" section. Without this option, functions default to the ".near" section.
-mtf makes all functions default to the ".far" section ๐ Without it, functions default to the ".near" section.
-mtiny=n Variables that are n bytes or smaller are allocated to the ".tiny" section. These variables use the $gp base register. The default for this option is 4, but note that there's a 65536-byte limit to the ".tiny" section.
-mtiny=n sends variables that are n bytes or smaller to the ".tiny" section, and they use the $gp base register ๐ The default is 4, but remember the 65536-byte limit on the ".tiny" section ๐
โจ MicroBlaze Options โจ
-msoft-float Use software emulation for floating point (default).
-msoft-float uses software emulation for floating point (this is the default) ๐
-mhard-float Use hardware floating-point instructions.
-mhard-float uses hardware floating-point instructions ๐ฅ
-mmemcpy Do not optimize block moves, use "memcpy".
-mmemcpy skips optimizing block moves and uses "memcpy" instead ๐ฆ
-mno-clearbss This option is deprecated. Use -fno-zero-initialized-in-bss instead.
-mno-clearbss is deprecated, so bestie, use -fno-zero-initialized-in-bss instead ๐ญ
-mcpu=cpu-type Use features of, and schedule code for, the given CPU. Supported values are in the format vX.YY.Z, where X is a major version, YY is the minor version, and Z is compatibility code. Example values are v3.00.a, v4.00.b, v5.00.a, v5.00.b, v6.00.a.
-mcpu=cpu-type uses the features of the given CPU and schedules code for it ๐ Supported values look like vX.YY.Z, where X is the major version, YY is the minor version, and Z is compatibility code. Example values: v3.00.a, v4.00.b, v5.00.a, v5.00.b, v6.00.a ๐ง
-mxl-soft-mul Use software multiply emulation (default).
-mxl-soft-mul uses software multiply emulation (default) ๐
-mxl-soft-div Use software emulation for divides (default).
-mxl-soft-div uses software emulation for divides (default) ๐ธ
-mxl-barrel-shift Use the hardware barrel shifter.
-mxl-barrel-shift uses the hardware barrel shifter โญ
-mxl-pattern-compare Use pattern compare instructions.
-mxl-pattern-compare uses pattern compare instructions ๐
-msmall-divides Use table lookup optimization for small signed integer divisions.
-msmall-divides uses table lookup optimization for small signed integer divisions ๐
-mxl-stack-check This option is deprecated. Use -fstack-check instead.
-mxl-stack-check is deprecated, so use -fstack-check instead ๐
-mxl-gp-opt Use GP-relative ".sdata"/".sbss" sections.
-mxl-gp-opt uses GP-relative ".sdata"/".sbss" sections ๐ฆ
-mxl-multiply-high Use multiply high instructions for high part of 32x32 multiply.
-mxl-multiply-high uses multiply high instructions for the high part of a 32x32 multiply ๐
-mxl-float-convert Use hardware floating-point conversion instructions.
-mxl-float-convert uses hardware floating-point conversion instructions ๐ง
-mxl-float-sqrt Use hardware floating-point square root instruction.
-mxl-float-sqrt uses the hardware floating-point square root instruction ๐
-mbig-endian Generate code for a big-endian target.
-mbig-endian generates code for a big-endian target ๐ซถ
-mlittle-endian Generate code for a little-endian target.
-mlittle-endian generates code for a little-endian target ๐
-mxl-reorder Use reorder instructions (swap and byte reversed load/store).
-mxl-reorder uses reorder instructions (swap and byte reversed load/store) ๐
-mxl-mode-app-model Select application model app-model. Valid models are
executable normal executable (default), uses startup code crt0.o.
xmdstub for use with Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent called xmdstub. This uses startup file crt1.o and sets the start address of the program to 0x800.
bootstrap for applications that are loaded using a bootloader. This model uses startup file crt2.o which does not contain a processor reset vector handler. This is suitable for transferring control on a processor reset to the bootloader rather than the application.
novectors for applications that do not require any of the MicroBlaze vectors. This option may be useful for applications running within a monitoring application. This model uses crt3.o as a startup file.
Option -xl-mode-app-model is a deprecated alias for -mxl-mode-app-model.
-mxl-mode-app-model selects the application model app-model. Valid models are:
executableโ normal executable (default), uses startup codecrt0.o๐ธxmdstubโ for use with the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent called xmdstub ๐ง This uses startup filecrt1.oand sets the start address of the program to0x800.bootstrapโ for applications that are loaded using a bootloader ๐ This model uses startup filecrt2.o, which does not contain a processor reset vector handler. It's suitable for transferring control on a processor reset to the bootloader rather than the application.novectorsโ for applications that don't need any of the MicroBlaze vectors ๐ฆ This option may be useful for applications running within a monitoring application. This model usescrt3.oas a startup file.
Option-xl-mode-app-modelis a deprecated alias for-mxl-mode-app-modelโ ๏ธ
-mpic-data-is-text-relative Assume that the displacement between the text and data segments is fixed at static link time. This allows data to be referenced by offset from start of text address instead of GOT since PC-relative addressing is not supported.
-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 the GOT, since PC-relative addressing isn't supported.
โจ MIPS Options โจ
-EB Generate big-endian code.
-EB generates big-endian code ๐
-EL Generate little-endian code. This is the default for mips*el-- configurations.
-EL generates little-endian code ๐ This is the default for mips*el-*-* configurations.
-march=arch Generate code that runs on arch, 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 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 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.
-march=arch generates code that runs on arch, which can be the name of a generic MIPS ISA or the name of a particular processor ๐ฆ
ISA names: mips1, mips2, mips3, mips4, mips32, mips32r2, mips32r3, mips32r5, mips32r6, mips64, mips64r2, mips64r3, mips64r5 and mips64r6.
Processor names: 4kc, 4km, 4kp, 4ksc, 4kec, 4kem, 4kep, 4ksd, 5kc, 5kf, 20kc, 24kc, 24kf2_1, 24kf1_1, 24kec, 24kef2_1, 24kef1_1, 34kc, 34kf2_1, 34kf1_1, 34kn, 74kc, 74kf2_1, 74kf1_1, 74kf3_2, 1004kc, 1004kf2_1, 1004kf1_1, i6400, i6500, interaptiv, loongson2e, loongson2f, loongson3a, gs464, gs464e, gs264e, m4k, m14k, m14kc, m14ke, m14kec, m5100, m5101, octeon, octeon+, octeon2, octeon3, orion, p5600, p6600, r2000, r3000, r3900, r4000, r4400, r4600, r4650, r4700, r5900, r6000, r8000, rm7000, rm9000, r10000, r12000, r14000, r16000, sb1, sr71000, vr4100, vr4111, vr4120, vr4130, vr4300, vr5000, vr5400, vr5500, xlr and xlp ๐
The special value from-abi picks the most compatible architecture for the selected ABI (that is, mips1 for 32-bit ABIs and mips3 for 64-bit ABIs) ๐
The native Linux/GNU toolchain also supports the value native, which picks the best architecture option for the host processor. -march=native has no effect if GCC doesn't recognize the processor ๐
In processor names, a final 000 can be abbreviated as k (for example, -march=r2k). Prefixes are optional, and vr may be written r โจ
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core, names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core, and names of the form nf3_2 refer to processors with FPUs clocked at a 3:2 ratio with respect to the core. For compatibility reasons, nf is accepted as a synonym for nf2_1, while nx and bfx are accepted as synonyms for nf1_1 ๐ง
GCC defines two macros based on the value of this option. The first is "_MIPS_ARCH", which gives the name of the target architecture as a string. The second has the form "_MIPS_ARCH_foo", where foo is the capitalized value of "_MIPS_ARCH". For example, -march=r2000 sets "_MIPS_ARCH" to "r2000" and defines the macro "_MIPS_ARCH_R2000" ๐
Note that the"_MIPS_ARCH"macro uses the processor names given above. In other words, it has the full prefix and does not abbreviate000ask. In the case offrom-abi, the macro names the resolved architecture (either"mips1"or"mips3"). It names the default architecture when no-marchoption is given. ๐
-mtune=arch Optimize for arch. Among other things, this option controls the way instructions are scheduled, and the perceived cost of arithmetic operations. The list of arch values is the same as for -march.
When this option is not used, GCC optimizes for the processor specified by -march. By using -march and -mtune together, it is possible to generate code that runs on a family of processors, but optimize the code for one particular member of that family.
-mtune defines the macros "_MIPS_TUNE" and "_MIPS_TUNE_foo", which work in the same way as the -march ones described above.
-mtune=arch optimizes for arch ๐ธ Among other things, it controls the way instructions are scheduled and the perceived cost of arithmetic operations. The list of arch values is the same as for -march.
When this option isn't used, GCC optimizes for the processor specified by -march. Using -march and -mtune together lets you generate code that runs on a family of processors, but optimize it for one particular member of that family ๐
-mtune defines the macros "_MIPS_TUNE" and "_MIPS_TUNE_foo", which work the same way as the -march ones described above ๐ง
-mips1 Equivalent to -march=mips1.
-mips1 is the same as -march=mips1 ๐
-mips2 Equivalent to -march=mips2.
-mips2 is the same as -march=mips2 ๐
-mips3 Equivalent to -march=mips3.
-mips3 is the same as -march=mips3 ๐
-mips4 Equivalent to -march=mips4.
-mips4 is the same as -march=mips4 ๐
-mips32 Equivalent to -march=mips32.
-mips32 is the same as -march=mips32 ๐
-mips32r3 Equivalent to -march=mips32r3.
-mips32r3 is the same as -march=mips32r3 ๐
-mips32r5 Equivalent to -march=mips32r5.
-mips32r5 is the same as -march=mips32r5 ๐
-mips32r6 Equivalent to -march=mips32r6.
-mips32r6 is the same as -march=mips32r6 ๐
-mips64 Equivalent to -march=mips64.
-mips64 is the same as -march=mips64 ๐
-mips64r2 Equivalent to -march=mips64r2.
-mips64r2 is the same as -march=mips64r2 ๐
-mips64r3 Equivalent to -march=mips64r3.
-mips64r3 is the same as -march=mips64r3 ๐
-mips64r5 Equivalent to -march=mips64r5.
-mips64r5 is the same as -march=mips64r5 ๐
-mips64r6 Equivalent to -march=mips64r6.
-mips64r6 is the same as -march=mips64r6 ๐
-mips16 -mno-mips16 Generate (do not generate) MIPS16 code. If GCC is targeting a MIPS32 or MIPS64 architecture, it makes use of the MIPS16e ASE.
MIPS16 code generation can also be controlled on a per-function basis by means of "mips16" and "nomips16" attributes.
-mips16 / -mno-mips16 generates (or doesn't generate) MIPS16 code ๐ฆ If GCC is targeting a MIPS32 or MIPS64 architecture, it makes use of the MIPS16e ASE.
MIPS16 code generation can also be controlled on a per-function basis using the "mips16" and "nomips16" attributes ๐
-mflip-mips16 Generate MIPS16 code on alternating functions. This option is provided for regression testing of mixed MIPS16/non-MIPS16 code generation, and is not intended for ordinary use in compiling user code.
-mflip-mips16 generates MIPS16 code on alternating functions ๐ It's there for regression testing of mixed MIPS16/non-MIPS16 code generation and is not intended for ordinary use in compiling user code.
-minterlink-compressed -mno-interlink-compressed Require (do not require) that code using the standard (uncompressed) MIPS ISA be link-compatible with MIPS16 and microMIPS code, and vice versa.
For example, code using the standard ISA encoding cannot jump directly to MIPS16 or microMIPS code; it must either use a call or an indirect jump. -minterlink-compressed therefore disables direct jumps unless GCC knows that the target of the jump is not compressed.
-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 vice versa ๐ซถ
For example, code using the standard ISA encoding can't jump directly to MIPS16 or microMIPS code; it has to use a call or an indirect jump. -minterlink-compressed therefore disables direct jumps unless GCC knows that the target of the jump isn't compressed ๐
-minterlink-mips16 -mno-interlink-mips16 Aliases of -minterlink-compressed and -mno-interlink-compressed. These options predate the microMIPS ASE and are retained for backwards compatibility.
-minterlink-mips16 / -mno-interlink-mips16 are aliases of -minterlink-compressed and -mno-interlink-compressed ๐ These options predate the microMIPS ASE and are kept for backwards compatibility.
-mabi=32 -mabi=o64 -mabi=n32 -mabi=64 -mabi=eabi Generate code for the given ABI.
Note that the EABI has a 32-bit and a 64-bit variant. GCC normally generates 64-bit code when you select a 64-bit architecture, but you can use -mgp32 to get 32-bit code instead.
For information about the O64 ABI, see <https://gcc.gnu.org/projects/mipso64-abi.html>.
-mabi=32, -mabi=o64, -mabi=n32, -mabi=64 and -mabi=eabi generate code for the given ABI โจ
Note that the EABI has a 32-bit and a 64-bit variant. GCC normally generates 64-bit code when you select a 64-bit architecture, but you can use -mgp32 to get 32-bit code instead ๐
For information about the O64 ABI, see https://gcc.gnu.org/projects/mipso64-abi.html ๐ฆ
okay so GCC has this spicy variant of the o32 ABI where the floating-point registers are 64 bits wide instead of 32 ๐ฆ You pick it with -mabi=32 -mfp64, and honestly it's giving upgrade. BUT it leans on the mthc1 and mfhc1 instructions, so it's only a thing on MIPS32R2, MIPS32R3 and MIPS32R5 processors. ๐
The register assignments for arguments and return values stay exactly the same โจ The only glow-up is that each scalar value gets squished into one 64-bit register instead of a pair of 32-bit ones. Like, scalar floating-point values come back in $f0 only, not a $f0/$f1 pair. The call-saved set is also unchanged, so the even-numbered double-precision registers still get saved. ๐ซถ
There are two more o32 variants for the transition era from 32-bit to 64-bit registers ๐ They're FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg). FPXX is mandatory vibes: all code has to run correctly with 32-bit or 64-bit registers. It can be interlinked with FP32 or FP64, but not both, so no mixing, periodt. FP64A is similar to FP64 but it forbids odd-numbered single-precision registers. It can be used with the "FRE" mode of FPUs in MIPS32R5 processors, and that lets FP32 and FP64A code interlink and run in the same process without changing FPU modes. Iconic ๐
-mabicalls,-mno-abicallsโ generate (or don't generate) code that's suitable for 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, regardless of options like -fPIC and -fpic. However, 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. This mode is 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. However, it doesn't affect the ABI of the final executable; it only affects 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 option only affects-mno-shared -mabicalls. For the n64 ABI, this option has no effect 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 relatively efficient, but it only works if the GOT is smaller than about 64k. Anything larger 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, although the code is less efficient, since it takes three instructions to fetch the value of a global symbol. ๐
Note that 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 do.
These options have no effect unless GCC is generating position independent code.
-mgp32โ assume general-purpose registers are 32 bits wide.-mgp64โ assume general-purpose registers are 64 bits wide.-mfp32โ assume floating-point registers are 32 bits wide.-mfp64โ assume floating-point registers are 64 bits wide.-mfpxxโ don't assume a width for floating-point registers at all. ๐-mhard-floatโ use floating-point coprocessor instructions. ๐ฅ-msoft-floatโ don't use floating-point coprocessor instructions. Do floating-point math with library calls instead.-mno-floatโ same as-msoft-float, but it also asserts that the program being compiled doesn't do any floating-point operations at all. Right now this is only supported by some bare-metal MIPS configurations, where it may pick a special set of libraries that lack all floating-point support (including, for example, the floating-point "printf" formats). โ ๏ธ Watch out: if code compiled with-mno-floataccidentally contains floating-point operations, it's likely to hit a link-time or run-time failure. ๐-msingle-floatโ assume the floating-point coprocessor only supports single-precision operations.-mdouble-floatโ assume the floating-point coprocessor supports double-precision operations. This is the default. ๐-modd-spreg,-mno-odd-spregโ enable (or don't enable) the use of odd-numbered single-precision floating-point registers for the o32 ABI. This is the default for processors that are known to support these registers. When using the o32 FPXX ABI,-mno-odd-spregis set by default.-mabs=2008,-mabs=legacyโ control how the special not-a-number (NaN) IEEE 754 floating-point data gets treated by the "abs.fmt" and "neg.fmt" machine instructions. ๐ซง
By default, or when -mabs=legacy is used, the legacy treatment is selected. In this case these instructions count as arithmetic, so they're avoided wherever correct operation is required and the input operand might be a NaN. A longer sequence of instructions that manipulates the sign bit of the floating-point datum manually is used instead, unless the -ffinite-math-only option has also been specified.
The -mabs=2008 option selects the IEEE 754-2008 treatment. In this case these instructions count as non-arithmetic, so they operate correctly in all cases, including where the input operand is a NaN. These instructions are therefore always used for the respective operations.
-mnan=2008,-mnan=legacyโ control the encoding of the special not-a-number (NaN) IEEE 754 floating-point data. ๐ฆ
-mnan=legacy selects the legacy encoding. Here, quiet NaNs (qNaNs) are denoted by the first bit of their trailing significand field being 0, whereas signaling NaNs (sNaNs) are denoted by the first bit of their trailing significand field being 1.
-mnan=2008 selects the IEEE 754-2008 encoding. In this case qNaNs are denoted by the first bit of their trailing significand field being 1, whereas sNaNs are denoted by the first bit of their trailing significand field being 0.
The default is -mnan=legacy unless GCC has been configured with --with-nan=2008.
-mllsc,-mno-llscโ use (or don't use)ll,sc, andsyncinstructions to implement atomic memory built-in functions. When neither option is specified, GCC uses the instructions if the target architecture supports them. ๐
-mllsc is useful if the runtime environment can emulate the instructions, and -mno-llsc can be useful when compiling for nonstandard ISAs. You can make either option the default by configuring GCC with --with-llsc and --without-llsc respectively. --with-llsc is the default for some configurations, so check the installation documentation for details.
-mdsp,-mno-dspโ use (or don't use) revision 1 of the MIPS DSP ASE. This option defines the preprocessor macro__mips_dsp, and it also defines__mips_dsp_revto 1. โจ-mdspr2,-mno-dspr2โ use (or don't use) revision 2 of the MIPS DSP ASE. This option defines the preprocessor macros__mips_dspand__mips_dspr2, and it also defines__mips_dsp_revto 2. โจ-msmartmips,-mno-smartmipsโ use (or don't use) the MIPS SmartMIPS ASE. ๐-mpaired-single,-mno-paired-singleโ use (or don't use) paired-single floating-point instructions. This option requires hardware floating-point support to be enabled. ๐ฅ-mdmx,-mno-mdmxโ use (or don't use) MIPS Digital Media Extension instructions. This option can only be used when generating 64-bit code, and it requires hardware floating-point support to be enabled. ๐-mips3d,-mno-mips3dโ use (or don't use) the MIPS-3D ASE. The option-mips3dimplies-mpaired-single. ๐ธ-mmicromips,-mno-micromipsโ generate (or don't generate) microMIPS code.
microMIPS code generation can also be controlled on a per-function basis by means of "micromips" and "nomicromips" attributes. ๐ง
-mmt,-mno-mtโ use (or don't use) MT Multithreading instructions. ๐งต-mmcu,-mno-mcuโ use (or don't use) the MIPS MCU ASE instructions. ๐ฆ-meva,-mno-evaโ use (or don't use) the MIPS Enhanced Virtual Addressing instructions. ๐-mvirt,-mno-virtโ use (or don't use) the MIPS Virtualization (VZ) instructions. ๐ซถ-mxpa,-mno-xpaโ use (or don't use) the MIPS eXtended Physical Address (XPA) instructions. ๐-mcrc,-mno-crcโ use (or don't use) the MIPS Cyclic Redundancy Check (CRC) instructions. โจ-mginv,-mno-ginvโ use (or don't use) the MIPS Global INValidate (GINV) instructions. ๐-mloongson-mmi,-mno-loongson-mmiโ use (or don't use) the MIPS Loongson MultiMedia extensions Instructions (MMI). ๐-mloongson-ext,-mno-loongson-extโ use (or don't use) the MIPS Loongson EXTensions (EXT) instructions. ๐-mloongson-ext2,-mno-loongson-ext2โ use (or don't use) the MIPS Loongson EXTensions r2 (EXT2) instructions. ๐-mlong64โ force "long" types to be 64 bits wide. See-mlong32for an explanation of the default and the way the pointer size is determined. ๐-mlong32โ force "long", "int", and pointer types to be 32 bits wide. ๐
The default size of "int"s, "long"s and pointers depends on the ABI. All the supported ABIs use 32-bit "int"s. The n64 ABI uses 64-bit "long"s, as does the 64-bit EABI, and the others use 32-bit "long"s. Pointers are the same size as "long"s, or the same size as integer registers, whichever is smaller. main character energy, honestly ๐
-msym32,-mno-sym32โ okay so this one decides whether GCC just assumes every symbol has a 32-bit value, no matter which ABI you picked ๐-msym32makes that assumption and-mno-sym32doesn't. It's giving main character energy with-mabi=64and-mno-abicallsbecause GCC can then make shorter, faster references to symbolic addresses โจ-G numโ put externally-visible data in a small data section ๐ as long as that data is no bigger than num bytes. GCC can then access the data more efficiently, and-mgpopthas all the juicy details ๐ง
The default -G value depends on your configuration, so check what your setup is using ๐ธ
-mlocal-sdata,-mno-local-sdataโ extend (or don't extend) the-Gbehaviour to local data too, like static variables in C ๐ฆ-mlocal-sdatais the default for all configurations.
If the linker is yelling that an application is using too much small data, try rebuilding the less performance-critical parts with -mno-local-sdata ๐ญ You might also want to build large libraries with -mno-local-sdata so they leave more room for the main program ๐ซถ
-mextern-sdata,-mno-extern-sdataโ assume (or don't assume) that externally-defined data lives in a small data section, as long as its size is within the-Glimit ๐-mextern-sdatais the default for all configurations.
Bestie, listen up ๐ 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 Var is placed in a small data section. If Var is defined by another module, you either need to compile that module with a high-enough -G setting or attach a "section" attribute to Var's definition. If Var is common, you have to link the application with a high-enough -G setting โ ๏ธ
The easiest way to keep the vibes consistent is to compile and link every module with the same -G option ๐ But if you want a library that supports several different small data limits, compile it with the highest supported -G setting and also use -mno-extern-sdata so the library stops making assumptions about externally-defined data ๐
-mgpopt,-mno-gpoptโ use (or don't use) GP-relative accesses for symbols that are known to be in a small data section ๐ See-G,-mlocal-sdataand-mextern-sdata.-mgpoptis the default for all configurations.
-mno-gpopt is useful when the $gp register might not hold the value of "_gp" ๐ฅบ For example, if your code is part of a library that might get used in a boot monitor, programs that call boot monitor routines pass an unknown value in $gp. (In those situations, the boot monitor itself is usually compiled with -G0.)
-mno-gpopt implies -mno-local-sdata and -mno-extern-sdata ๐
-membedded-data,-mno-embedded-dataโ allocate variables to the read-only data section first if possible, then the small data section if possible, and otherwise to data ๐ฆ It gives slightly slower code than the default, but uses less RAM while executing, so it might be the move 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 alongside-membedded-data.-mcode-readable=settingโ specify whether GCC is allowed to generate code that reads from executable sections ๐ง There are three possible settings, and they're all very different:-mcode-readable=yesโ instructions can freely access executable sections ๐ This is the default setting.-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must not do so ๐ This option is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It's also useful on processors that can be configured to have a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM.-mcode-readable=noโ instructions must not access executable sections ๐ This can be useful on targets configured with a dual instruction/data SRAM interface that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM.
-msplit-addresses,-mno-split-addressesโ enable (or disable) use of the%hi()and%lo()assembler relocation operators ๐ฐ๏ธ This option has been superseded by-mexplicit-relocsbut is kept around for backwards compatibility.-mexplicit-relocs,-mno-explicit-relocsโ use (or don't use) assembler relocation operators when dealing with symbolic addresses ๐ The alternative, selected by-mno-explicit-relocs, is to use assembler macros instead.
-mexplicit-relocs is the default if GCC was configured to use an assembler that supports relocation operators โจ
-mcheck-zero-division,-mno-check-zero-divisionโ trap (or don't trap) on integer division by zero ๐ฅ The default is-mcheck-zero-division.-mdivide-traps,-mdivide-breaksโ MIPS systems check for division by zero by generating either a conditional trap or a break instruction ๐ Traps give you smaller code, but they're only supported on MIPS II and later. Also, some versions of the Linux kernel have a bug that stops trap from generating the proper signal ("SIGFPE") ๐ญ Use-mdivide-trapsto allow conditional traps on architectures that support them, and-mdivide-breaksto force the use of breaks.
The default is usually -mdivide-traps, but you can override that at configure time with --with-divide=breaks ๐ Divide-by-zero checks can be completely disabled using -mno-check-zero-division.
-mload-store-pairs,-mno-load-store-pairsโ enable (or disable) an optimization that pairs consecutive load or store instructions to enable load/store bonding ๐ซถ This option is enabled by default, but it only takes effect when the selected architecture is known to support bonding.-munaligned-access,-mno-unaligned-accessโ enable (or disable) direct unaligned access for MIPS Release 6 ๐ฆ MIPSr6 requires load/store unaligned-access support, either by hardware or by trap&emulate. So-mno-unaligned-accessmay be needed by the kernel ๐-mmemcpy,-mno-memcpyโ force (or don't force) the use ofmemcpyfor non-trivial block moves ๐ The default is-mno-memcpy, which lets GCC inline most constant-sized copies.-mlong-calls,-mno-long-callsโ disable (or don't disable) use of thejalinstruction ๐ธ Calling functions withjalis more efficient, but it requires the caller and callee to be in the same 256 megabyte segment.
This option has no effect on abicalls code ๐
The default is -mno-long-calls.
-mmad,-mno-madโ enable (or disable) use of themad,maduandmulinstructions, as provided by the R4650 ISA โจ-mimadd,-mno-imaddโ enable (or disable) use of themaddandmsubinteger instructions ๐ง The default is-mimaddon architectures that supportmaddandmsub, except for the 74k architecture, where it was found to generate slower code ๐-mfused-madd,-mno-fused-maddโ enable (or disable) use of the floating-point multiply-accumulate instructions, when they're available ๐ฅ The default is-mfused-madd.
On the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product is calculated to infinite precision and is not subject to the FCSR Flush to Zero bit ๐ That might 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โ tell the MIPS assembler to not run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐-mfix-24k,-mno-fix-24kโ work around the 24K E48 (lost data on stores during refill) errata ๐ ๏ธ The workarounds are implemented by the assembler rather than by GCC, so don't blame GCC for it ๐ญ-mfix-r4000,-mno-fix-r4000โ work 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โ work 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โ work around certain R10000 errata ๐ll/scsequences may not behave atomically on revisions prior to 3.0. They may deadlock on revisions 2.6 and earlier.
This option can only be used if the target architecture supports branch-likely instructions ๐ -mfix-r10000 is the default when -march=r10000 is used, and -mno-fix-r10000 is the default otherwise.
-mfix-r5900,-mno-fix-r5900โ do not attempt to schedule the preceding instruction into the delay slot of a branch instruction placed at the end of a short loop of six instructions or fewer. Instead, always schedule anopinstruction there ๐ง The short loop bug can, under certain conditions, make loops execute only once or twice, thanks to a hardware bug in the R5900 chip ๐ญ The workaround is implemented by the assembler rather than by GCC.-mfix-rm7000,-mno-fix-rm7000โ work around the RM7000dmult/dmultuerrata ๐ธ The workarounds are implemented by the assembler rather than by GCC.-mfix-vr4120,-mno-fix-vr4120โ work 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 the mips64vr*-elf configurations โจ
Other VR4120 errata require a NOP to be inserted between certain pairs of instructions ๐ซถ These errata are handled by the assembler, not by GCC itself.
-mfix-vr4130โ okay so this one is a VR4130 errata fix ๐ง It works around themflo/mfhibug, but the actual workarounds are done by the assembler, not GCC ๐ GCC is lowkey smart though, and it avoidsmfloandmfhialtogether when the VR4130macc,macchi,dmaccanddmacchiinstructions are available instead โจ-mfix-sb1,-mno-fix-sb1โ bestie, this one works around certain SB-1 CPU core errata ๐ธ Right now it only handles the SB-1 revision 2F1andF2floating-point errata.-mr10k-cache-barrier=settingโ this one is giving very deep processor drama ๐ฆ It decides whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors.
The R10K is like many other processors. It tries to guess how a conditional branch will go and starts running instructions from the "taken" branch ahead of time. If the guess was wrong, it throws those instructions away. The problem is that on the R10K, even the thrown-away instructions can leave side effects behind ๐ญ
This only really affects kernel stores and, depending on the system, kernel loads. For example, a store that gets speculated might pull the target memory into cache and mark that cache line as dirty, even if the store is later aborted. If a DMA operation writes to that same memory before the dirty line gets flushed, the cached data overwrites the DMA-ed data. The R10K processor manual has the full scoop, including other potential problems ๐
One workaround is to insert cache barrier instructions before every memory access that might get speculatively executed and that might have side effects even if it's aborted. -mr10k-cache-barrier=setting controls how GCC does this. It assumes that aborted accesses to any byte in the following regions have no side effects:
- the memory occupied by the current function's stack frame;
- the memory occupied by an incoming stack argument;
- the memory occupied by an object with a link-time-constant address.
Making sure speculative accesses to these regions are actually safe is the kernel's job, not GCC's ๐ซถ
If your input program has a function declaration like this:
void foo (void);
then the implementation of foo has to let j foo and jal foo run speculatively. GCC follows this rule for functions it compiles itself, and it expects non-GCC functions (like hand-written assembly) to do the same ๐
The option comes in three forms:
-mr10k-cache-barrier=load-storeโ inserts a cache barrier before a load or store that might be speculatively executed and that might have side effects even if aborted.-mr10k-cache-barrier=storeโ inserts a cache barrier before a store that might be speculatively executed and that might have side effects even if aborted.-mr10k-cache-barrier=noneโ disables the insertion of cache barriers. This is the default setting ๐-mflush-func=func,-mno-flush-funcโ picks the function GCC calls to flush the I and D caches, or tells it to not call any flush function at all โจ If you do call one, it has to take the same arguments as the common_flush_func: the address of the memory range being flushed, the size of that range, and the number 3 (to flush both caches). The default depends on what target GCC was configured for, but it's commonly either_flush_funcor__cpu_flush.mbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions ๐ง This cost is only a heuristic, so don't count on it giving the same results across releases. A zero cost just 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, they may be generated if the selected architecture supports them. The one exception is the MIPS32 and MIPS64 architectures, plus processors that implement them. For those, Branch Likely instructions are not generated by default, because those architectures specifically deprecate their use ๐-mcompact-branches=never,-mcompact-branches=optimal,-mcompact-branches=alwaysโ these options control which form of branches gets generated. The default is-mcompact-branches=optimal.-mcompact-branches=neverโ makes sure compact branch instructions are never generated.-mcompact-branches=alwaysโ makes sure a compact branch instruction is generated if one is available. If it isn't, a delay slot form of the branch gets used instead.
This option is supported from MIPS Release 6 onwards.
-mcompact-branches=optimalโ uses a delay slot branch if one is available in the current ISA and the delay slot gets successfully filled. If the delay slot isn't filled, a compact branch gets chosen instead, as long as one is available ๐
-mfp-exceptions,-mno-fp-exceptionsโ specifies whether FP exceptions are enabled. This affects how FP instructions get scheduled on some processors. The default is that FP exceptions are enabled ๐ฅ
For example, on the SB-1, if FP exceptions are disabled and we're emitting 64-bit code, 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 is enabled, GCC aligns pairs of instructions that it thinks should execute in parallel ๐ฆ
This only does anything when you're optimizing for the VR4130. It usually makes code faster, but the trade-off is that the code gets bigger. It's enabled by default at optimization level -O3.
-msynci,-mno-synciโ enables (or disables) generation ofsynciinstructions on architectures that support them. If enabled, thesynciinstructions get generated when__builtin___clear_cacheis compiled. This option defaults to-mno-synci, but you can override that default by configuring GCC with--with-synciโจ
When compiling for single processor systems, it's generally safe to use synci.
Heads up, bestie ๐จ On many multi-core (SMP) systems, synci doesn't invalidate the instruction caches on all cores, and it may lead to undefined behavior. ๐
-mrelax-pic-calls,-mno-relax-pic-callsโ tries to turn PIC calls that normally go through register$25into direct calls ๐ This only works if the linker can resolve the destination at link time and the destination is within range for a direct call.
-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, this optimization can be done by the assembler and the linker alone, without any help from the compiler.
-mmcount-ra-address,-mno-mcount-ra-addressโ emits (or doesn't emit) code that lets_mcountmodify the calling function's return address ๐ When enabled, this option extends the usual_mcountinterface with a new ra-address parameter. It has typeintptr_t *and gets passed in register$12._mcountcan then change the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in
*ra-address, if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address.
-mframe-header-opt,-mno-frame-header-optโ enables (or disables) frame header optimization in the o32 ABI ๐ง With the o32 ABI, calling functions allocate 16 bytes on the stack for the called function to write out register arguments. When this is enabled, the optimization skips allocating the frame header if it can be determined that it's unused.
This optimization is off by default at all optimization levels.
-mlxc1-sxc1,-mno-lxc1-sxc1โ when applicable, enables (or disables) generation of thelwxc1,swxc1,ldxc1andsdxc1instructions. Enabled by default ๐-mmadd4,-mno-madd4โ when applicable, enables (or disables) generation of 4-operandmadd.s,madd.dand related instructions. Enabled by default ๐ธ
โจ MMIX Options โจ
These options are defined for the MMIX ๐ง
-mlibfuncs,-mno-libfuncsโ specifies that intrinsic library functions are being compiled, with all values passed in registers no matter the size ๐ฅ-mepsilon,-mno-epsilonโ generates floating-point comparison instructions that compare with respect to therEepsilon register ๐ฆ-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code that passes function parameters and return values which, in the called function, are seen as registers$0and up. The GNU ABI, by contrast, uses global registers$231and up ๐-mzero-extend,-mno-zero-extendโ when reading data from memory in sizes shorter than 64 bits, this uses (or doesn't use) zero-extending load instructions by default, instead of sign-extending ones ๐-mknuthdiv,-mno-knuthdivโ makes the result of a division that yields a remainder have the same sign as the divisor. With the default,-mno-knuthdiv, the sign of the remainder follows the sign of the dividend. Both methods are arithmetically valid, though the latter is almost exclusively used ๐-mtoplevel-symbols,-mno-toplevel-symbolsโ prepends (or doesn't prepend) a:to all global symbols, so the assembly code can be used with thePREFIXassembly directive ๐ซถ-melfโ generates an executable in the ELF format, instead of the default mmo format used by the mmix simulator ๐-mbranch-predict,-mno-branch-predictโ uses (or doesn't use) the probable-branch instructions when static branch prediction indicates a probable branch โญ-mbase-addresses,-mno-base-addressesโ okay so these two decide whether the compiler generates code that uses base addresses ๐. Using one auto-generates a request (the assembler and linker handle it) to set up a constant in a global register โจ. That register then serves one or more base address requests within the range0to255from the value it holds ๐ฆ. This usually gives you short and fast code, but ngl there's a catch: the number of different data items you can address is limited ๐ญ. So if your program has tons of static data, you may need-mno-base-addresses๐ซถ.-msingle-exit,-mno-single-exitโ force (or don't force) the generated code to have one single exit point in each function ๐.
๐ MN10300 Options ๐
These -m options are defined for Matsushita MN10300 architectures ๐ธ.
-mmult-bugโ generate code that dodges bugs in the multiply instructions for MN10300 processors. This is the default ๐ .-mno-mult-bugโ don't generate that bug-dodging code for the MN10300 multiply instructions.-mam33โ generate code using features specific to the AM33 processor ๐ฅ.-mno-am33โ don't generate code using AM33-specific features. This is the default.-mam33-2โ generate code using features specific to the AM33/2.0 processor โจ.-mam34โ generate code using features specific to the AM34 processor ๐ฆ.-mtune=cpu-typeโ schedule instructions using the timing characteristics of the CPU type you pick ๐ง. This does not change the targeted processor type, so it's just timing vibes. The CPU type must be one ofmn10300,am33,am33-2oram34๐.-mreturn-pointer-on-d0โ when generating a function that returns a pointer, return it in both"a0"and"d0"๐. Otherwise the pointer only comes back in"a0", and trying to call those functions without a prototype throws errors ๐. This option is on by default, but you can turn it off with-mno-return-pointer-on-d0๐.-mno-crt0โ don't link in the C run-time initialization object file ๐.-mrelaxโ tells the linker to run a relaxation pass that shortens branches, calls and absolute memory addresses โญ. It only does anything when it's on the command line for the final link step.
This option makes symbolic debugging impossible ๐ญ. Proceed with caution, bestie.
-mliwโ allow the compiler to generate Long Instruction Word instructions if the target is AM33 or later ๐. This is the default, and it defines the preprocessor macro"__LIW__"๐ซถ.-mno-liwโ don't let the compiler generate Long Instruction Word instructions. This defines the preprocessor macro"__NO_LIW__"๐.-msetlbโ allow the compiler to generate the SETLB and Lcc instructions if the target is AM33 or later ๐. This is the default, and it defines the preprocessor macro"__SETLB__"โจ.-mno-setlbโ no SETLB or Lcc instructions for you ๐ซ. This defines the preprocessor macro"__NO_SETLB__"๐ธ.
๐ฆ Moxie Options ๐ฆ
-mebโ generate big-endian code. This is the default formoxie-*-*configurations ๐ .-melโ generate little-endian code ๐.-mmul.xโ generatemul.xandumul.xinstructions. This is the default formoxiebox-*-*configurations ๐ฅ.-mno-crt0โ don't link in the C run-time initialization object file ๐ง.
๐ MSP430 Options ๐
These options are defined for the MSP430 ๐.
-masm-hexโ force assembly output to always use hex constants ๐. Normally they're signed decimals, but this one is there for testsuite and/or aesthetic purposes ๐ .-mmcu=โ pick the MCU you're targeting ๐ฏ. GCC uses the MCU name, uppercased and wrapped in__on both sides, to create a C preprocessor symbol. Themsp430.hheader then uses that symbol to choose an MCU-specific supplementary header file ๐ซถ.
This option also picks the ISA. If the MCU only supports the 430 ISA, that's what gets selected. Otherwise you get the 430X ISA โจ. The generic MCU name msp430 selects the 430 ISA, and the generic msp430x selects the 430X ISA ๐ฆ.
An MCU-specific linker script also gets added to the linker command line. Its name is the MCU name with .ld tacked on, so -mmcu=xxx defines the C preprocessor symbol "__XXX__" and makes the linker look for a script called xxx.ld ๐ธ.
The ISA and hardware multiply support for each MCU are hard-coded into GCC ๐ง . But if you want more device support, you can extend it with an external devices.csv file ๐.
GCC looks for devices.csv using the methods below, in this order of precedence. The first method beats the second, and the second beats the third ๐.
- Include path specified with
-Iand-Lโdevices.csvgets searched for in each directory listed as an include path or a linker library search path ๐. - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIRโ set this global environment variable to the full path of the directory that containsdevices.csv, and GCC will search there ๐. If it finds the file, that directory also gets registered as an include path and a linker library path. That means header files and linker scripts in there work without manually specifying-Iand-Lon the command line โจ. - The
msp430-elf{,bare}/include/devicesdirectory โ finally, GCC checksmsp430-elf{,bare}/include/devicesunder the toolchain root directory ๐ง. This one doesn't exist in a default installation. But if you've made it yourself and copieddevices.csvin there, the MCU data gets read โญ. Like before, this directory also gets registered as an include path and a linker library path ๐ซถ.
If none of those search methods find devices.csv, the hard-coded MCU data is used ๐
.
-mwarn-mcu,-mno-warn-mcuโ turn warnings on or off for conflicts between the MCU name from-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 ๐ธ.-mcpu=โ specifies the ISA to use. The accepted values aremsp430,msp430xandmsp430xv2๐.
This option is deprecated ๐. Use -mmcu= to select the ISA instead, bestie.
-msimโ links to the simulator runtime libraries and linker script ๐ฎ. It overrides any scripts that-mmcu=would have selected ๐.-mlargeโ use large-model addressing, with 20-bit pointers and a 20-bit"size_t"๐.-msmallโ use small-model addressing, with 16-bit pointers and a 16-bit"size_t"๐ฆ.-mrelaxโ this gets passed to the assembler and linker, letting the linker do certain optimizations that can't happen until the final link โญ.mhwmult=โ describes the type of hardware multiply the target supports ๐ฅ. The accepted values are:nonefor no hardware multiply at all.16bitfor the original 16-bit-only multiply that early MCUs had.32bitfor the 16/32-bit multiply that later MCUs have.f5seriesfor the 16/32-bit multiply on F5-series MCUs.autotells GCC to figure out the hardware multiply support from the MCU name you gave to-mmcu. If there's no-mmcu, or the MCU name isn't recognized, no hardware multiply support is assumed ๐ง .
auto is the default setting ๐.
Hardware multiplies usually happen by calling a library routine, which saves space in your code ๐ซถ. But when you compile at -O3 or higher, the hardware multiplier gets invoked inline ๐. That makes the code bigger, but faster ๐
.
The hardware multiply routines turn off interrupts while they run and restore the previous interrupt state when they finish ๐ก๏ธ. That makes them safe to use inside interrupt handlers as well as in normal code โจ.
-minrtโ enables a minimum runtime environment, with no static initializers or constructors ๐งธ. This one is for memory-constrained devices. The compiler includes special symbols in some objects that tell the linker and runtime which code fragments are required ๐.-mtiny-printfโ enables reduced code size"printf"and"puts"library functions ๐ฆ. The tiny versions aren't reentrant, so be careful using them in multi-threaded applications ๐ฌ.
Stream support has been removed. The string to print always goes to stdout through the "write" syscall, and it isn't buffered before it's sent to write ๐.
This option requires Newlib Nano IO, so GCC must be configured with --enable-newlib-nano-formatted-io ๐ ๏ธ.
-mmax-inline-shift=โ takes an integer from 0 to 64 inclusive, and sets the maximum number of inline shift instructions that should be emitted to shift by a constant amount ๐ข. Once that limit would be exceeded, an mspabi helper function gets used instead. The default value is4๐ .
This only matters when a shift by multiple positions can't be done with one instruction, like all shifts over 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=,-mdata-region=โ these tell the compiler where to place functions and data that don't have a"lower","upper","either"or"section"attribute ๐. The possible values are"lower","upper","either"or"any". The first three behave like the matching attribute. The fourth one,"any", is the default, and it leaves placement entirely up to the linker script and how it assigns the standard sections (".text",".data", etc) to memory regions ๐บ๏ธ.-msilicon-errata=โ passes a request to the assembler to enable the fixes for the named silicon errata ๐โจ.-msilicon-errata-warn=โ okay so this one tells the assembler to start raising its hand ๐ with warnings whenever a silicon errata might need to be applied. Main character assembler behavior ๐-mwarn-devices-csv,-mno-warn-devices-csvโ this pair controls whether you get a heads-up ifdevices.csvis missing or if there's trouble parsing it. It's on by default ๐ซถ
โจ NDS32 Options โจ
okay bestie, these are defined for NDS32 implementations ๐ฆ
-mbig-endianโ generate code in big-endian mode ๐ธ-mlittle-endianโ generate code in little-endian mode ๐-mreduced-regsโ use the reduced-set registers when doing register allocation ๐ง-mfull-regsโ use the full-set registers for register allocation instead ๐-mcmovโ generate conditional move instructions โจ-mno-cmovโ nope, do not generate conditional move instructions ๐ โโ๏ธ-mext-perfโ generate performance extension instructions ๐ฅ-mno-ext-perfโ do not generate performance extension instructions ๐-mext-perf2โ generate performance extension 2 instructions ๐ฅ-mno-ext-perf2โ do not generate performance extension 2 instructions ๐-mext-stringโ generate string extension instructions ๐-mno-ext-stringโ do not generate string extension instructions ๐-mv3pushโ generate v3push25/pop25instructions ๐ฆ-mno-v3pushโ do not generate v3push25/pop25instructions ๐-m16-bitโ generate 16-bit instructions ๐-mno-16-bitโ do not generate 16-bit instructions ๐ญ-misr-vector-size=numโ set the size of each interrupt vector. It has to be4or16, no other vibes allowed ๐ธ-mcache-block-size=numโ set the size of each cache block. It must be a power of 2 between4and512๐ง-march=archโ specify the name of the target architecture ๐-mcmodel=code-modelโ sets the code model to one of the following ๐smallโ all the data and read-only data segments must be within512KBof addressing space. The text segment must be within16MBof addressing space ๐mediumโ the data segment must be within512KB, while the read-only data segment can be within4GBof addressing space. The text segment should still be within16MBof addressing space ๐ฆlargeโ all the text and data segments can be within4GBof addressing space ๐
-mctor-dtorโ enable 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โ put global and static objects that are less than or equal tonumbytes into the small data or BSS sections, instead of the normal data or BSS sections. The default value ofnumis8๐-mgpopt=option,-mgpopt,-mno-gpoptโ this controls whether GP-relative accesses get generated (or not). These option names are recognized ๐งnoneโ do not generate GP-relative accesses ๐ โโ๏ธlocalโ generate GP-relative accesses for small data objects that are not external, weak, or uninitialized common symbols. GP-relative addressing is also used for objects that have been explicitly placed in a small data section via a"section"attribute ๐globalโ same aslocal, but it 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โ generate 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 in64Kof memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer ๐allโ generate 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 in64Kof 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 except when -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 ๐ซถ
โ ๏ธ bestie, you may need to specify -mno-gpopt explicitly when building programs that include large amounts of small data, including large GOT data sections. In that case, the 16-bit offset for GP-relative addressing might not be big enough to reach the entire small data section ๐ญ
-mgprel-sec=regexpโ this option specifies additional section names that can be accessed via GP-relative addressing. It's most useful alongside"section"attributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression ๐ฆ
This option does not 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โ this option names 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 alongside"section"attributes 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. There are also no conventional section names used in standard linker scripts for sections in the low or high areas of memory ๐ง
-mel,-mebโ generate little-endian (the default) or big-endian (experimental) code, respectively ๐-march=archโ this specifies the name of the target Nios II architecture. GCC uses this name to figure out what kinds of instructions it can emit when generating assembly code. Permissible names are:r1,r2๐
The preprocessor macro "__nios2_arch__" is available to programs, with value 1 or 2, indicating the targeted ISA level ๐ค
-mbypass-cache,-mno-bypass-cacheโ forces all load and store instructions to always bypass the cache by using the I/O variants of the instructions. The default is not to bypass the cache ๐-mno-cache-volatile,-mcache-volatileโ volatile memory accesses bypass the cache using the I/O variants of the load and store instructions. The default is not to bypass the cache ๐-mno-fast-sw-div,-mfast-sw-divโ do not use 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,-mhw-divโ enable or disable the compiler emitting themul,mulx, anddivfamilies of instructions. The default is to emitmuland not emitdivormulx๐-mbmx,-mno-bmx,-mcdx,-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โ each-mcustom-insn=Noption enables use of a custom instruction with encodingNwhen generating code that usesinsn. For example,-mcustom-fadds=253generates custom instruction253for single-precision floating-point add operations, instead of the default behavior of using a library call ๐ง
The following values of insn are supported. Except as otherwise noted, floating-point operations are expected to be implemented with normal IEEE 754 semantics and to correspond directly to the C operators or the equivalent GCC built-in functions ๐ค
Single-precision floating point:
fadds,fsubs,fdivs,fmulsโ binary arithmetic operations ๐ฅfnegsโ unary negation ๐fabssโ unary absolute value ๐fcmpeqs,fcmpges,fcmpgts,fcmples,fcmplts,fcmpnesโ comparison operations ๐fmins,fmaxsโ floating-point minimum and maximum. These instructions are only generated if-ffinite-math-onlyis specified โจfsqrtsโ unary square root operation ๐fcoss,fsins,ftans,fatans,fexps,flogsโ floating-point trigonometric and exponential functions. These instructions are only generated if-funsafe-math-optimizationsis also specified ๐ซถ
Double-precision floating point:
faddd,fsubd,fdivd,fmuldโ binary arithmetic operations ๐ฅfnegdโ unary negation ๐fabsdโ unary absolute value ๐ฆfcmpeqd,fcmpged,fcmpgtd,fcmpled,fcmpltd,fcmpnedโ comparison operations ๐ธfmind,fmaxdโ double-precision minimum and maximum. These instructions are only generated if-ffinite-math-onlyis specified ๐fsqrtdโ unary square root operation ๐fcosd,fsind,ftand,fatand,fexpd,flogdโ double-precision trigonometric and exponential functions. These instructions are only generated if-funsafe-math-optimizationsis also specified ๐ง
Conversions:
fextsdโ conversion from single precision to double precision ๐ftruncdsโ conversion from double precision to single precision ๐fixsi,fixsu,fixdi,fixduโ conversion from floating point to signed or unsigned integer types, with truncation towards zero ๐roundโ conversion from single-precision floating point to signed integer, rounding to the nearest integer and ties away from zero. This corresponds to the"__builtin_lroundf"function when-fno-math-errnois used ๐คfloatis,floatus,floatid,floatudโ conversion from signed or unsigned integer types to floating-point types ๐
In addition, all of these transfer instructions for internal registers X and Y have to be set up before you can use any of the double-precision floating-point instructions ๐. 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, if it's a unary operation) goes to the custom arithmetic instruction with its least significant half in source register src1 and its most significant half in src2 โจ. When a custom instruction returns a double-precision result, you get the most significant 32 bits in the destination register, and the other half comes back in the 32-bit register Y ๐ฅ. The best part is that GCC automatically generates the code sequences needed to write register X and/or read register Y whenever you use double-precision floating-point instructions. It's literally doing the work for you, periodt ๐
.
Here are the transfer instructions you've got to know about:
fwrxโ writessrc1into the least significant half ofXandsrc2into the most significant half ofX๐ธ.fwryโ writessrc1intoY๐ง.frdxhi,frdxloโ read the most or least (respectively) significant half ofXand store it indest๐.frdyโ reads the value ofYand stores it intodest๐.
Heads up, bestie: you can get more local control over how Nios II custom instructions are generated by using the target("custom-insn=N") and target("no-custom-insn") function attributes or pragmas ๐.
-mcustom-fpu-cfg=name
This option turns on a predefined, named set of custom instruction encodings (see -mcustom-insn above) โจ. These are the sets defined right now:
-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
Custom instruction assignments given by individual -mcustom-insn= options override the ones from -mcustom-fpu-cfg=, no matter what order they show up in on the command line ๐.
Want more local control over which FPU configuration applies? Use the target("custom-fpu-cfg=name") function attribute or pragma ๐ซ.
The name fph2 is short for Nios II Floating Point Hardware 2 Component ๐. Please note that the custom instructions enabled by -mcustom-fmins=233 and -mcustom-fmaxs=234 are only generated if -ffinite-math-only is specified ๐. The custom instruction enabled by -mcustom-round=248 is only generated if -fno-math-errno is specified. Unlike the other configurations, -fsingle-precision-constant is not set ๐ญ.
These additional -m options are available for the Altera Nios II ELF (bare-metal) target:
-mhalโ links with the HAL BSP. This suppresses linking with the GCC-provided C runtime startup and termination code, and it's typically used with-msys-crt0=to point at the alternate startup code the HAL BSP provides ๐ง.-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 is only useful together with-mhal๐ธ.-msys-lib=systemlibโsystemlibis the library name of the library that provides low-level system calls the C library needs, like "read" and "write". Typically used to link with a library provided by 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 ๐ .-misa=ISA-stringโ generates code for the specified PTX ISA (e.g.sm_35). ISA strings must be lower-case. Valid ISA strings includesm_30andsm_35. The default ISA issm_35โจ.-mptx=version-stringโ generates code for the specified PTX version (e.g.6.3). Valid version strings include3.1and6.3. The default PTX version is3.1๐ฅ.-mmainkernelโ links in code for a__mainkernel. This is for stand-alone execution instead of offloading execution ๐.-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 is 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 code generation variant is used for OpenMP offloading, but the option is exposed on its own so you can test the compiler. To generate code suitable for linking into programs that use OpenMP offloading, use-mgompinstead ๐ง.-muniform-simtโ switches to a code generation variant that lets every thread in each warp execute, while keeping memory state and side effects as if only one thread in each warp was active outside OpenMP SIMD regions. All atomic operations and calls to the runtime (malloc,free,vprintf) are conditionally executed (iff current lane index equals the master lane index), and the register being assigned is copied via a shuffle instruction from the master lane. Outside 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 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. This enables-msoft-stackand-muniform-simt, and 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โ ignored, it's only here for compatibility. It used to select linker and preprocessor options for use with newlib ๐.-msoft-div,-mhard-divโ select software or hardware divide (l.div,l.divu) instructions. The default is hardware divide โจ.-msoft-mul,-mhard-mulโ select software or hardware multiply (l.mul,l.muli) instructions. The default is hardware multiply ๐ฅ.-msoft-float,-mhard-floatโ select software or hardware for floating point operations. The default is software ๐ธ.-mdouble-floatโ when-mhard-floatis selected, enables generation of double-precision floating point instructions. By default, functions from libgcc are used for double-precision floating point operations ๐.-munordered-floatโ when-mhard-floatis selected, enables generation of unordered floating point compare and set flag (lf.sfun*) instructions. By default, functions from libgcc are used for unordered floating point compare and set flag operations ๐ฆ.-mcmovโ enables generation of conditional move (l.cmov) instructions. By default, the equivalent is generated using set and branch ๐ง.-mrorโ enables generation of rotate right (l.ror) instructions. By default, functions from libgcc are used for rotate right operations ๐.-mroriโ enables generation of rotate right with immediate (l.rori) instructions. By default, functions from libgcc are used for rotate right with immediate operations ๐ซ.-msextโ enables generation of sign extension (l.ext*) instructions. By default, memory loads are used to perform sign extension ๐.-msfimmโ enables generation of 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โ enables generation of 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โ doesn't 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-bit"int". This is the default ๐.-mint32,-mno-int16โ uses 32-bit"int"๐.-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 old"reload"allocator is used ๐ญ.
๐ง picoChip Options ๐ง
These -m options are defined for picoChip implementations:
-mae=ae_type
Okay so -mae=ae_type is the big one ๐
It sets the instruction set, register set, and instruction scheduling parameters for the array element type ae_type, and the supported values are ANY, MUL, and MAC ๐
-mae=ANYโ this is the totally generic AE type ๐ Code built with it runs on any of the other AE types, but it isn't as efficient as a build targeting one specific AE type, and some operations (e.g., multiplication) don't work properly on every AE type ๐ญ-mae=MULโ the most useful AE type for compiled code โจ It's also the default, so you get it if you don't pick anything ๐-mae=MACโ a DSP-style MAC AE ๐ฆ Heads up bestie: code built with this one can perform poorly when doing byte (char) manipulation, because the DSP AE has no hardware support for byte load/stores ๐-msymbol-as-addressโ lets the compiler use a symbol name directly as an address in a load/store instruction, skipping the step of loading it into a register first ๐ง Usually this makes bigger programs that run faster, but the results vary from program to program, so it's a user option instead of being permanently on ๐ธ-mno-inefficient-warningsโ turns off the warnings about inefficient code ๐ Those can pop up when you do byte-level memory operations on the MAC AE type. MAC has no hardware support for byte-level memory operations, so every byte load/store has to be synthesized from word load/stores, which is inefficient. The warning is basically telling you to rewrite the code to avoid byte operations, or to target an AE type with the right hardware support. This option silences all of that ๐ซถ
โจ PowerPC Options โจ
These are listed under
๐ธ PRU Options ๐ธ
These command-line options are defined for the PRU target ๐ง
-minrtโ links with a minimum runtime environment that has no support for static initializers and constructors ๐ Using it can seriously shrink the final ELF binary. Beware though, the compiler could still generate code with static initializers and constructors, so it's up to you to make sure your source program won't use those features ๐ญ-mmcu=mcuโ picks the PRU MCU variant to use ๐ Check Newlib for the exact list of supported MCUs ๐-mno-relaxโ tells GCC to pass the--no-relaxoption to the linker instead of--relaxโจ-mloopโ allows (or doesn't allow) GCC to use theLOOPinstruction ๐-mabi=variantโ picks the ABI variant to output code for ๐-mabi=tigives you the unmodified TI ABI, while-mabi=gnugives you a GNU variant that plays nicer with certain GCC assumptions. Here's how they differ:- Function Pointer Size โ the TI ABI says function (code) pointers are 16-bit, whereas GNU only supports 32-bit data and code pointers ๐ฆ
- Optional Return Value Pointer โ return values larger than 64 bits get passed through a hidden pointer as the first argument of the function ๐ The TI ABI says that pointer can be NULL if the caller isn't using the returned value. GNU always passes and expects a valid return value pointer ๐
The current-mabi=tiimplementation just raises a compile error whenever any of the above code constructs shows up ๐ญ So the standard C library can't be built, and it gets left out when linking with-mabi=ti.
Relaxation is a GNU feature, and for safety reasons it's disabled when you use -mabi=ti ๐ The TI toolchain doesn't emit relocations for QBBx instructions, so the GNU linker can't 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 roughly n instructions ๐-mplt,-mno-pltโ when generating PIC code, this decides whether PLTs are allowed or not ๐ It's ignored for non-PIC code, and the default is-mpltโจ-mabi=ABI-stringโ picks the integer and floating-point calling convention ๐ The ABI string has two parts: the size of integer types, and which registers get used for floating-point types. For example,-march=rv64ifd -mabi=lp64dmeanslongand pointers are 64-bit (which implicitly makesint32-bit), and floating-point values up to 64 bits wide get passed in F registers ๐ Compare that with-march=rv64ifd -mabi=lp64f, which still lets the compiler generate code using the F and D extensions, but only lets floating-point values up to 32 bits long get passed in registers. Or there's-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers at all ๐ง
The default for this one is system dependent, so if you want a specific calling convention, pick it yourself ๐
The valid calling conventions are ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d โจ Some combos just can't work on certain ISAs. For example, -march=rv32if -mabi=ilp32d is invalid, because that ABI needs 64-bit values 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. It's not well specified right now and is subject to change, so be careful ๐
-mfdiv,-mno-fdivโ uses (or doesn't use) hardware floating-point divide and square root instructions ๐ฅ This needs the F or D extensions for floating-point registers. The default is to use them if the architecture you specified has them ๐-mdiv,-mno-divโ uses (or doesn't use) hardware instructions for integer division ๐ This needs the M extension. The default is to use them if the architecture has them ๐-misa-spec=ISA-spec-stringโ picks the version of the RISC-V Unprivileged (formerly User-Level) ISA specification your code should conform to ๐ The options are:2.2โ produces code conforming to version 2.2 โจ20190608โ produces code conforming to version 20190608 ๐ฆ20191213โ produces code conforming to version 20191213 ๐ธ
The default is -misa-spec=20191213, unless GCC was configured with --with-isa-spec= set to 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โจ When-march=isn't specified, it uses the setting from-mcpu. If both-marchand-mcpu=are missing, the default is system dependent, so if you want specific architecture extensions, spell them out yourself ๐-mcpu=processor-stringโ uses the architecture of, and optimizes the output for, the given processor by its particular CPU name ๐ฅ The permitted values aresifive-e20,sifive-e21,sifive-e24,sifive-e31,sifive-e34,sifive-e76,sifive-s21,sifive-s51,sifive-s54,sifive-s76,sifive-u54, andsifive-u74๐-mtune=processor-stringโ optimizes the output for the given processor, named by microarchitecture or particular CPU name ๐ The permitted values arerocket,sifive-3-series,sifive-5-series,sifive-7-series,size, and all valid options for-mcpu=๐
If -mtune= isn't specified, it uses the setting from -mcpu, and if neither is given, the default is rocket ๐
The size choice isn't meant for end-users. It's used when -Os is specified, and it overrides the instruction cost info from -mtune=, but not the pipeline info. The result is smaller code that still performs well ๐ซถ
-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐ If-mpreferred-stack-boundaryisn't specified, the default is 4 (16 bytes, or 128 bits) ๐ฆ
Warning: if you use this switch, you have to build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐ญ
-msmall-data-limit=nโ puts global and static data smaller than n bytes into a special section (on some targets) ๐ธ-msave-restore,-mno-save-restoreโ uses (or doesn't use) smaller but slower prologue and epilogue code that calls library functions ๐ง The default is fast inline prologues and epilogues โจ-mshorten-memrefs,-mno-shorten-memrefsโ does (or doesn't) try to make more use of compressed load/store instructions by swapping a load/store of 'base register + large offset' for a new load/store of 'new base + small offset' ๐ If the new base gets stored 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โ-mstrict-alignmeans do not generate unaligned memory accesses, and-mno-strict-alignmeans do generate them ๐ The default depends on whether the processor you're optimizing for supports fast unaligned access or not ๐-mcmodel=medlowโ generates code for the medium-low code model ๐ฆ The program and its statically defined symbols must lie within a single 2 GiB address range, and between absolute addresses -2 GiB and +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 must be within any single 2 GiB address range ๐ Programs can be statically or dynamically linked ๐-mexplicit-relocs,-mno-exlicit-relocsโ uses (or doesn't use) assembler relocation operators when dealing with symbolic addresses ๐ The alternative is assembler macros instead, which may limit optimization ๐ซถ-mrelax,-mno-relaxโ takes advantage of linker relaxations to reduce the number of instructions needed to materialize symbol addresses โญ The default is to take advantage of them ๐-memit-attribute,-mno-emit-attributeโ emits (or doesn't emit) a RISC-V attribute to record extra information into ELF objects ๐ฅ This feature requires at least binutils 2.32 ๐-malign-data=typeโ okay so this one controls how GCC lines up variables and constants of array, structure, or union types ๐โจ Your choices 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โ bestie, this is the stack protection squad ๐ก๏ธ It generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block ๐งต
If you go with tls, then -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset decide which register is the base register for reading the canary, and what offset gets applied from that base register. There's no default register or offset here, because this is entirely for use within the Linux kernel ๐ง๐
๐ธ RL78 Options โจ
-msimโ links in extra target libraries so your code can run inside a simulator ๐ฎ-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ this picks which kind of hardware multiplication and division support you get ๐งฎ The simplest one 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 uses the multiplication and division instructions supported by the RL78/G14 (S3 core) parts ๐ฅ The"rl78"value is an alias for"g14", and the"mg10"value 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โ this 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 (S2) core doesn't have multiply or divide instructions. Instead it uses a hardware peripheral for those operations ๐ง The G10 (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 off hardware multiplications altogether ๐ซ
Heads up, babe: even though the RL78/G14 core is the default target, specifying-mcpu=g14or-mcpu=rl78on the command line does change how the toolchain behaves, because it also turns on G14 hardware multiply support. If you don't specify these on the command line, software multiplication routines get used even though the code targets the RL78 core. This is for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ฐ๏ธ
There's also a C preprocessor macro defined based on this setting. The possible values are "__RL78_G10__", "__RL78_G13__", or "__RL78_G14__" ๐ฆ
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the matching-mcpu=option ๐ซถ They're only here for backwards compatibility, so you don't have to change your old builds ๐-mallregsโ lets the compiler use all of the available registers ๐ By default, registers"r24..r31"are reserved for interrupt handlers. With this option on, those registers can also be used in ordinary functions ๐-m64bit-doubles,-m32bit-doublesโ makes the"double"data 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โ this tells interrupt handler functions to preserve the MDUC registers ๐ You only really need it if normal code might touch the MDUC registers, like if it does multiplication and division ๐งฎ The default is to ignore the MDUC registers, because that makes the interrupt handlers faster โก You need to pass the target option-mg13for 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 does a multiplication or division, 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โ lets GCC use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root ๐งฎ-mpowerpc-gfxopt,-mno-powerpc-gfxoptโ lets GCC use the optional PowerPC architecture instructions in the Graphics group, including floating-point select ๐จ-mmfcrf,-mno-mfcrfโ lets GCC generate the move from condition register field instruction, which is implemented on the POWER4 and other processors that support the PowerPC V2.01 architecture ๐-mpopcntb,-mno-popcntbโ lets GCC generate the popcount and double-precision FP reciprocal estimate instruction, which is implemented on the POWER5 and other processors that support the PowerPC V2.02 architecture ๐ข-mpopcntd,-mno-popcntdโ lets GCC generate the popcount instruction implemented on the POWER7 and other processors that support the PowerPC V2.06 architecture ๐-mfprnd,-mno-fprndโ lets GCC generate the FP round to integer instructions implemented on the POWER5+ and other processors that support the PowerPC V2.03 architecture ๐-mcmpb,-mno-cmpbโ lets GCC generate the compare bytes instruction implemented on the POWER6 and other processors that support the PowerPC V2.05 architecture ๐งฉ-mhard-dfp,-mno-hard-dfpโ lets GCC generate the decimal floating-point instructions implemented on some POWER processors ๐ช-mpowerpc64,-mno-powerpc64โ lets GCC generate the additional 64-bit instructions found in the full PowerPC64 architecture, and treats GPRs as 64-bit doubleword quantities ๐ GCC defaults to-mno-powerpc64๐
The default value of all of these is determined when GCC is configured. Specifying -mcpu=cpu_type overrides these options, so we recommend you use -mcpu=cpu_type instead of the options listed above ๐ซถ
-mcpu=cpu_typeโ sets the architecture type, register usage, and instruction scheduling parameters for the machine typecpu_type๐ฅ๏ธ Supported values forcpu_typeare401,403,405,405fp,440,440fp,464,464fp,476,476fp,505,601,602,603,603e,604,604e,620,630,740,7400,7450,750,801,821,823,860,970,8540,a2,e300c2,e300c3,e500mc,e500mc64,e5500,e6500,ec603e,G3,G4,G5,titan,power3,power4,power5,power5+,power6,power6x,power7,power8,power9,power10,powerpc,powerpc64,powerpc64le,rs64, andnative๐
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le give you pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC machine types ๐ง They come with a generic processor model for scheduling purposes ๐
Specifying native detects the host processor of the system doing the compilation and picks the matching architecture option ๐ต๏ธ -mcpu=native has no effect if GCC doesn't recognize the processor ๐คทโโ๏ธ
The other options each specify a specific processor. Code generated under those options runs best on that processor, and it may not run at all on others ๐
The -mcpu options automatically enable or disable the following options: -maltivec -mfprnd -mhard-float -mmfcrf -mmultiple -mpopcntb -mpopcntd -mpowerpc64 -mpowerpc-gpopt -mpowerpc-gfxopt -mmulhw -mdlmzb -mmfpgpr -mvsx -mcrypto -mhtm -mpower8-fusion -mpower8-vector -mquad-memory -mquad-memory-atomic -mfloat128 -mfloat128-hardware -mprefixed -mpcrel -mmma -mrop-protect ๐ช
Which options get set for a particular CPU changes between compiler versions, depending on what seems to produce the best code for that CPU ๐ It doesn't necessarily match the actual hardware's capabilities, so don't assume it does ๐ซ If you want to set one individual option to a particular value, you can put it after the -mcpu option, like -mcpu=970 -mno-altivec ๐
On AIX, the -maltivec and -mpowerpc64 options are not enabled or disabled by -mcpu at the moment, because AIX doesn't have full support for these options yet. You can still enable or disable them individually if you're sure it'll work in your environment โจ
-mtune=cpu_typeโ sets the instruction scheduling parameters for the machine typecpu_type, but doesn't 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 set by-mcpu, but the scheduling parameters set by-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 be up to a total of 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โ ๐ okay so-maltivecmakes GCC generate code that uses AltiVec instructions, and it also unlocks built-in functions for more direct access to the AltiVec instruction set.-mno-altivecturns that off. You might also need-mabi=altivecto adjust the current ABI with the AltiVec ABI enhancements โจ
When -maltivec is on, the element order for AltiVec intrinsics like vec_splat, vec_extract, and vec_insert matches the array element order for your target's endianness ๐ซถ Element zero is the leftmost element in a vector register on a big-endian target, and the rightmost one on a little-endian target. Bestie, this one is lowkey the most important bit ๐
-mvrsave,-mno-vrsaveโ ๐ธ generates VRSAVE instructions when GCC is making AltiVec code (or doesn't, with the-mno-version).-msecure-pltโ ๐ makes code so thatldandld.socan build executables and shared libraries with non-executable.pltand.gotsections. This is a PowerPC 32-bit SYSV ABI option, so it's only for that combo ๐-mbss-pltโ ๐ฆ makes code that uses a BSS.pltsection thatld.sofills in. The catch is it needs.pltand.gotsections that are both writable and executable. Also a PowerPC 32-bit SYSV ABI option.-misel,-mno-iselโ โญ switches ISEL instruction generation on or off. That's the whole tea โ-mvsx,-mno-vsxโ ๐ generates code that uses (or avoids) vector/scalar (VSX) instructions, and also enables built-in functions that give more direct access to the VSX instruction set.-mcrypto,-mno-cryptoโ ๐ฅ enables (or disables) the built-in functions for direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA.-mhtm,-mno-htmโ ๐ง enables (or disables) the built-in functions for direct access to the Hardware Transactional Memory (HTM) instructions, which were also added in version 2.07 of the PowerPC ISA.-mpower8-fusion,-mno-power8-fusionโ ๐ generates code that keeps some integer operations next to each other, so the instructions can get fused together on POWER8 and later processors. The-mno-version does not keep them adjacent, so no fusing ๐-mpower8-vector,-mno-power8-vectorโ ๐ generates code that uses (or skips) the vector and scalar instructions added in version 2.07 of the PowerPC ISA. It also enables built-in functions for more direct access to the vector instructions, obsessed โจ-mquad-memory,-mno-quad-memoryโ ๐ generates code that uses (or skips) the non-atomic quad word memory instructions. Heads up:-mquad-memoryrequires 64-bit mode ๐ โโ๏ธ-mquad-memory-atomic,-mno-quad-memory-atomicโ ๐ same deal, but for the atomic quad word memory instructions.-mquad-memory-atomicalso requires 64-bit mode.-mfloat128,-mno-float128โ ๐ enables or disables the__float128keyword for IEEE 128-bit floating point, and picks between software emulation or hardware instructions for it.
Okay, the IEEE 128-bit floating point support needs the VSX instruction set (-mvsx) to be enabled first. It's also only supported on Linux, so no cap, that's a hard limit ๐ง
The default for -mfloat128 is enabled on PowerPC Linux systems using the VSX instruction set, and disabled on other systems โจ
If you use the ISA 3.0 instruction set (-mpower9-vector or -mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support will also turn on the generation of ISA 3.0 IEEE 128-bit floating point instructions ๐ Otherwise, if you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets done with software emulation ๐ซ
-mfloat128-hardware,-mno-float128-hardwareโ ๐ฅ enables or disables using ISA 3.0 hardware instructions to support the__float128data type.
The default for -mfloat128-hardware is enabled on PowerPC Linux systems using the ISA 3.0 instruction set, and disabled on other systems ๐
-m32,-m64โ ๐ generates code for the 32-bit or 64-bit environments of Darwin and SVR4 targets (including GNU/Linux). The 32-bit environment setsint,long, and pointer to 32 bits, and makes code that runs on any PowerPC variant. The 64-bit environment setsintto 32 bits,longand pointer to 64 bits, and generates code for PowerPC64, same as-mpowerpc64๐ง-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ ๐ these change how the TOC (Table Of Contents) gets generated, and every executable file gets one.-mfull-tocis the default, and in that mode GCC gives at least one TOC entry for each unique non-automatic variable reference in your program. It also puts floating-point constants in the TOC. The catch? Only 16,384 entries fit in the TOC ๐ญ
If a linker error 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, and -mno-sum-in-toc makes GCC generate code that calculates the sum of an address and a constant at run time, instead of stuffing that sum into the TOC. You can use one or both, and each one makes the code very slightly slower and larger in exchange for saving TOC space ๐ธ
Still out of room even with both? Try -mminimal-toc. It makes GCC create only one TOC entry for every file. The code is slower and larger, but it uses extremely little TOC space. Maybe only use it on files with less frequently-executed code ๐ฅบ
-maix64,-maix32โ ๐ enables the 64-bit AIX ABI and calling convention, which means 64-bit pointers, a 64-bitlongtype, and the infrastructure needed to support them.-maix64implies-mpowerpc64, while-maix32disables the 64-bit ABI and implies-mno-powerpc64. GCC defaults to-maix32โจ-mxl-compat,-mno-xl-compatโ ๐ produces code that conforms more closely to IBM XL compiler semantics when you're using the AIX-compatible ABI. Here's the tea: it passes floating-point arguments to prototyped functions beyond the register save area (RSA) on the stack, in addition to the argument FPRs. It also doesn't assume the most significant double in a 128-bitlong doublevalue is properly rounded when comparing values and converting to double. And it uses XL symbol names forlong doublesupport routines.
The AIX calling convention got extended, but that wasn't documented at first, to handle an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than declared. IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine is compiled without optimization. Storing floating-point arguments on the stack all the time is inefficient and rarely needed, so this option isn't on by default. You only really need it when calling subroutines compiled by IBM XL compilers without optimization ๐
-mpeโ ๐งโโ๏ธ supports the IBM RS/6000 SP Parallel Environment (PE). It links an application written to use message passing with special startup code so the application can actually run. The system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you have to override the specs file with-specs=to point at the right directory.
โ ๏ธ The Parallel Environment doesn't support threads, so-mpeand-pthreadare incompatible. Don't mix them, bestie ๐
-malign-natural,-malign-powerโ ๐ on AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux,-malign-naturaloverrides the ABI-defined alignment of larger types, like floating-point doubles, and puts them on their natural size-based boundary.-malign-powertells GCC to follow the ABI-specified alignment rules instead. GCC defaults to the standard alignment defined in the ABI.
On 64-bit Darwin, natural alignment is the default, and -malign-power isn't supported there ๐
โโ๏ธ
-msoft-float,-mhard-floatโ ๐ generates code that does not use (or does use) the floating-point register set. If you use-msoft-float, software floating-point emulation is provided, but you have to pass the option to GCC when linking too.-mmultiple,-mno-multipleโ ๐งฉ generates code that uses (or doesn't use) the load multiple word and store multiple word instructions. These get generated by default on POWER systems, but not on PowerPC systems.
โ ๏ธ Do not use -mmultiple on 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โ ๐ generates code that uses (or doesn't use) the load or store instructions that update the base register to the address of the calculated memory location. These 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 gets stored. That means code that walks the stack frame across interrupts or signals might end up with corrupted data.
-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ ๐ฆ generates code that tries to avoid (or doesn't avoid) indexed load or store instructions. Those can cause a performance penalty on Power6 processors in certain situations, like stepping through large arrays that cross a 16M boundary. This option is enabled by default when targeting Power6 and disabled otherwise.-mfused-madd,-mno-fused-maddโ ๐ซ generates code that uses (or doesn't use) the floating-point multiply and accumulate instructions. These are generated by default if hardware floating point is used. The machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fast, and-mno-fused-maddis mapped to-ffp-contract=off๐-mmulhw,-mno-mulhwโ okay bestie, these two decide whether your code uses the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors.-mmulhwmakes the code use them, and-mno-mulhwmakes it skip them. They're on by default when you're targeting those chips, so you're already winning ๐-mdlmzb,-mno-dlmzbโ ๐ this one controls the string-searchdlmzbinstruction on the IBM 405, 440, 464 and 476 processors.-mdlmzbgenerates code that uses it and-mno-dlmzbgenerates code that doesn't. Same energy as before: it's on by default for those targets ๐ซถ-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems,-mno-bit-alignmeans structs and unions with bit-fields are not forced to line up with the bit-field's base type, and-mbit-alignmeans they are forced to. The vibe check here is memory layout ๐
By default, a struct with nothing but 8 unsigned bit-fields of length 1 gets aligned to a 4-byte boundary and ends up 4 bytes big. With -mno-bit-align, that same struct is aligned to a 1-byte boundary and is just 1 byte in size. Iconic glow-up ๐ฆ
-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems,-mno-strict-alignmeans the compiler does not assume the system handles unaligned memory references, while-mstrict-alignmeans it does assume that ๐ง-mrelocatable,-mno-relocatableโ โจ these generate code that either allows or doesn't allow a static executable to be relocated to a different address at run time. A simple embedded PowerPC system loader is expected to relocate the whole of.got2, plus the 4-byte locations listed in the.fixupsection (a table of 32-bit addresses generated by this option). For this to work, every object linked together has to be compiled with-mrelocatableor-mrelocatable-lib. Also,-mrelocatablecode aligns the stack to an 8-byte boundary, so keep that in mind bestie ๐ธ-mrelocatable-lib,-mno-relocatable-libโ this is basically-mrelocatablewith a glow-up. It still generates a.fixupsection so static executables can be relocated at run time, but it does not use the smaller stack alignment that-mrelocatabledoes. Objects built with-mrelocatable-libcan be linked with objects built with any combination of the-mrelocatableoptions, which is so convenient ๐-mno-toc,-mtocโ on System V.4 and embedded PowerPC systems,-mno-tocmeans the compiler does not assume register 2 holds a pointer to a global area with the addresses the program uses.-mtocis the one that does assume it ๐-mlittle,-mlittle-endianโ ๐ on System V.4 and embedded PowerPC systems, this compiles your code for the processor in little-endian mode.-mlittle-endianis exactly the same as-mlittle, so pick whichever you vibe with.-mbig,-mbig-endianโ ๐ on System V.4 and embedded PowerPC systems, this compiles your code for the processor in big-endian mode.-mbig-endianis the same as-mbig, no drama.-mdynamic-no-picโ ๐ on Darwin and Mac OS X systems, this compiles code so it's not relocatable, but its external references are relocatable. The result is suitable for applications, but not for shared libraries, so don't try to ship it as a.dylib๐-msingle-pic-baseโ this treats the register used for PIC addressing as read-only, instead of loading it in the prologue for every function. Your runtime system has to set that register to the right value before execution starts, because nobody else is going to do it for you ๐-mprioritize-restricted-insns=priorityโ this controls the priority given to dispatch-slot restricted instructions during the second scheduling pass. Thepriorityargument takes0,1, or2, which give no priority, the highest priority, or the second-highest priority to those instructions (in that order) ๐-msched-costly-dep=dependence_typeโ this decides which dependences the target counts as costly during instruction scheduling. Thedependence_typeargument takes one of these values:noโ no dependence is costly. Chill vibes only ๐allโ every dependence is costly. Intense ๐true_store_to_loadโ a true dependence from store to load is costly.store_to_loadโ any dependence from store to load is costly.numberโ any dependence whose latency is greater than or equal tonumberis costly.
-minsert-sched-nops=schemeโ this picks which NOP insertion scheme gets used during the second scheduling pass. Theschemeargument takes one of these values:noโ don't insert NOPs at all.padโ pad any dispatch group that has vacant issue slots with NOPs, according to the scheduler's grouping. ๐งธregroup_exactโ insert NOPs to force costly dependent insns into separate groups. It inserts exactly as many NOPs as needed to push an insn into a new group, according to the estimated processor grouping. Precise, bestie โจnumberโ insert NOPs to force costly dependent insns into separate groups, withnumberNOPs used to force an insn into a new group.
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code using calling conventions that follow the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement. This is the default unless you configured GCC usingpowerpc-*-eabiaix, so it's basically the classic move ๐-mcall-sysv-eabi,-mcall-eabiโ this one is a two-for-one: it's the same as specifying both-mcall-sysvand-meabi๐-mcall-sysv-noeabiโ another combo deal ๐ this is the same as specifying both-mcall-sysvand-mno-eabi.-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐ธ-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐ฆ-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐-mtraceback=traceback_typeโ this selects the type of traceback table. The valid values fortraceback_typearefull,part, andno. Pick your fighter ๐ฅ-maix-struct-returnโ this returns all structures in memory, which is what the AIX ABI specifies ๐งฑ-msvr4-struct-returnโ this returns structures smaller than 8 bytes in registers, as specified by the SVR4 ABI. Smaller structs, faster vibes โจ-mabi=abi-typeโ this extends the current ABI with a particular extension, or removes that extension. The valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1,elfv2, and, for AIX,vec-extabiandvec-default. That's a lot of options, so take a breath ๐ซ-mabi=ibmlongdoubleโ this changes the current ABI to use IBM extended-precisionlong double. โ ๏ธ This is not likely to work if your system defaults to IEEE extended-precisionlong double. If you switch thelong doubletype away from IEEE extended-precision, the compiler will issue a warning unless you use-Wno-psabi. It also requires-mlong-double-128to be enabled.-mabi=ieeelongdoubleโ this changes the current ABI to use IEEE extended-precisionlong double. โ ๏ธ This is not likely to work if your system defaults to IBM extended-precisionlong double. If you switch away from IBM extended-precision, the compiler will issue a warning unless you use-Wno-psabi. It also requires-mlong-double-128to be enabled.-mabi=elfv1โ this changes the current ABI to the ELFv1 ABI. It's the default ABI for big-endian PowerPC 64-bit Linux. Overriding the default ABI needs special system support, and it's likely to fail in spectacular ways ๐-mabi=elfv2โ this changes the current ABI to the ELFv2 ABI. It's the default ABI for little-endian PowerPC 64-bit Linux. Overriding the default ABI needs special system support, and it's likely to fail in spectacular ways too, so please don't ๐-mgnu-attribute,-mno-gnu-attributeโ these control whether the compiler emits.gnu_attributeassembly directives. Those directives set tag/value pairs in a.gnu.attributessection, which specify ABI variations in function parameters or return values ๐-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems,-mprototypeassumes that all calls to variable argument functions are properly prototyped. Without it, the compiler has to insert an instruction before every non-prototyped call to set or clear bit 6 of the condition code register (CR), which tells whether floating-point values are passed in the floating-point registers in case the function takes variable arguments. With-mprototype, only calls to prototyped variable argument functions set or clear that bit ๐-msimโ on embedded PowerPC systems, this assumes the startup module is calledsim-crt0.oand the standard C libraries arelibsim.aandlibc.a. This is the default forpowerpc-*-eabisimconfigurations ๐งช-mmvmeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibmvme.aandlibc.a๐-madsโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibads.aandlibc.a๐-myellowknifeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibyk.aandlibc.a๐-mvxworksโ on System V.4 and embedded PowerPC systems, this tells the compiler you're building for a VxWorks system ๐-membโ on embedded PowerPC systems, this sets thePPC_EMBbit in the ELF flags header to indicate that eabi extended relocations are used ๐งฉ
-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems, these decide whether you adhere to the Embedded Applications Binary Interface (EABI), which is a set of modifications to the System V.4 specifications. โจ Here's the tea:-meabialigns the stack to an 8-byte boundary, calls a function__eabifrommainto set up the EABI environment, and lets the-msdataoption use bothr2andr13to point to two separate small data areas.-mno-eabialigns the stack to a 16-byte boundary, doesn't call any EABI initialization function frommain, and lets the-msdataoption use onlyr13to point to a single small data area.
-meabi is on by default if you configured GCC using one of the powerpc*-*-eabi* options, so that's the default main character energy ๐
-msdata=eabi: okay bestie, on System V.4 and embedded PowerPC systems, small initializedconstglobal and static data goes into the.sdata2section, which is pointed to by registerr2๐. Small initialized non-constglobal and static data goes into.sdatainstead, pointed to by registerr13โจ. Small uninitialized global and static data gets tucked into.sbss, which sits right next to.sdata๐ฆ. Heads up:-msdata=eabiis incompatible with-mrelocatable๐ซ, and it also turns on-memb๐ซถ.-msdata=sysv: same vibe on System V.4 and embedded PowerPC systems, but way simpler ๐ . Small global and static data goes into.sdata, pointed to by registerr13. Small uninitialized global and static data goes into.sbss, which is adjacent to.sdata. Just know that-msdata=sysvis incompatible with-mrelocatable๐ซ.-msdata=default,-msdata: this one is giving "it depends" ๐. On System V.4 and embedded PowerPC systems, if-meabiis used, the code gets compiled the same as-msdata=eabi. Otherwise, it gets compiled the same as-msdata=sysv๐ธ.-msdata=data: on System V.4 and embedded PowerPC systems, small global data goes into.sdata, and small uninitialized global data goes into.sbss๐ง. The catch is that registerr13does not get used to address small data here. This is the default unless other-msdataoptions are used.-msdata=none,-mno-sdata: on embedded PowerPC systems, all initialized global and static data goes into.data, and all uninitialized data goes into.bss๐.-mreadonly-in-sdata: read-only objects get put into.sdataas well โจ. This is the default, so you're already getting it ๐.-mblock-move-inline-limit=num: inline every block move (think calls tomemcpyor structure copies) that's less than or equal tonumbytes ๐ฅ. The minimum value fornumis 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default is target-specific.-mblock-compare-inline-limit=num: generate non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal tonumbytes ๐. Ifnumis0, then all inline expansion, both non-loop and loop, of block compare is disabled ๐ซ. The default is target-specific.-mblock-compare-inline-loop-limit=num: this one makes an inline expansion using loop code for all block compares that are less than or equal tonumbytes, but bigger than the limit for the non-loop inline block compare ๐. If the block length isn't constant, at mostnumbytes get compared beforememcmpis called to handle the rest of the block. The default is target-specific.-mstring-compare-inline-limit=num: compare at mostnumstring bytes with inline code ๐. If the difference or the end of the 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, global and static items that are less than or equal tonumbytes get put into the small data or BSS sections, instead of the normal data or BSS section ๐ง. By default,numis 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, this does (or does not) emit register names in the assembly language output using symbolic forms ๐ฆ.-mlongcall,-mno-longcall: by default, the compiler assumes all calls are 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. You can override this with theshortcallfunction attribute, or with#pragma longcall(0)โจ.
Some linkers can detect out-of-range calls and generate glue code on the fly ๐ช. On those systems, long calls are unnecessary and generate slower code ๐ญ. As of this writing, the AIX linker can do this, and so can the GNU linker for PowerPC/64. It's planned to add this feature to the GNU linker for 32-bit PowerPC systems 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 it generates bl callee if the PPC bl instruction can reach 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 toss it ๐๏ธ.
In the future, GCC may ignore all longcall specifications when the linker is known to generate glue ๐.
-mpltseq,-mno-pltseq: this implements (or does not implement)-fno-pltand long calls using an inline PLT call sequence ๐. That sequence supports lazy linking and long calls to functions indlopen'd shared libraries. Inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers. They're enabled by default if support is 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: this marks (or does not mark) calls to__tls_get_addrwith a relocation that specifies the function argument ๐ท๏ธ. The relocation lets the linker reliably connect the function call with the argument setup instructions for TLS optimization. That in turn lets GCC better schedule the sequence ๐ฏ.-mrecip,-mno-recip: this enables the use of 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, for floating-point arguments. You should use-ffast-mathwhen using-mrecip, or at least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-math, and-fno-trapping-math๐ซถ. The throughput of the sequence is generally higher than the throughput of the non-reciprocal instruction โก. But the precision can drop by up to 2 ulp (i.e. the inverse of 1.0 equals0.99999994) for reciprocal square roots ๐ฌ.-mrecip=opt: this controls which reciprocal estimate instructions may be used ๐๏ธ.optis a comma-separated list of options, and any of them can be preceded by a!to invert it. Here's the menu: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 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 enables all of the reciprocal estimate instructions except for FRSQRTE, XSRSQRTEDP, and XVRSQRTEDP, which handle the double-precision reciprocal square root calculations ๐.
-mrecip-precision,-mno-recip-precision: this assumes (or does not assume) that the reciprocal estimate instructions give higher-precision estimates than the PowerPC ABI requires ๐ฏ. Selecting-mcpu=power6,-mcpu=power7, or-mcpu=power8automatically selects-mrecip-precision๐ช. The double-precision square root estimate instructions aren't generated by default on low-precision machines, since they don't converge after three steps ๐.-mveclibabi=type: this specifies the ABI type to use for vectorizing intrinsics using an external library ๐. The only type supported right now ismass, which tells GCC to use IBM's Mathematical Acceleration Subsystem (MASS) libraries for vectorizing intrinsics with external libraries. When generating code for power7, GCC currently emits calls toacosd2,acosf4,acoshd2,acoshf4,asind2,asinf4,asinhd2,asinhf4,atan2d2,atan2f4,atand2,atanf4,atanhd2,atanhf4,cbrtd2,cbrtf4,cosd2,cosf4,coshd2,coshf4,erfcd2,erfcf4,erfd2,erff4,exp2d2,exp2f4,expd2,expf4,expm1d2,expm1f4,hypotd2,hypotf4,lgammad2,lgammaf4,log10d2,log10f4,log1pd2,log1pf4,log2d2,log2f4,logd2,logf4,powd2,powf4,sind2,sinf4,sinhd2,sinhf4,sqrtd2,sqrtf4,tand2,tanf4,tanhd2, andtanhf4๐. Both-ftree-vectorizeand-funsafe-math-optimizationsmust also be enabled ๐ซถ. And the MASS libraries must be specified at link time ๐.-mfriz,-mno-friz: this generates (or does not generate) thefrizinstruction when-funsafe-math-optimizationsis used to optimize rounding of floating-point values to 64-bit integers and back to floating point ๐ซง. Watch out, though: thefrizinstruction doesn't return the same value if the floating-point number is too large to fit in an integer ๐ญ.
-mpointers-to-nested-functions -mno-pointers-to-nested-functions
Okay so bestie, these two are a matched pair ๐
Generate (or don't generate) code that loads up the static chain register ("r11") when you call through a pointer on AIX and 64-bit Linux systems, where a function pointer points to a 3-word descriptor holding the function address, the TOC value to load into register "r2", and the static chain value to load into register "r11". ๐ The -mpointers-to-nested-functions one is on by default. โจ But if you use -mno-pointers-to-nested-functions, you cannot call through pointers to nested functions, or through pointers to functions compiled in other languages that use the static chain. ๐ That's a whole vibe check, so be careful with it ๐ญ
-msave-toc-indirect -mno-save-toc-indirect
Generate (or don't generate) code that saves the TOC value in the reserved stack location in the function prologue, if the function calls through a pointer on AIX and 64-bit Linux systems. ๐ฆ If the TOC value isn't saved in the prologue, it gets saved just before the call through the pointer. ๐ธ The -mno-save-toc-indirect option is the default, so that's your baseline ๐ซถ
-mcompat-align-parm -mno-compat-align-parm
Generate (or don't generate) code that passes structure parameters with a maximum alignment of 64 bits, for compatibility with older versions of GCC. ๐ง
Okay so the older versions of GCC (prior to 4.9.0) incorrectly did not align a structure parameter on a 128-bit boundary when that structure had a member that needed 128-bit alignment. ๐ญ This got fixed in more recent versions of GCC. ๐ You can use this option if you need code that plays nicely with functions compiled by those older versions ๐
The -mno-compat-align-parm option is the default ๐
-mstack-protector-guard=guard -mstack-protector-guard-reg=reg -mstack-protector-guard-offset=offset -mstack-protector-guard-symbol=symbol
Generate stack protection code that uses a canary at guard. ๐ฅ The supported locations are global for a global canary, or tls for a per-thread canary in the TLS block. ๐ The tls one is the default with GNU libc version 2.4 or later. โญ
With the tls choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also decide which register to use as the base register for reading the canary, and what offset from that base register to use. ๐ซถ The defaults for those are whatever the relevant ABI says. ๐
-mstack-protector-guard-symbol=symbol overrides the offset with a symbol reference to a canary in the TLS block. โจ
-mpcrel -mno-pcrel
Generate (or don't generate) pc-relative addressing. ๐ฆ The -mpcrel option needs the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) to both be enabled. ๐
-mprefixed -mno-prefixed
Generate (or don't generate) addressing modes that use prefixed load and store instructions. ๐ธ The -mprefixed option needs -mcpu=power10 (or later) to be enabled. ๐
-mmma -mno-mma
Generate (or don't generate) the MMA instructions. ๐ The -mma option needs -mcpu=power10 (or later) to be enabled ๐ง
-mrop-protect -mno-rop-protect
Generate (or don't 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
Generate (or don't generate) code that runs in privileged state. ๐
-mblock-ops-unaligned-vsx -mno-block-ops-unaligned-vsx
Generate (or don't generate) unaligned VSX loads and stores for inline expansion of "memcpy" and "memmove". ๐
โจ RX Options โจ
These command-line options are defined for RX targets ๐ฆ
-m64bit-doubles -m32bit-doubles
Makes the "double" data type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size. ๐ The default is -m32bit-doubles. ngl the reason is that RX floating-point hardware only works on 32-bit values ๐
-fpu -nofpu
Enables (-fpu) or disables (-nofpu) the use of RX floating-point hardware. ๐ฅ It's on by default for the RX600 series and off for the RX200 series. ๐ธ
Floating-point instructions are only generated for 32-bit floating-point values, though. ๐ญ So the FPU hardware isn't used for doubles if the -m64bit-doubles option is used. ๐
Note: if-fpuis enabled, then-funsafe-math-optimizationsalso gets enabled automatically. ๐ This is because the RX FPU instructions are themselves unsafe. ๐
-mcpu=name
Picks the type of RX CPU to target. ๐ Right now there are three supported types: 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 gets enabled by default when this type is selected. ๐ซถ
-mbig-endian-data -mlittle-endian-data
Stores data (but not code) in big-endian format. ๐ The default is -mlittle-endian-data, so data gets stored in little-endian format by default. ๐
-msmall-data-limit=N
Specifies the maximum size in bytes of global and static variables that can be placed into the small data area. ๐ธ Using the small data area can lead to smaller and faster code, but the area is limited, so it's up to the programmer to make sure it doesn't overflow. ๐ญ Also, when the small data area is used, one of the RX's registers (usually "r13") gets reserved to point to this area, so the compiler can't use it anymore. ๐ That could make the code slower and/or larger if variables get pushed onto the stack instead of being held in this register. ๐
Note, common variables (variables that haven't been initialized) and constants aren't placed into the small data area, because they get assigned to other sections in the output executable. ๐ฆ
The default value is zero, which disables this feature. ๐ Also, this feature isn't enabled by default with higher optimization levels (-O2 etc), because reserving a register can have potentially detrimental effects. ๐ It's up to the programmer to experiment and figure out whether it helps their program. ๐ซถ See the description of the -mpid option for how the actual register to hold the small data area pointer is chosen. โจ
-msim -mno-sim
Uses the simulator runtime. ๐ง The default is to use the libgloss board-specific runtime. ๐
-mas100-syntax -mno-as100-syntax
When generating assembler output, uses a syntax that's compatible with Renesas's AS100 assembler. ๐ธ This syntax can also be handled by the GAS assembler, but it has some restrictions, so it isn't generated by default. ๐
-mmax-constant-size=N
Specifies the maximum size, in bytes, of a constant that can be used as an operand in an RX instruction. ๐ฅ The RX instruction set does allow constants up to 4 bytes long in instructions, but a longer value means a longer instruction. ๐ญ So in some situations it can be beneficial to restrict the size of constants used in instructions. ๐ Constants that are too big get placed into a constant pool and referenced via register indirection instead. ๐ซถ
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
Enables linker relaxation. ๐ฆ This is a process where the linker tries to shrink a program by finding shorter versions of various instructions. ๐ It's disabled by default. ๐
-mint-register=N
Specifies the number of registers to reserve for fast interrupt handler functions. ๐ The value N can be between 0 and 4. ๐ A value of 1 means register "r13" is reserved for the exclusive use of fast interrupt handlers. ๐ง A value of 2 reserves "r13" and "r12". ๐ A value of 3 reserves "r13", "r12" and "r11", and a value of 4 reserves "r13" through "r10". ๐ A value of 0, the default, doesn't reserve any registers. ๐ธ
-msave-acc-in-interrupts
Specifies that interrupt handler functions should preserve the accumulator register. ๐ This is only necessary if normal code might use the accumulator register, for example because it does 64-bit multiplications. ๐ The default is to ignore the accumulator, because that makes the interrupt handlers faster. โญ
-mpid -mno-pid
Enables the generation of position independent data. ๐ฆ When enabled, 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 be figured out at run time without the executable needing to be relocated, which is a big win for embedded apps with tight memory constraints. ๐ Data that can be modified isn't affected by this option. ๐
Note, using this feature reserves a register, usually "r13", for the constant data base address. ๐ญ This can make the code slower and/or larger, especially in complicated functions. ๐
The actual register chosen to hold the constant data base address depends on whether -msmall-data-limit and/or -mint-register are enabled. ๐ Starting with register "r13" and going downwards, registers get allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. ๐ง So it's possible for the small data area register to be "r8" if both -mint-register=4 and -mpid are specified on the command line. ๐
By default this feature isn't 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 issuing a warning if it finds more than one fast interrupt handler while compiling a file. ๐ The default is to issue a warning for each extra fast interrupt handler found, since the RX only supports one such interrupt. ๐ฅ
-mallow-string-insns -mno-allow-string-insns
Enables or disables the use of the string manipulation instructions "SMOVF", "SCMPU", "SMOVB", "SMOVU", "SUNTIL" "SWHILE" and also the "RMPA" instruction. ๐ These instructions may prefetch data, which isn't safe to do when accessing an I/O register. ๐ญ (See section 12.2.7 of the RX62N Group User's Manual for more information.) ๐ซถ
Okay so the default is to allow these instructions ๐
, but GCC can't reliably spot every situation where a string instruction might touch an I/O register, so it can't turn them off automatically ๐. That part's on you, bestie. If your program pokes at I/O space, you need to pass -mno-allow-string-insns yourself โจ.
When the instructions are on, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. When they're off, it defines __RX_DISALLOW_STRING_INSNS__ instead ๐ฆ.
-mjsr,-mno-jsrโ Use only (or not only)JSRinstructions to call functions ๐. This comes in handy when your code is bigger than whatBSRinstructions can reach ๐. Heads up,-mno-jsrdoesn't mean "never useJSR" ๐. It just means any kind of branch is fair game ๐.
Note: the generic GCC command-line option -ffixed-reg has a special vibe on the RX port when you pair it with the interrupt function attribute ๐. That attribute marks a function meant to handle fast interrupts โก. GCC makes sure it only touches r10, r11, r12 and/or r13, and only when the normal use of those registers has been restricted through the -ffixed-reg or -mint-register command-line options ๐ซถ.
๐ธ S/390 and zSeries Options ๐ธ
These are the -m options for the S/390 and zSeries architecture ๐.
-mhard-float,-msoft-floatโ Use (or skip) the hardware floating-point instructions and registers for floating-point math ๐ฅ. With-msoft-float, the functions inlibgcc.ado the floating-point work instead ๐ง. With-mhard-float, the compiler generates IEEE floating-point instructions ๐. Hard float is the default โจ.-mhard-dfp,-mno-hard-dfpโ Use (or skip) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐. With-mno-hard-dfp, the functions inlibgcc.ahandle decimal floating point ๐. With-mhard-dfp, the compiler generates the decimal-floating-point hardware instructions ๐ . This is the default for-march=z9-ecor higher ๐.-mlong-double-64,-mlong-double-128โ These switches control the size of thelong doubletype ๐. A size of 64 bits makeslong doublethe same asdouble๐ฆ. This is the default ๐ .-mbackchain,-mno-backchainโ Store (or don't store) the address of the caller's frame as a backchain pointer in the callee's stack frame ๐. A backchain can be needed to debug with tools that don't understand DWARF call frame information ๐. When-mno-packed-stackis in effect, the backchain pointer lives at the bottom of the stack frame ๐ชจ. When-mpacked-stackis in effect, the backchain goes into the topmost word of the 96/160 byte register save area ๐ซง.
Okay, so, code built with -mbackchain is call-compatible with code built with -mno-backchain ๐. Using the backchain for debugging usually means the whole binary has to be built with -mbackchain ๐ง.
โ ๏ธ The combination of-mbackchain,-mpacked-stackand-mhard-floatis not supported ๐. If you want to build a Linux kernel, use-msoft-float๐ง.
The default is to not maintain the backchain ๐.
-mpacked-stack,-mno-packed-stackโ Use (or skip) the packed stack layout ๐ฆ. With-mno-packed-stack, the compiler uses every field of the 96/160 byte register save area only for its default purpose ๐งธ. Unused fields still eat stack space ๐ญ. With-mpacked-stack, register save slots get densely packed at the top of the register save area ๐ฑ. Unused space gets reused for other things, which is way more efficient with the stack space ๐ง . But when-mbackchainis also in effect, the topmost word of the save area is always used for 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 made with -mpacked-stack is call-compatible with code made with -mno-packed-stack ๐ซถ. Heads up though, some non-FSF releases of GCC 2.95 for S/390 or zSeries generated code that uses the stack frame backchain at run time, not just for debugging ๐ฌ. That code isn't 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โ Generate (or don't generate) code that uses thebrasinstruction for subroutine calls ๐. This only works reliably if the total executable size doesn't go over 64k ๐. The default is to use thebasrinstruction instead, which doesn't have that limit ๐ .-m64,-m31โ With-m31, the compiler generates code compliant with the GNU/Linux for S/390 ABI ๐งฉ. With-m64, it generates code compliant with the GNU/Linux for zSeries ABI ๐. This lets GCC generate 64-bit instructions ๐. For the s390 targets, the default is-m31, while the s390x targets default to-m64โจ.-mzarch,-mesaโ With-mzarch, the compiler generates code using the instructions available on z/Architecture ๐ฆ. With-mesa, it uses the instructions available on ESA/390 ๐๏ธ. Heads up,-mesaisn't possible with-m64๐ โโ๏ธ. When generating GNU/Linux for S/390 ABI code, the default is-mesa. When generating GNU/Linux for zSeries ABI code, the default is-mzarch๐.-mhtm,-mno-htmโ The-mhtmoption turns on a set of builtins that use instructions from the transactional execution facility, introduced with the IBM zEnterprise EC12 machine generation ๐ง . These are the S/390 System z Built-in Functions ๐ฅ.-mhtmis on by default when you use-march=zEC12๐.-mvx,-mno-vxโ With-mvx, the compiler generates code using the instructions from the vector extension facility, introduced with the IBM z13 machine generation ๐. This option changes the ABI for some vector type values when it comes to alignment and calling conventions ๐. If vector type values are used in an ABI-relevant context, a GAS.gnu_attributecommand gets added to mark the resulting binary with the ABI it used ๐ท๏ธ.-mvxis on by default when you use-march=z13๐.-mzvector,-mno-zvectorโ The-mzvectoroption enables vector language extensions and builtins using instructions from the vector extension facility, introduced with the IBM z13 machine generation ๐ซ. It adds support forvectoras a keyword to define vector type variables and arguments ๐ง. Okay, thevectorkeyword is only available when GNU extensions are enabled ๐. It won't get expanded if you ask for strict standard compliance, like with-std=c99๐ซ. On top of the GCC low-level builtins,-mzvectorturns on a set of builtins added for compatibility with AltiVec-style implementations like Power and Cell ๐ฆ. To use these builtins, you need to include the header filevecintrin.h๐.-mzvectoris disabled by default ๐.-mmvcle,-mno-mvcleโ Generate (or don't generate) code using themvcleinstruction for block moves ๐. With-mno-mvcle, it uses anmvcloop instead ๐. This is the default unless you're optimizing for size ๐.-mdebug,-mno-debugโ Print (or don't print) extra debug information while compiling ๐. The default is to not print debug information ๐ โโ๏ธ.-march=cpu-typeโ Generate code that runs oncpu-type, which is the name of a system representing a certain processor type ๐ป. The possible values forcpu-typearez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12,z15/arch13, andnative๐. The default is-march=z900๐ธ. Specifyingnativeas the cpu type selects the best architecture option for the host processor ๐ง.-march=nativehas no effect if GCC doesn't recognize the processor ๐คทโโ๏ธ.-mtune=cpu-typeโ Tune everything applicable in the generated code tocpu-type, except for the ABI and the set of available instructions ๐ถ. The list ofcpu-typevalues is the same as for-march๐. The default is the value used for-march๐.-mtpf-trace,-mno-tpf-traceโ Generate code that adds (or doesn't add) TPF OS specific branches to trace routines in the operating system ๐ค๏ธ. This option is off by default, even when compiling for the TPF OS ๐.-mtpf-trace-skip,-mno-tpf-trace-skipโ Generate code that changes (or doesn't change) the default branch targets enabled by-mtpf-traceso they point to specialized trace routines ๐ฏ. Those routines let you selectively skip function trace entries for the TPF OS โญ๏ธ. This option is off by default, even when compiling for the TPF OS and specifying-mtpf-trace๐.-mfused-madd,-mno-fused-maddโ Generate code that uses (or doesn't use) the floating-point multiply and accumulate instructions โ๏ธโ. These instructions are generated by default if hardware floating point is used ๐ .-mwarn-framesize=framesizeโ Emit a warning if the current function exceeds the given frame size ๐จ. Because this is a compile-time check, it doesn't have to be a real problem when the program runs ๐งโโ๏ธ. It's meant to catch functions that most likely cause a stack overflow ๐ฑ. It's super useful in environments with a limited stack size, like the Linux kernel ๐ง.-mwarn-dynamicstackโ Emit a warning if the function callsallocaor uses dynamically-sized arrays ๐ข. This is generally a bad idea when the stack size is limited ๐.-mstack-guard=stack-guard,-mstack-size=stack-sizeโ okay so these two are a debugging duo ๐ต๏ธโโ๏ธ๐ On S/390, passing them makes the back end sneak extra instructions into the function prologue that trigger a trap if the stack size getsstack-guardbytes abovestack-size(remember, the S/390 stack grows downward, so keep that in mind ๐ง). If you skipstack-guard, GCC picks the smallest power of 2 that's larger than the frame size of the compiled function. These are meant for chasing stack overflow problems, but the extra code adds only little overhead, so it can even run on production-like systems without greater performance degradation โจ Just know the values have to be exact powers of 2,stack-sizehas to be greater thanstack-guardwithout going over64k, and the extra code assumes the stack starts at an address aligned to the value ofstack-size. Also,stack-guardcan only be used together withstack-size๐-mhotpatch=pre-halfwords,post-halfwordsโ this one is giving "hot-patching" vibes ๐ฅ When it's enabled, every function in the compilation unit gets a hot-patching prologue. The function label gets prepended withpre-halfwordstwo-byte NOP instructions (max1000000), and after the label,2 * post-halfwordsbytes get tacked on using the largest NOP-like instructions the architecture allows (max1000000). If both arguments are zero, hotpatching is disabled ๐ And you can override it for individual functions with thehotpatchattribute ๐
โจ Score Options โจ
These options are defined for Score implementations, bestie ๐ธ
-mebโ compile for big-endian mode. This is the default ๐-melโ compile for little-endian mode ๐ง-mnhwloopโ disable generation ofbcnzinstructions ๐-mulsโ enable generation of unaligned load and store instructions ๐ฆ-mmacโ enable multiply-accumulate instructions. Disabled by default, so you have to ask for it ๐-mscore5โ target the SCORE5 architecture ๐-mscore5uโ target the SCORE5U architecture ๐-mscore7โ target the SCORE7 architecture. This is the default ๐-mscore7dโ target the SCORE7D architecture ๐
๐ฆ SH Options ๐ฆ
These -m options are defined for the SH implementations, and they are a whole vibe ๐ญ
-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 is not 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 is not 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 in a way that the floating-point unit is not 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 in a way that the floating-point unit is not 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 is not 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, so it's just vibes for now ๐-mbโ compile for the processor in big-endian mode ๐-mlโ compile for the processor in little-endian mode ๐-mdalignโ align doubles at 64-bit boundaries ๐
Heads up, bestie:-mdalignchanges 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 inswitchtables. The default is 16-bit offsets ๐ธ-mbitopsโ enable bit manipulation instructions on SH2A ๐-mfmovdโ enable thefmovdinstruction. Check-mdalignfor alignment constraints ๐-mrenesasโ comply with the calling conventions defined by Renesas ๐-mno-renesasโ comply with the calling conventions GCC used before the Renesas conventions were available. This is the default for all targets of the SH toolchain ๐-mnomacsaveโ mark theMACregister as call-clobbered, even if-mrenesasis given ๐-mieee,-mno-ieeeโ control the IEEE compliance of floating-point comparisons, which affects how unordered comparison results get handled ๐ง By default,-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled,-mno-ieeeis implicitly set, which makes floating-point greater-equal and less-equal comparisons faster โก You can override either implicit setting by specifying-mieeeor-mno-ieeeyourself ๐-minline-ic_invalidateโ inline code that invalidates instruction cache entries after setting up nested function trampolines ๐ง This has no effect if-musermodeis in effect and your selected code generation option (like-m4) doesn't allow theicbiinstruction. If the selected option doesn't allowicbiand-musermodeisn't in effect, the inlined code pokes the instruction cache address array directly with an associative write. That means it needs privileged mode at run time, and it fails if the cache line was mapped via the TLB and has become unmapped ๐ญ
This one is a little spicy: it needs privileged mode at run time, and it fails if the cache line was mapped via the TLB and has since become unmapped ๐
-misizeโ dump instruction size and location in the assembly code ๐-mpadstructโ this option is deprecated ๐ It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI
Deprecated alert: -mpadstruct is on its way out, and it's incompatible with the SH ABI, so maybe leave it alone ๐
-matomic-model=modelโ sets the model of atomic operations, plus any additional parameters, as a comma-separated list. For details on the atomic built-in functions, see __atomic Builtins ๐ซถ These are the models and parameters that are supported:noneโ disable compiler-generated atomic sequences and emit library calls for atomic operations instead. This is the default if the target is notsh*-*-linux*๐soft-gusaโ generate GNU/Linux compatible gUSA software atomic sequences for the atomic built-in functions. These sequences need extra support from the system's interrupt/exception handling code and are only suitable for single-core SH3* and SH4* systems. This is enabled by default when the target issh*-*-linux*and the chip is SH3* or SH4*. When the target is SH4A, this option also partially uses the hardware atomic instructionsmovli.landmovco.lto make the code more efficient, unlessstrictis specified โจsoft-tcbโ generate software atomic sequences that use a variable in the thread control block. This is 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 using this model, thegbr-offset=parameter has to be specified as well ๐งsoft-imaskโ generate software atomic sequences that temporarily disable interrupts by settingSR.IMASK = 1111. This model only works when the program runs in privileged mode and is only suitable for single-core systems. It doesn't require extra support from the interrupt/exception handling code. This model is enabled by default when the target issh*-*-linux*and the chip is SH1* or SH2* ๐ธhard-llcsโ generate hardware atomic sequences using only themovli.landmovco.linstructions. This is only available on SH4A and is suitable for multi-core systems. Since the hardware instructions only support 32-bit atomic variable access, 8-bit and 16-bit variables are emulated with 32-bit accesses. Code compiled with this option is also compatible with other software atomic model interrupt/exception handling systems if it's executed on an SH4A system. This model doesn't require extra support from the interrupt/exception handling code ๐
gbr-offset=โ okay so this one sets the byte offset of the variable inside the thread control block structure that the generated atomic sequences should use, but only when the soft-tcb model is selected ๐ง For any other model it gets ignored, so no stress ๐ The value has to be an integer multiple of4and fall in the range0-1020๐strictโ this one is lowkey strict in the best way ๐ซถ It stops you from mixing multiple atomic models, even when they're compatible, and makes the compiler generate atomic sequences of the specified model only ๐ฅ-mtasโ this makes the compiler generate thetas.bopcode for__atomic_test_and_set๐ ngl it can drag your overall performance because of the operand cache line flushes thattas.bimplies, depending on your hardware and software setup ๐ญ On multi-core SH4A processors,tas.bneeds to be handled with caution, since it can cause data corruption with certain cache configurations ๐
Bestie, tas.b on multi-core SH4A can corrupt your data for certain cache configs. Be careful ๐
-mprefergotโ when you're generating position-independent code, this emits function calls through the Global Offset Table instead of the Procedure Linkage Table ๐ฆ-musermode,-mno-usermodeโ this one is about whether the compiler is allowed to generate privileged mode code ๐-musermodesays don't allow it, and-mno-usermodesays go ahead and allow it โจ Using-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 isSH1*orSH2*,-musermodehas no effect, since there's no user mode there ๐-multcost=numberโ sets the cost the compiler assumes for a multiply insn ๐ฅ-mdiv=strategyโ picks the division strategy for integer division operations ๐strategycan be one of these:call-div1โ calls a library function that uses the single-step division instructiondiv1to do the operation ๐ง Dividing by zero gives an unspecified result and doesn't trap ๐ This is the default except for SH4, SH2A, and SHcompact ๐call-fpโ calls a library function that does the operation in double precision floating point ๐ฆ Dividing by zero causes a floating-point exception ๐ This is the default for SHcompact with FPU ๐ If you specify this for targets without a double precision FPU, it 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 ๐ธ Dividing by zero gives an unspecified result and doesn't trap ๐ This is the default for SH4 โจ If you specify this for targets without dynamic shift instructions, it defaults tocall-div1๐
Oh, and if you don't specify a division strategy, the compiler picks the default based on the current target ๐ For SH2A, the default is to use the divs and divu instructions instead of library function calls ๐ฅ
-maccumulate-outgoing-argsโ reserves space once for outgoing arguments in the function prologue, instead of around each call ๐ง This is generally beneficial for performance and size ๐ It's also needed for unwinding, so the stack frame doesn't get changed around conditional code ๐ซถ-mdivsi3_libfunc=nameโ sets the name of the library function used for 32-bit signed division toname๐ It only affects the name used in the call division strategies, and the compiler still expects the same sets of input, output, and clobbered registers as if this option weren't there ๐-mfixed-range=register-rangeโ makes the compiler treat the given register range as fixed registers ๐ A fixed register is one the register allocator can't use, which is super useful when you're compiling kernel code ๐ A register range is written as 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 when it can ๐ If you don't specify it, the value is picked based on the processor type you're compiling for โจ-mzdcbranch,-mno-zdcbranchโ this is about whether zero displacement conditional branch instructionsbtandbfare fast ๐ With-mzdcbranch, the compiler prefers zero displacement branch code sequences ๐ It's enabled by default when generating code for SH4 and SH4A, and you can explicitly turn it off with-mno-zdcbranch๐-mcbranch-force-delay-slotโ forces the use of delay slots for conditional branches, which fills 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 found in the original SH7055 ๐ ๏ธ-mfused-madd,-mno-fused-maddโ generate code that does (or doesn't) use the floating-point multiply and accumulate instructions ๐ These 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โ lets you allow or disallow 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โ lets you allow or disallow the compiler from emitting thefsrrainstruction for reciprocal square root approximations โจ The option-mfsrramust be used in combination 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 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 โจ
-mimpure-text suppresses the "relocations remain against allocatable but non-writable sections" linker error message ๐ However, the necessary relocations trigger copy-on-write, and the shared object is not actually shared across processes ๐ Instead of using -mimpure-text, you should compile all source code with -fpic or -fPIC ๐ฅ
These switches are supported in addition to the above on Solaris 2 ๐
-pthreadsโ this is a synonym for-pthread๐
๐ SPARC Options ๐
These -m options are supported on the SPARC ๐
-mno-app-regs,-mapp-regsโ specify-mapp-regsto generate output using the global registers2through4, which the SPARC SVR4 ABI reserves for applications ๐ Like global register1, each of global registers2through4is then treated as an allocable register that gets clobbered by function calls ๐ง This is the default ๐ธ
To be fully SVR4 ABI-compliant (with some performance loss), specify -mno-app-regs ๐ซถ You should compile libraries and system software with this option ๐ฅ
-mflat,-mno-flatโ with-mflat, the compiler doesn't generate save/restore instructions and uses a "flat" or single register window model ๐ฆ This model is compatible with the regular register window model ๐ The local registers and the input registers (0--5) are still treated as "call-saved" registers and 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 containing floating-point instructions ๐ This is the default ๐-mno-fpu,-msoft-floatโ generates output containing library calls for floating point ๐
Warning: the requisite libraries aren't available for all SPARC targets ๐ญ Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation ๐ You 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 containing quad-word (long double) floating-point instructions ๐ฆ-msoft-quad-floatโ generates output containing library calls for quad-word (long double) floating-point instructions ๐ง The functions called are the ones specified in the SPARC ABI ๐ This is the default โจ
As of this writing, there are no SPARC implementations with hardware support for the quad-word floating-point instructions ๐ญ They all invoke a trap handler for one of these instructions, and then the trap handler emulates the effect of the instruction ๐ Because of that trap handler overhead, this is much slower than calling the ABI library routines ๐ Thus, the -msoft-quad-float option is the default ๐
-mno-unaligned-doubles,-munaligned-doublesโ assumes that doubles have 8-byte alignment ๐ธ This is the default ๐
-munaligned-doubles keeps doubles at 8-byte alignment only when they're tucked inside another type or have an absolute address. Otherwise, GCC gives them 4-byte alignment ๐ธ This dodges some rare compatibility drama with code from other compilers, but it's not the default because it costs performance, especially in floating-point code ๐ญ
-muser-mode,-mno-user-modeโ Okay so-muser-modemeans no code that can only run in supervisor mode gets generated ๐ This only matters for thecasainstruction emitted for the LEON3 processor. This is the default ๐-mfaster-structs,-mno-faster-structsโ With-mfaster-structs, GCC assumes structures should have 8-byte alignment โจ That lets structure assignment copies use pairs oflddandstdinstructions instead of twice as manyldandstpairs ๐ฅ
โ ๏ธ Big warning, bestie: this changed alignment directly violates the SPARC ABI ๐ So it's only for targets where the developer knows and accepts that the code isn't fully in line with the ABI rules.
-mstd-struct-return,-mno-std-struct-returnโ With-mstd-struct-return, GCC adds checking code to functions that return structures or unions ๐ It catches size mismatches between the two sides of a function call, 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โ Turns on Local Register Allocation ๐ง This has been the default for SPARC since GCC 7, so if you want the old Reload, you gotta pass-mno-lra๐ซถ-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for machine typecpu_type๐ The supported values arev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,leon5,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8๐
Native Solaris and GNU/Linux toolchains also support the value native, which picks the best architecture option for the host processor โจ -mcpu=native has no effect if GCC doesn't recognize the processor ๐คท
Default instruction scheduling parameters are used for values that pick an architecture instead of a specific implementation. Those are v7, v8, sparclite, sparclet and v9 ๐
Here's the lowdown on each architecture and the chips it covers ๐
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3,leon5sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of the SPARC architecture ๐ฆ With -mcpu=cypress, the compiler also optimizes for the Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series. It's also a good fit for the older SPARCStation 1, 2, IPX etc. ๐
With -mcpu=v8, GCC generates code for the V8 variant of the SPARC architecture ๐ 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, the compiler also optimizes for the SuperSPARC chip, as used in the SPARCStation 10, 1000 and 2000 series ๐
With -mcpu=sparclite, GCC generates code for the SPARClite variant of the SPARC architecture ๐ฅ 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 optimizes for the Fujitsu MB86934 chip, the more recent SPARClite with an FPU ๐
With -mcpu=sparclet, GCC generates code for the SPARClet variant of the SPARC architecture ๐ธ 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, the compiler also optimizes for the TEMIC SPARClet chip ๐ง
With -mcpu=v9, GCC generates code for the V9 variant of the SPARC architecture ๐ This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers and conditional move instructions. With -mcpu=ultrasparc, the compiler also optimizes for the Sun UltraSPARC I/II/IIi chips. With -mcpu=ultrasparc3, it optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips ๐
With -mcpu=niagara, it optimizes for Sun UltraSPARC T1 chips. With -mcpu=niagara2, it optimizes for Sun UltraSPARC T2 chips. With -mcpu=niagara3, it optimizes for Sun UltraSPARC T3 chips. With -mcpu=niagara4, it optimizes for Sun UltraSPARC T4 chips ๐ With -mcpu=niagara7, it optimizes for Oracle SPARC M7 chips. With -mcpu=m8, it optimizes for Oracle M8 chips โญ
-mtune=cpu_typeโ Sets the instruction scheduling parameters for machine typecpu_type, but unlike-mcpu=cpu_type, it does not touch the instruction set or register set ๐ซถ
The same values for -mcpu=cpu_type work for -mtune=cpu_type, but the only useful ones are those that pick 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 also be used โจ
-mv8plus,-mno-v8plusโ With-mv8plus, GCC generates code for the SPARC-V8+ ABI ๐ฆ The difference from the V8 ABI is that the global and out registers are 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โ With-mvis4, GCC generates code that takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mvis4when targeting a CPU that supports such instructions, like niagara-7 and later. Setting-mvis4also sets-mvis3,-mvis2and-mvis๐-mvis4b,-mno-vis4bโ With-mvis4b, GCC generates code that takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions, plus the extra VIS instructions introduced in the Oracle SPARC Architecture 2017 ๐ The default is-mvis4bwhen targeting a CPU that supports such instructions, like m8 and later. Setting-mvis4balso sets-mvis4,-mvis3,-mvis2and-mvis๐ซถ-mcbcond,-mno-cbcondโ With-mcbcond, GCC generates code that takes advantage of the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ The default is-mcbcondwhen targeting a CPU that supports such instructions, like Niagara-4 and later โจ-mfmaf,-mno-fmafโ With-mfmaf, GCC generates code that takes advantage of the UltraSPARC Fused Multiply-Add Floating-point instructions ๐ฅ The default is-mfmafwhen targeting a CPU that supports such instructions, like Niagara-3 and later ๐-mfsmuld,-mno-fsmuldโ With-mfsmuld, GCC generates code that takes advantage of 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 an FPU, except-mcpu=leon๐-mpopc,-mno-popcโ With-mpopc, GCC generates code that takes advantage of the UltraSPARC Population Count instruction ๐ธ The default is-mpopcwhen targeting a CPU that supports such an instruction, like Niagara-2 and later ๐-msubxc,-mno-subxcโ With-msubxc, GCC generates code that takes advantage of the UltraSPARC Subtract-Extended-with-Carry instruction ๐ง The default is-msubxcwhen targeting a CPU that supports such an instruction, like Niagara-7 and later ๐-mfix-at697fโ Enables the documented workaround for the single erratum of the Atmel AT697F processor (which is erratum #13 of the AT697E processor) ๐ง-mfix-ut699โ Enables the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor ๐ ๏ธ-mfix-ut700โ Enables the documented workaround for the back-to-back store errata of the UT699E/UT700 processor ๐ฉน-mfix-gr712rcโ Enables the documented workaround for the back-to-back store errata of the GR712RC processor ๐ท
On SPARC-V9 processors in 64-bit environments, you also get these -m options ๐โจ
-m32,-m64โ Generates code for a 32-bit or 64-bit environment ๐ The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits ๐-mcmodel=whichโ Sets the code model to one of these ๐งmedlowโ The Medium/Low code model: 64-bit addresses, and programs must be linked in the low 32 bits of memory ๐ธ Programs can be statically or dynamically linked ๐ฆmedmidโ The Medium/Middle code model: 64-bit addresses, and programs must be linked in the low 44 bits of memory ๐ The text and data segments must be less than 2GB in size, and the data segment must be located within 2GB of the text segment ๐ซถ
medanyโ ๐ The Medium/Anywhere code model! You get 64-bit addresses, and programs can be linked literally anywhere in memory. The catch: the text and data segments must each be under2GB, and the data segment has to sit within2GBof the text segment. ๐ซถembmedanyโ โจ The embedded version of Medium/Anywhere, for embedded systems. You still get 64-bit addresses and text and data segments under2GBeach, but both can start anywhere in memory, and that gets sorted out 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โ ๐ง Pick the memory model for the processor from one of these:defaultโ the default memory model for the processor and operating system, no drama.rmoโ Relaxed Memory Orderpsoโ Partial Store Ordertsoโ Total Store Orderscโ Sequential Consistency
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, and they're set in the processor's PSTATE.MM field. Very academic, very iconic. ๐
-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. You have to add that back whenever you make stack frame references. This is the default in 64-bit mode. Otherwise, GCC assumes there's no offset at all.
๐ Options for System V ๐
These additional options are available on System V Release 4 so they play nice with other compilers on those systems: ๐ฆ
-Gโ Creates a shared object. It's recommended to use-symbolicor-sharedinstead, bestie.-Qyโ Identifies the version of each tool the compiler used, and drops them into a.identassembler directive in the output. ๐-Qnโ Refrains from adding.identdirectives to the output file. This is the default, so you're already good. ๐-YP,dirsโ Searches the directoriesdirs, and no others, for libraries specified with-l. Strict guest list energy. ๐ช-Ym,dirโ Looks in the directorydirto find the M4 preprocessor. The assembler uses this one. ๐งฉ
๐ TILE-Gx Options ๐
These -m options are supported on the TILE-Gx: ๐
-mcmodel=smallโ Generates code for the small model. Direct calls can only reach500Min either direction. PC-relative addresses are32bits, but absolute addresses support the full address range. โจ-mcmodel=largeโ Generates code for the large model. No limits on call distance, PC-relative addresses, or absolute addresses. Main character energy. ๐-mcpu=nameโ Selects the CPU type to target. Right now the only supported type istilegx. ๐ฏ-m32,-m64โ Generates code for a 32-bit or 64-bit environment. The 32-bit environment setsint,long, and pointer to32bits. The 64-bit environment setsintto32bits, andlongand pointer to64bits. ๐-mbig-endian,-mlittle-endianโ Generates code in big or little endian mode, respectively. ๐ธ
๐ฆ TILEPro Options ๐ฆ
These -m options are supported on the TILEPro: ๐
-mcpu=nameโ Selects the CPU type to target. Right now the only supported type istilepro. ๐ฏ-m32โ Generates code for a 32-bit environment, which setsint,long, and pointer to32bits. This is the only supported behaviour, so the flag is basically ignored. Lowkey a little extra, but it's fine. ๐
๐ฅ V850 Options ๐ฅ
These -m options are defined for V850 implementations: ๐
-mlong-calls,-mno-long-callsโ Treats all calls as being far away (or near, for the-mno-version). If calls are assumed to be far away, the compiler always loads the function's address into a register and calls indirectly through that pointer. ๐-mno-ep,-mepโ Doesn't optimize (or does optimize) basic blocks that use the same index pointer4or more times to copy the pointer into theepregister, and then uses the shortersldandsstinstructions. The-mepoption is on by default if you optimize. โก-mno-prolog-function,-mprolog-functionโ Doesn't use (or does use) external functions to save and restore registers in the prologue and epilogue of a function. Those external functions are slower, but they take up 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. Right now, this just turns on-mepand-mprolog-function. ๐ค-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 to256bytes in total, with128bytes 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 to64kilobytes. ๐ท-mzda=nโ Puts static or global variables whose size isnbytes or less into the first32kilobytes of memory. ๐งธ-mv850โ Says the target processor is the V850. ๐ฏ-mv850e3v5โ Says the target processor is the V850E3V5. The preprocessor constant__v850e3v5__is defined if you use this option. ๐-mv850e2v4โ Says the target processor is the V850E3V5. This is an alias for-mv850e3v5, so it's the exact same vibe. ๐-mv850e2v3โ Says the target processor is the V850E2V3. The preprocessor constant__v850e2v3__is defined if you use this option. ๐ฆ-mv850e2โ Says the target processor is the V850E2. The preprocessor constant__v850e2__is defined if you use this option. ๐-mv850e1โ Says the target processor is the V850E1. The preprocessor constants__v850e1__and__v850e__are defined if you use this option. โจ-mv850esโ Says the target processor is the V850ES. This is an alias for-mv850e1. ๐-mv850eโ Says the target processor is the V850E. The preprocessor constant__v850e__is defined if you use this option. ๐
If none of -mv850, -mv850e, -mv850e1, -mv850e2, -mv850e2v3, or -mv850e3v5 are defined, then a default target processor gets chosen, and the matching __v850*__ preprocessor constant is defined. ๐คทโโ๏ธ
The preprocessor constants __v850 and __v851__ are always defined, no matter which processor variant you're targeting. ๐ซถ
-mdisable-callt,-mno-disable-calltโ Suppresses generation of theCALLTinstruction for thev850e,v850e1,v850e2,v850e2v3, andv850e3v5flavours 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. IfCALLTinstructions are being generated, then the C preprocessor symbol__V850_CALLT__is defined. ๐ต-mrelax,-mno-relaxโ Passes on (or doesn't 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 isn't 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, these rules apply:- Integer sized structures and unions are returned via a memory pointer rather than a register.
- Large structures and unions (more than
8bytes 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โ Enables support for the old GCC version of the V850 ABI. With this version, these rules apply:- Integer sized structures and unions are returned in register
r10. - Large structures and unions (more than
8bytes in size) are passed by reference. - Functions are aligned to
32-bit boundaries, unless you're optimizing for size. - The
-m8byte-aligncommand-line option is not supported. - The
-mdisable-calltcommand-line option is supported, but it's not enabled by default.
- Integer sized structures and unions are returned in register
When this version of the ABI is enabled, the C preprocessor symbol __V850_GCC_ABI__ is defined. ๐ฐ๏ธ
-m8byte-align,-mno-8byte-alignโ Enables support fordoubleandlong longtypes to be aligned on8-byte boundaries. By default, the alignment of all objects is restricted to at most4bytes. When-m8byte-alignis in effect, the C preprocessor symbol__V850_8BYTE_ALIGN__is defined. ๐-mbig-switchโ Generates code suitable for big switch tables. Only use this option if the assembler or linker complains about out of range branches within a switch table. ๐จ-mapp-regsโ Causesr2andr5to be used in the code the compiler generates. This setting is the default. ๐จ-mno-app-regsโ Causesr2andr5to be treated as fixed registers. ๐งฑ
๐ธ VAX Options ๐ธ
These -m options are defined for the VAX: ๐ผ
-munixโ Doesn't output certain jump instructions (likeaobleqand so on) that the Unix assembler for the VAX can't handle across long ranges. ๐ซ-mgnuโ Does output those jump instructions, on the assumption that the GNU assembler is being used. ๐-mgโ Outputs code for G-format floating-point numbers instead of D-format. ๐ข-mlra,-mno-lraโ Enables Local Register Allocation. This is still experimental for the VAX, so by default the compiler uses standard reload. ๐งช
๐ฆ Visium Options ๐ฆ
-mdebugโ A program that does file I/O and is destined to run on an MCM target should be linked with this option. It causes the librarieslibc.aandlibdebug.ato be linked. Run the program on the target under the control of the GDB remote debugging stub. ๐๐
-msim ๐
A program that does file I/O and is meant to run on the simulator should be linked with option. ๐ The page never names the option here, so just know it's the one that pulls in libc.a and libsim.a. โจ
-mfpu,-mhard-floatโ ๐ Generates code with floating-point instructions. This is the default. ๐ธ-mno-fpu,-msoft-floatโ ๐ Generates code that uses library calls for floating-point instead.
โ ๏ธ-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile your whole program with it. ๐ญ You also need to buildlibgcc.a(the library that ships with GCC) with-msoft-floatfor this to work.
-mcpu=cpu_typeโ ๐ฆ Sets the instruction set, register set, and instruction scheduling parameters for the machine typecpu_type. The supported values aremcm,gr5, andgr6.
mcm is just a synonym for gr5, kept around for backward compatibility. ๐ซถ
By default (unless it's configured otherwise), GCC generates code for the GR5 variant of the Visium architecture. โจ
With -mcpu=gr6, GCC generates code for the GR6 variant. The only difference from GR5 code is that the compiler will generate block move instructions. ๐ฅ
-mtune=cpu_typeโ ๐ง Sets the instruction scheduling parameters for the machine typecpu_type, but doesn't touch the instruction set or register set the way-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 from"main". By default it returns POSIX-style condition (e.g. error) codes instead. ๐-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 valid values forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers. ๐ That lastnooption disables"pragma pointer_size". ๐
๐ธ VxWorks Options ๐ธ
The options in this section are defined for all VxWorks targets. ๐ซถ Options specific to the target hardware are listed with the other options for that target. ๐ฆ
-mrtpโ ๐ง GCC can generate code for both VxWorks kernels and real time processes (RTPs). This option switches from the former to the latter. It also defines the preprocessor macro__RTP__. โจ-non-staticโ ๐ Links an RTP executable against shared libraries instead of 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 only 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 you picked. ๐ญ 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 compile time by figuring out the processor type of the machine doing the compiling. 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 matching micro-architecture level from the x86-64 psABI. On ABIs other than the x86-64 psABI, they select the same CPU features that the x86-64 psABI documents for that micro-architecture level. ๐ฆ
Since these cpu-type values don't have a corresponding -mtune setting, using -march with them enables generic tuning. ๐
If you want specific tuning, use -mtune=other-cpu-type with an appropriate other-cpu-type value. โจ
i386โ ๐ฆ The original Intel i386 CPU. ๐i486โ ๐ท The Intel i486 CPU. (No scheduling is implemented for this chip. ๐)i586,pentiumโ ๐ The Intel Pentium CPU with no MMX support. ๐lakemontโ ๐ฌ The Intel Lakemont MCU, based on the Intel Pentium CPU. โจpentium-mmxโ ๐น The Intel Pentium MMX CPU, based on the Pentium core with MMX instruction set support. ๐pentiumproโ ๐ The Intel Pentium Pro CPU. ๐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 instruction set support. ๐pentium3,pentium3mโ ๐ฅ The Intel Pentium III CPU, based on the Pentium Pro core with MMX and SSE instruction set support. โญpentium-mโ ๐ป The Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE and SSE2 instruction set support. It's used by Centrino notebooks. ๐ฆpentium4,pentium4mโ ๐ The Intel Pentium 4 CPU with MMX, SSE and SSE2 instruction set support. ๐prescottโ โจ An improved version of the Intel Pentium 4 CPU with MMX, SSE, SSE2 and SSE3 instruction set support. ๐ทnoconaโ ๐ An improved version of the Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2 and SSE3 instruction set support. ๐core2โ โ The Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. ๐ซถnehalemโ ๐ The Intel Nehalem CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and POPCNT instruction set support. ๐westmereโ ๐ The Intel Westmere CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES 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, AVX, AES 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, AVX, AES, 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, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2 and F16C instruction set support. ๐ฆbroadwellโ ๐ท The Intel Broadwell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED ADCX and PREFETCHW instruction set support. ๐skylakeโ ๐ The Intel Skylake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC and XSAVES instruction set support. ๐ฅbonnellโ ๐ญ The Intel Bonnell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. ๐ซงsilvermontโ โ๏ธ The Intel Silvermont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL and RDRND instruction set support. ๐goldmontโ ๐ฅ The Intel Goldmont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT and FSGSBASE instruction set support. ๐goldmont-plusโ ๐ฅ The Intel Goldmont Plus CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX and UMIP instruction set support. ๐tremontโ ๐ฒ The Intel Tremont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, UMIP, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE and WAITPKG instruction set support. ๐ฆknlโ ๐ The Intel Knight's Landing CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF, AVX512ER and AVX512CD instruction set support. ๐knmโ ๐ The Intel Knights Mill CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF, AVX512ER, AVX512CD, AVX5124VNNIW, AVX5124FMAPS and AVX512VPOPCNTDQ instruction set support. ๐skylake-avx512โ ๐๏ธ The Intel Skylake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ and AVX512CD instruction set support. ๐
cannonlakeโ okay bestie, this one is an Intel Cannonlake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA and UMIP instruction set support ๐โจicelake-clientโ the Intel Icelake Client CPU is giving 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES instruction set support ๐ธicelake-serverโ the server version of Icelake, the Intel Icelake Server CPU, comes with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES, PCONFIG and WBNOINVD instruction set support ๐ฅcascadelakeโ an Intel Cascadelake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD and AVX512VNNI instruction set support ๐cooperlakeโ this Intel cooperlake CPU is literally built with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI and AVX512BF16 instruction set support ๐ฆtigerlakeโ the Intel Tigerlake CPU is a whole vibe with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT and KEYLOCKER instruction set support ๐sapphirerapidsโ an Intel sapphirerapids CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI, AVX512BF16, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8 and AVX-VNNI instruction set support ๐alderlakeโ the Intel Alderlake CPU has 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, UMIP, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE, WAITPKG, ADCX, AVX, AVX2, BMI, BMI2, F16C, FMA, LZCNT, PCONFIG, PKU, VAES, VPCLMULQDQ, SERIALIZE, HRESET, KL, WIDEKL and AVX-VNNI instruction set support ๐งrocketlakeโ Intel Rocketlake CPU energy with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES instruction set support ๐k6โ the AMD K6 CPU, with MMX instruction set support. Vintage, but iconic ๐k6-2,k6-3โ improved versions of the AMD K6 CPU, with MMX and 3DNow! instruction set support. Glow-up era โจathlon,athlon-tbirdโ the AMD Athlon CPU with MMX, 3dNOW!, enhanced 3DNow! and SSE prefetch instructions support ๐ธathlon-4,athlon-xp,athlon-mpโ an improved AMD Athlon CPU with MMX, 3DNow!, enhanced 3DNow! and full SSE instruction set support. Main character upgrade ๐k8,opteron,athlon64,athlon-fxโ processors based on the AMD K8 core with x86-64 instruction set support, including the AMD Opteron, Athlon 64, and Athlon 64 FX processors. (This supersets MMX, SSE, SSE2, 3DNow!, enhanced 3DNow! and 64-bit instruction set extensions.) Iykyk ๐ฆk8-sse3,opteron-sse3,athlon64-sse3โ improved versions of AMD K8 cores with SSE3 instruction set support. Lowkey the sequel we needed ๐amdfam10,barcelonaโ CPUs based on AMD Family 10h cores with x86-64 instruction set support. (This supersets MMX, SSE, SSE2, SSE3, SSE4A, 3DNow!, enhanced 3DNow!, ABM and 64-bit instruction set extensions.) ๐ซถbdver1โ CPUs based on AMD Family 15h cores with x86-64 instruction set support. (This supersets FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.) ๐ฅbdver2โ AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, TBM, F16C, FMA, FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.) Upgrade energy ๐bdver3โ AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.) โจbdver4โ AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP, LWP, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.) Still slaying ๐znver1โ AMD Family 17h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, and 64-bit instruction set extensions.) ๐znver2โ AMD Family 17h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, and 64-bit instruction set extensions.) ๐ฆznver3โ AMD Family 19h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, and 64-bit instruction set extensions.) Newest in the group chat ๐btver1โ CPUs based on AMD Family 14h cores with x86-64 instruction set support. (This supersets MMX, SSE, SSE2, SSE3, SSSE3, SSE4A, CX16, ABM and 64-bit instruction set extensions.) ๐ธbtver2โ CPUs based on AMD Family 16h cores with x86-64 instruction set support. This includes MOVBE, F16C, BMI, AVX, PCLMUL, AES, SSE4.2, SSE4.1, CX16, ABM, SSE4A, SSSE3, SSE3, SSE2, SSE, MMX and 64-bit instruction set extensions. Ngl, very well-rounded ๐ซถwinchip-c6โ IDT WinChip C6 CPU, dealt with the same way as i486, with additional MMX instruction set support. Retro bestie ๐งธwinchip2โ IDT WinChip 2 CPU, dealt with the same way as i486, with additional MMX and 3DNow! instruction set support. Vintage but still vibing ๐c3โ VIA C3 CPU with MMX and 3DNow! instruction set support. (No scheduling is implemented for this chip.) ๐c3-2โ VIA C3-2 (Nehemiah/C5XL) CPU with MMX and SSE instruction set support. (No scheduling is implemented for this chip.) ๐c7โ VIA C7 (Esther) CPU with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.) ๐ฆsamuel-2โ VIA Eden Samuel 2 CPU with MMX and 3DNow! instruction set support. (No scheduling is implemented for this chip.) ๐nehemiahโ VIA Eden Nehemiah CPU with MMX and SSE instruction set support. (No scheduling is implemented for this chip.) ๐ธestherโ VIA Eden Esther CPU with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.) ๐งeden-x2โ VIA Eden X2 CPU with x86-64, MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.) ๐eden-x4โ VIA Eden X4 CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 instruction set support. (No scheduling is implemented for this chip.) Glow-up unlocked โจnanoโ generic VIA Nano CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.) ๐ซถnano-1000โ VIA Nano 1xxx CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.) ๐nano-2000โ VIA Nano 2xxx CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.) ๐nano-3000โ VIA Nano 3xxx CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.) Peak VIA era ๐nano-x2โ ๐ฆ VIA Nano Dual Core CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x4โ ๐ VIA Nano Quad Core CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)geodeโ ๐ธ AMD Geode embedded processor with MMX and 3DNow! instruction set support.
โจ -mtune=cpu-type โจ
okay so -mtune is about tuning everything in the generated code except the ABI and the set of available instructions ๐
Picking a specific cpu-type schedules things nicely for that exact chip, but the compiler still won't spit out code that can't run on the default machine type, unless you also use a -march=cpu-type option ๐ซถ For example, if GCC is configured for i686-pc-linux-gnu, then -mtune=pentium4 makes code tuned for Pentium 4 that still runs on i686 machines. iconic, honestly ๐ฅ
The choices for cpu-type are the same as for -march. On top of that, -mtune gets 2 extra choices ๐
genericโ ๐ Produces code optimized for the most common IA32/AMD64/EM64T processors. If you already know which 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, the behavior of this option changes. So if you upgrade to a newer GCC, the code generated by this option shifts to match whatever processors are most common when that GCC version gets released ๐ฆ
There is no -march=generic option, because -march is about the instruction set the compiler is allowed to use, and there's no generic instruction set that works for every processor. -mtune, on the other hand, is about the processor (or, in this case, the whole 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 will change. So if you upgrade to a newer GCC, the generated code will reflect the most current Intel processors at the time that version is released ๐ธ
There is no -march=intel option, because -march is about the instruction set the compiler can use, and there's no common instruction set that works for all processors. -mtune is about the processor (or, here, the collection of processors) the code is optimized for ๐
โจ -mcpu=cpu-type โจ
ngl this one is just a deprecated synonym for -mtune. Don't start new code with it ๐
โจ -mfpmath=unit โจ
This one decides what unit does your floating-point math ๐งฎ The choices for unit are:
387โ ๐ Uses the standard 387 floating-point coprocessor that's on the majority of chips, and emulates it otherwise. Code compiled this way runs almost everywhere ๐ The temporary results get computed in 80-bit precision instead of the precision the type asks for, so you can get slightly different results compared to most other chips. See-ffloat-storefor a more detailed description. This is the default choice for non-Darwin x86-32 targets.sseโ โญ Uses scalar floating-point instructions from the SSE instruction set. It's supported by Pentium III and newer chips, and on the AMD side by Athlon-4, Athlon XP and Athlon MP chips. The earlier version of SSE only does single-precision arithmetic, so double and extended-precision math still goes through 387. A later version, only on Pentium 4 and AMD x86-64 chips, handles double-precision arithmetic too ๐ฆ
For the x86-32 compiler, you have to use -march=cpu-type, -msse or -msse2 to enable the SSE extensions and make this option work. For the x86-64 compiler, those extensions are on by default ๐ซถ
The resulting code should be way faster in most cases and avoids the numerical instability problems of 387 code. Heads up though: it may break existing code that expects temporaries to be 80 bits ๐ญ
This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and for x86-32 targets with the SSE2 instruction set when -ffast-math is enabled ๐
sse,387,sse+387,bothโ ๐งช Tries to use both instruction sets at once. This effectively doubles the number of available registers, and on chips with separate execution units for 387 and SSE, it doubles the execution resources too. Use this one with care, because it's still experimental: the GCC register allocator doesn't model separate functional units well, which leads to unstable performance ๐
โจ -masm=dialect โจ
This makes the compiler output assembly instructions in the dialect you pick โ๏ธ It also decides which dialect is used for basic asm and extended asm. The supported choices (in dialect order) are att or intel. The default is att. Darwin does not support intel, sorry bestie ๐ฅบ
โจ -mieee-fp / -mno-ieee-fp โจ
These control whether or not the compiler uses IEEE floating-point comparisons. The IEEE ones correctly handle the case where the result of a comparison is unordered, which is lowkey important ๐
โจ -m80387 / -mhard-float โจ
Generates output containing 80387 instructions for floating point ๐ธ
โจ -mno-80387 / -msoft-float โจ
Generates output containing library calls for floating point instead ๐
Warning: the libraries you need are not part of GCC ๐จ Normally the facilities of the machine's usual C compiler get used, but that can't be done directly during cross-compilation. You have to set up your own suitable library functions for cross-compilation yourself. Be prepared!
On machines where a function returns floating-point results in the 80387 register stack, some floating-point opcodes might still get emitted even when -msoft-float is used ๐
โจ -mno-fp-ret-in-387 โจ
Do not use the FPU registers for function return values ๐ โโ๏ธ
The usual calling convention has functions return float and double values in an FPU register, even when there's no FPU at all. The idea is that the operating system should emulate the FPU ๐ง The option -mno-fp-ret-in-387 makes those values come back in ordinary CPU registers instead.
โจ -mno-fancy-math-387 โจ
Some 387 emulators don't support the sin, cos and sqrt instructions for the 387, so this option tells the compiler to avoid generating those instructions ๐ This option gets overridden when -march says the target CPU always has an FPU, since then the instruction doesn't need emulating. Also, these instructions aren't generated unless you also use the -funsafe-math-optimizations switch ๐ฆ
โจ -malign-double / -mno-align-double โจ
These control whether GCC aligns double, long double, and long long variables on a two-word boundary or a one-word boundary ๐ Aligning double variables on a two-word boundary makes code run a bit faster on a Pentium, at the cost of more memory ๐ง
On x86-64, -malign-double is enabled by default.
Warning: if you use the -malign-double switch, structures containing those types are aligned differently than the published application binary interface specifications for x86-32. They won't be binary compatible with structures in code compiled without that switch ๐ญ
โจ -m96bit-long-double / -m128bit-long-double โจ
These switches control the size of the long double type ๐ The x86-32 application binary interface says the size should be 96 bits, so -m96bit-long-double is the default in 32-bit mode.
Modern architectures (Pentium and newer) prefer long double to be aligned to an 8- or 16-byte boundary. In arrays or structures that follow the ABI, that's not possible. So -m128bit-long-double aligns long double to a 16-byte boundary by padding it with an extra 32-bit zero ๐
In the x86-64 compiler, -m128bit-long-double is the default, because its ABI says long double is aligned on a 16-byte boundary ๐
Notice that neither of these options gives you any extra precision over the x87 standard of 80 bits for a long double ๐
Warning: if you override the default 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 won't be binary-compatible with code compiled without that switch ๐จ
โจ -mlong-double-64 / -mlong-double-80 / -mlong-double-128 โจ
Same deal here: these switches control the size of the long double type ๐ A size of 64 bits makes long double equivalent to double. That's the default for the 32-bit Bionic C library. A size of 128 bits makes long double equivalent to __float128, and that's 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 โจ
This controls how GCC aligns variables ๐ฆ The supported values for type are:
compatโ uses an increased alignment value, and it's compatible with what GCC 4.8 and earlier used. 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โ ๐ฆ okay so when you pick-mcmodel=medium, any data object bigger than threshold gets tucked into the large data section. Every object linked into the binary has to agree on this number, and it defaults to65535โจ.-mrtdโ ๐ this one's a whole different function-calling convention. Functions with a fixed number of arguments return with theret numinstruction, which pops their arguments on the way out, so the caller saves one instruction ๐ซถ. You can give a single function thestdcallfunction attribute to call it this way, or use thecdeclattribute to override-mrtdfor that function ๐.
โ ๏ธ Warning, bestie ๐ญ: this calling convention is incompatible with the one normally used on Unix, so you cannot use it if you need to call libraries compiled with the Unix compiler.
Also, you must provide function prototypes for all functions that take variable numbers of arguments (including printf), or incorrect code gets generated for calls to those functions ๐.
In addition, seriously incorrect code results if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored ๐ง.)
-mregparm=numโ ๐ฅ controls how many registers get used to pass integer arguments. By default, no registers are used for arguments, and at most 3 registers can be used. You can tweak this for one specific function with theregparmfunction attribute ๐.
โ ๏ธ Warning: if you use this switch and num is nonzero, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules.
-msseregparmโ โจ uses SSE register passing conventions forfloatanddoublearguments and return values. You can control this for a specific function with thesseregparmfunction attribute ๐ฆ.
โ ๏ธ Warning: if you use this switch, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules.
-mvect8-ret-in-memโ ๐ returns 8-byte vectors in memory instead of MMX registers. This is the default on VxWorks, to match the ABI of the Sun Studio compilers until version 12. Only use this if you need to stay compatible with existing code made by those older compiler versions or older versions of GCC ๐.-mpc32โ ๐ธ sets 80387 floating-point precision to 32 bits. The significands of floating-point results get rounded to 24 bits (single precision).-mpc64โ ๐ธ sets 80387 floating-point precision to 64 bits. The significands of floating-point results get rounded to 53 bits (double precision).-mpc80โ ๐ sets 80387 floating-point precision to 80 bits. The significands of floating-point results get rounded to 64 bits (extended double precision). This is the default โจ.
When you use one of these, floating-point operations in higher precisions aren't available to the programmer unless you set the FPU control word explicitly ๐ง .
Setting the rounding to less than 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 suffer significant loss of accuracy, typically through so-called "catastrophic cancellation", when this option sets the precision below extended precision ๐ญ.
-mstackrealignโ ๐ง realigns the stack at entry. On x86, this option generates an alternate prologue and epilogue that realigns the run-time stack if necessary. It's how legacy code that keeps 4-byte stack alignment can 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โ ๐งฑ attempts to keep the stack boundary aligned to a 2 raised to num byte boundary. If you don't specify-mpreferred-stack-boundary, the default is4(16 bytes or 128 bits).
โ ๏ธ Warning: when generating code for the x86-64 architecture with SSE extensions disabled,-mpreferred-stack-boundary=3can be used to keep the stack boundary aligned to an 8 byte boundary. 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 (such as functions from a standard library) are called with a misaligned stack. In that case, SSE instructions may lead to misaligned memory access traps. Variable arguments are also 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. That includes 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 Streaming SIMD Extension (SSE) data type __m128 may not work properly if it isn't 16-byte aligned.
To make sure these values get proper alignment on the stack, the stack boundary has to be at least as aligned as whatever any value stored on the stack requires. Every function also has to be generated so it keeps the stack aligned. So calling a function compiled with a higher preferred stack boundary from 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 up extra stack space and generally increases code size. Code that's sensitive to stack space usage, like embedded systems and operating system kernels, may want to reduce the preferred alignment to -mpreferred-stack-boundary=2 ๐ง.
Now for the big ol' squad of instruction set switches. Each one of these turns on its own extension, and every single one has a matching -mno- buddy to turn it off ๐:
-mmmxโ ๐ unlocks this instruction set.-msseโ ๐ unlocks this instruction set.-msse2โ ๐ unlocks this instruction set.-msse3โ ๐ unlocks this instruction set.-mssse3โ ๐ unlocks this instruction set.-msse4โ ๐ unlocks this instruction set.-msse4aโ ๐ unlocks this instruction set.-msse4.1โ ๐ unlocks this instruction set.-msse4.2โ ๐ unlocks this instruction set.-mavxโ ๐ unlocks this instruction set.-mavx2โ ๐ unlocks this instruction set.-mavx512fโ ๐ unlocks this instruction set.-mavx512pfโ ๐ unlocks this instruction set.-mavx512erโ ๐ unlocks this instruction set.-mavx512cdโ ๐ unlocks this instruction set.-mavx512vlโ ๐ unlocks this instruction set.-mavx512bwโ ๐ unlocks this instruction set.-mavx512dqโ ๐ unlocks this instruction set.-mavx512ifmaโ ๐ unlocks this instruction set.-mavx512vbmiโ ๐ unlocks this instruction set.-mshaโ ๐ unlocks this instruction set.-maesโ ๐ unlocks this instruction set.-mpclmulโ ๐ unlocks this instruction set.-mclflushoptโ ๐ unlocks this instruction set.-mclwbโ ๐ unlocks this instruction set.-mfsgsbaseโ ๐ unlocks this instruction set.-mptwriteโ ๐ unlocks this instruction set.-mrdrndโ ๐ unlocks this instruction set.-mf16cโ ๐ unlocks this instruction set.-mfmaโ ๐ unlocks this instruction set.-mpconfigโ ๐ unlocks this instruction set.-mwbnoinvdโ ๐ unlocks this instruction set.-mfma4โ ๐ unlocks this instruction set.-mprfchwโ ๐ unlocks this instruction set.-mrdpidโ ๐ unlocks this instruction set.-mprefetchwt1โ ๐ unlocks this instruction set.-mrdseedโ ๐ unlocks this instruction set.-msgxโ ๐ unlocks this instruction set.-mxopโ ๐ unlocks this instruction set.-mlwpโ ๐ unlocks this instruction set.-m3dnowโ ๐ unlocks this instruction set.-m3dnowaโ ๐ unlocks this instruction set.-mpopcntโ ๐ unlocks this instruction set.-mabmโ ๐ unlocks this instruction set.-madxโ ๐ unlocks this instruction set.-mbmiโ ๐ unlocks this instruction set.-mbmi2โ ๐ unlocks this instruction set.-mlzcntโ ๐ unlocks this instruction set.-mfxsrโ ๐ unlocks this instruction set.-mxsaveโ ๐ unlocks this instruction set.-mxsaveoptโ ๐ unlocks this instruction set.-mxsavecโ ๐ unlocks this instruction set.-mxsavesโ ๐ unlocks this instruction set.-mrtmโ ๐ unlocks this instruction set.-mhleโ ๐ unlocks this instruction set.-mtbmโ ๐ unlocks this instruction set.-mmwaitxโ ๐ unlocks this instruction set.-mclzeroโ ๐ unlocks this instruction set.-mpkuโ ๐ unlocks this instruction set.-mavx512vbmi2โ ๐ unlocks this instruction set.-mavx512bf16โ ๐ unlocks this instruction set.-mavx512fp16โ ๐ unlocks this instruction set.-mgfniโ ๐ unlocks this instruction set.-mvaesโ ๐ unlocks this instruction set.-mwaitpkgโ ๐ unlocks this instruction set.-mvpclmulqdqโ ๐ unlocks this instruction set.-mavx512bitalgโ ๐ unlocks this instruction set.-mmovdiriโ ๐ unlocks this instruction set.-mmovdir64bโ ๐ unlocks this instruction set.-menqcmdโ ๐ unlocks this instruction set.-muintrโ ๐ unlocks this instruction set.-mtsxldtrkโ ๐ unlocks this instruction set.-mavx512vpopcntdqโ ๐ unlocks this instruction set.-mavx512vp2intersectโ ๐ unlocks this instruction set.-mavx5124fmapsโ ๐ unlocks this instruction set.-mavx512vnniโ ๐ unlocks this instruction set.-mavxvnniโ ๐ unlocks this instruction set.-mavx5124vnniwโ ๐ unlocks this instruction set.-mcldemoteโ ๐ unlocks this instruction set.-mserializeโ ๐ unlocks this instruction set.-mamx-tileโ ๐ unlocks this instruction set.-mamx-int8โ ๐ unlocks this instruction set.-mamx-bf16โ ๐ unlocks this instruction set.-mhresetโ ๐ unlocks this instruction set.-mklโ ๐ unlocks this instruction set.-mwideklโ ๐ unlocks this instruction set.
These switches enable the use of instructions in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF, 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, AVX512FP16 or CLDEMOTE extended instruction sets. Each has a corresponding -mno- option to disable use of these instructions ๐.
These extensions are also available as built-in functions: see x86 Built-in Functions, for details of the functions enabled and disabled by these switches ๐ง.
To generate SSE/SSE2 instructions automatically from floating-point code (as opposed to 387 instructions), see -mfpmath=sse โจ.
GCC depresses SSEx instructions when -mavx is used. Instead, it generates new AVX instructions or AVX equivalence for all SSEx instructions when needed ๐
.
These options enable GCC to use these extended instructions in generated code, even without -mfpmath=sse. Applications that perform run-time CPU detection must compile separate files for each supported architecture, using the appropriate flags. In particular, the file containing 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โ ๐๏ธ lets you do fine-grained control of x86 code generation features. feature-list is a comma separated list of feature names. See also-mdump-tune-features. When specified, a feature gets turned on if it isn't preceded with^, and turned off if it is ๐.
โ ๏ธ Warning: -mtune-ctrl=feature-list is intended to be used by GCC developers. Using it may lead to code paths not covered by testing, and can potentially result in compiler ICEs or runtime errors ๐.
-mno-defaultโ ๐งน tells GCC to turn off all tunable features. See also-mtune-ctrl=feature-listand-mdump-tune-features๐ธ.-mcldโ ๐ okay so this one tells GCC to slip acldinstruction into the prologue of any function that uses string instructions ๐. String instructions check theDFflag to decide whether they go forward (autoincrement) or backward (autodecrement) ๐ฆ. The ABI saysDFshould be cleared on function entry, but some operating systems forget to clear it in their exception dispatchers ๐. So the exception handler can get called withDFset, and then string instructions go the wrong direction ๐ญ. This can be turned on by default on 32-bit x86 targets if you configure GCC with the--enable-cldconfigure option. In that case you can still turn offcldgeneration with the-mno-cldcompiler option ๐ .-mvzeroupperโ โจ GCC drops avzeroupperinstruction right before control flow leaves the function โจ. This keeps the AVX to SSE transition penalty low ๐, and it also removes unnecessaryzeroupperintrinsics ๐งน.-mprefer-avx128โ ๐ธ tells the auto-vectorizer to use 128-bit AVX instructions instead of 256-bit AVX instructions ๐ธ.-mprefer-vector-width=optโ ๐ง tells GCC to use an opt-bit vector width in instructions instead of the default for the platform you picked ๐ง.-mmove-max=bitsโ ๐ฆ sets the max number of bits that can be moved from memory to memory efficiently to bits. The valid values are128,256and512.-mstore-max=bitsโ ๐ sets the max number of bits that can be stored to memory efficiently to bits. The valid values are128,256and512.
Here's the little value menu that sits right after that one ๐
noneโ no extra limits on GCC beyond whatever the selected platform already sets ๐.128โ prefer 128-bit vector width for instructions ๐.256โ prefer 256-bit vector width for instructions ๐.512โ prefer 512-bit vector width for instructions ๐.-mcx16โ ๐ lets GCC generateCMPXCHG16Binstructions in 64-bit code, so it can do compare-and-exchange on 16-byte aligned 128-bit objects ๐. This is super useful for atomic updates on data structures bigger than one machine word ๐ฅ. The compiler uses this instruction to implement__syncBuiltins. For__atomicBuiltins on 128-bit integers, though, it always uses a library call ๐.-msahfโ ๐ง enables generation ofSAHFinstructions in 64-bit code. Early Intel Pentium 4 CPUs with Intel 64 support, which came out 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,SAHFis used to optimize thefmod,drem, andremainderbuilt-in functions; see Other Builtins for details ๐.-mmovbeโ ๐ซถ enables use of themovbeinstruction to implement__builtin_bswap32and__builtin_bswap64.-mshstkโ ๐ก enables shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET).-mcrc32โ ๐ข enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32siand__builtin_ia32_crc32diso they generate thecrc32machine instruction.-mmwaitโ โณ enables the built-in functions__builtin_ia32_monitorand__builtin_ia32_mwaitso they generate themonitorandmwaitmachine instructions.-mrecipโ ๐ฎ enablesRCPSSandRSQRTSS(plus their vectorized friendsRCPPSandRSQRTPS) with an extra Newton-Raphson step for precision. They're used instead ofDIVSSandSQRTSS(and their vectorized versions) for single-precision floating-point arguments. These only get generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math. Heads up: the throughput of the sequence is higher than the non-reciprocal instruction's, but precision can drop by up to 2 ulp (like, the inverse of1.0comes out as0.99999994) ๐.
Note that GCC already implements 1.0f/sqrtf(x) in terms of RSQRTSS (or RSQRTPS) with -ffast-math (or the option combination above), so you don't need -mrecip for that ๐.
Also note that GCC already emits the above sequence with the extra Newton-Raphson step for vectorized single-float division and vectorized sqrtf(x) with -ffast-math (or the option combination above), so you don't need -mrecip for those either ๐.
-mrecip=optโ ๐ controls which reciprocal estimate instructions may be used. opt is a comma-separated list of options, and any of them 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โ ๐ specifies the ABI type to use when vectorizing intrinsics with an external library. Supported values for type aresvmlfor the Intel short vector math library andacmlfor the AMD math core library. To use this option, both-ftree-vectorizeand-funsafe-math-optimizationshave to be enabled, and an SVML or ACML ABI-compatible library has to be specified at link time ๐.
When -mveclibabi=svml is used, 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=acml is used, GCC currently 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 ๐งฎ.
-mabi=nameโ ๐ 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โ ๐งญ forces all calls to functions to be indirect. This is handy when using Intel Processor Trace, since it gives more precise timing info for function calls โฑ.-mmanual-endbrโ ๐ฏ inserts the ENDBR instruction at function entry only through thecf_checkfunction attribute. This is useful when used with-fcf-protection=branchto control ENDBR insertion at function entry.-mcall-ms2sysv-xloguesโ ๐งต because of differences between the 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function has to treat RSI, RDI and XMM6-15 as clobbered. By default, the code that saves and restores these registers is emitted inline, which makes the prologues and epilogues pretty lengthy ๐. Using-mcall-ms2sysv-xloguesemits prologues and epilogues that use stubs in the static portion of libgcc to do these saves and restores. That shrinks function size at the cost of a few extra instructions ๐ค.-mtls-dialect=typeโ ๐งถ generates code to access thread-local storage using thegnuorgnu2conventions.gnuis the conservative default.gnu2is more efficient, but it may add compile- and run-time requirements that can't be satisfied on all systems โ ๏ธ.-mpush-args,-mno-push-argsโ ๐ค uses PUSH operations to store outgoing parameters. This method is shorter and usually just as fast as the SUB/MOV method, and it's enabled by default. In some cases, disabling it may improve performance thanks to better scheduling and reduced dependencies ๐.-maccumulate-outgoing-argsโ ๐งบ if enabled, the maximum amount of space needed for outgoing arguments is 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 drawback is a notable increase in code size ๐ฌ. This switch implies-mno-push-args.-mthreadsโ ๐งต supports thread-safe exception handling on MinGW. Programs that rely on thread-safe exception handling must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT. When linking, it links in the special thread helper library-lmingwthrd, which cleans up per-thread exception-handling data ๐งน.-mms-bitfields,-mno-ms-bitfieldsโ ๐ enables or disables bit-field layout that's compatible with the native Microsoft Windows compiler.
If packed is used on a structure, or if bit-fields are used, the Microsoft ABI may lay out the structure differently than GCC normally does. Especially when moving packed data between functions compiled with GCC and the native Microsoft compiler (either via function call or as data in a file), you may need to access either format ๐ง.
This option is enabled by default for Microsoft Windows targets. You can also control it locally with variable or type attributes. For more information, see x86 Variable Attributes and x86 Type Attributes ๐.
The Microsoft structure layout algorithm is fairly simple, except for 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:
- Members line up in order ๐ง Structure members are stored sequentially in the order they're declared. The first member gets the lowest memory address and the last one gets the highest.
- Everything has an alignment requirement ๐ Every data object has one. For everything except structures, unions, and arrays, it's either the size of the object or the current packing size (set with the
"aligned"attribute or the"pack"pragma), whichever is less. For structures, unions, and arrays, it's the biggest alignment requirement among their members. Every object gets an offset so that:
offset % alignment_requirement == 0
- Bit-fields get cozy ๐งธ Adjacent bit-fields get packed into the same 1-, 2-, or 4-byte allocation unit if their integral types are the same size, and if the next bit-field fits into the current allocation unit without crossing the boundary set by the common alignment requirements of the bit-fields.
Now, MSVC has its own zero-length bit-field drama ๐ Here's how it handles them:
- If a zero-length bit-field gets inserted between two bit-fields that would normally be coalesced, those 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 the member that follows it,bar, thenbargets aligned as the type of the zero-length bit-field. ๐
For example:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For t2, bar is placed at offset 2, rather than offset 1. Accordingly, the size of t2 is 4. For t3, the zero-length bit-field does not affect the alignment of bar or, as a result, the size of the structure. โจ
Taking this into account, it is important to note the following:
- 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 is not 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 following non-bit-field members are ignored ๐ซ
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes. ๐ธ
-mno-align-stringopsโ Don't align the destination of inlined string operations ๐ โโ๏ธ This makes the code smaller and can speed things up when the destination is already aligned, but GCC doesn't know that's the case.-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 turns on way more inlining, which bumps up the code size but may improve performance for code that depends on fastmemcpyandmemsetfor short lengths. It also enables inline expansion ofstrlenfor all pointer alignments. ๐ฅ-minline-stringops-dynamicallyโ For string operations of unknown size, use run-time checks with inline code for small blocks and a library call for large blocks. ๐ง-mstringop-strategy=algโ Overrides the internal decision heuristic for which algorithm gets used when inlining string operations. The allowed values foralgare:rep_byte,rep_4byte,rep_8byteโ Expand using 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 if__builtin_memcpyshould be inlined, and which inline algorithm to use when the expected size of the copy operation is known.strategyis a comma-separated list ofalg:max_size:dest_aligntriplets.algis specified in-mstringop-strategy, andmax_sizesets the max byte size that the inline algorithmalgis allowed to handle. For the last triplet, themax_sizemust be-1. Themax_sizevalues in the list must go in increasing order. The minimal byte size foralgis 0 for the first triplet, andmax_size + 1of the preceding range for the rest. ๐-mmemset-strategy=strategyโ Basically the same vibe as-mmemcpy-strategy=, except this one controls__builtin_memsetexpansion. ๐-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions. This skips the instructions that save, set up, and restore frame pointers, and frees up an extra register in leaf functions. The option-fomit-leaf-frame-pointerremoves the frame pointer for leaf functions, which might make debugging harder. ๐-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ Controls whether TLS variables can be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer has to be added. Whether or not this is 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 the VEX prefix. The option-mavxturns this on by default. โจ-mfentry,-mno-fentryโ If profiling is active (-pg), put the profiling counter call before the prologue.
Note: On x86 architectures, the attributems_hook_prologueisn't possible at the moment for-mfentryand-pg. ๐
-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), generate a__mcount_locsection that contains pointers to each profiling call. This is useful for automatically patching out calls. ๐-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), generate the calls to the profiling functions as NOPs. This is useful when they should be patched in later, dynamically. This is likely only useful together with-mrecord-mcount. ๐-minstrument-return=typeโ Instruments function exit in-pg -mfentryinstrumented functions with a call to the specified function. This only instruments true returns ending withret, not sibling calls ending withjump. Valid types are:noneโ to not instrumentcallโ to generate a call to__return__nop5โ to generate a 5 byte nop
-mrecord-return,-mno-record-returnโ Generates a__return_locsection pointing to all return instrumentation code. ๐-mfentry-name=nameโ Sets the name of the__fentry__symbol that gets called at function entry for-pg -mfentryfunctions. ๐ท๏ธ-mfentry-section=nameโ Sets the name of the section where-mrecord-mcountcalls get recorded (default__mcount_loc). ๐๏ธ-mskip-rax-setup,-mno-skip-rax-setupโ When generating code for the x86-64 architecture with SSE extensions disabled,-mskip-rax-setupcan be used to skip setting up the RAX register when there are no variable arguments passed in vector registers.
Warning: The RAX register is used to avoid unnecessarily saving vector registers on the stack when passing variable arguments, so the impacts of this option 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 much faster than 32-bit/64-bit integer divide. This option generates a run-time check. If both the dividend and divisor are within the range of 0 to 255, 8-bit unsigned integer divide is used instead of 32-bit/64-bit integer divide. ๐๏ธ-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Splits 32-byte AVX unaligned loads and stores. ๐ช-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default). This option only has an effect when-fstack-protectoror-fstack-protector-allis specified. ๐ก๏ธ
With the latter choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset further specify which segment register (%fs or %gs) to use as the base register for reading the canary, and from what offset from that base register. The defaults for those are as specified in the relevant ABI. ๐งฉ
-mgeneral-regs-onlyโ Generates code that uses only the general-purpose registers. This stops the compiler from using floating-point, vector, mask, and bound registers. ๐ซถ-mrelax-cmpxchg-loopโ Relaxes thecmpxchgloop by emitting an early load and compare beforecmpxchg, and executingpauseif the loaded value isn't the one expected. This reduces excessive cache line bouncing, and it works for all atomic logic fetch builtins that generate a compare-and-swap loop. ๐
-mindirect-branch=choice
Okay so this one is about how indirect calls and jumps get handled ๐
-mindirect-branch=choice: Converts indirect calls and jumps usingchoice. The default iskeep, which leaves them totally unmodified ๐ฆthunkturns them into call and return thunks.thunk-inlineturns them into inlined call and return thunks.thunk-externturns them into external call and return thunks that live in a separate object file โจ You can control this for one specific function with the function attribute"indirect_branch"๐ซถ
Note that -mcmodel=large is incompatible with -mindirect-branch=thunk and -mindirect-branch=thunk-extern ๐ The thunk function may not be reachable in the large code model, so it's a no-go.
Note that -mindirect-branch=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐
-mfunction-return=choice: Converts function returns usingchoice. The default iskeep, which keeps returns unmodified ๐ธthunkturns function returns into call and return thunks.thunk-inlineturns them into inlined call and return thunks.thunk-externturns them into external call and return thunks provided in a separate object file. You can control this for one specific function with the function attribute"function_return"๐
Note that -mindirect-return=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check โจ
Note that -mcmodel=large is incompatible with -mfunction-return=thunk and -mfunction-return=thunk-extern ๐ Same deal as before: 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) usingchoice๐ก๏ธ The default isnone, which disables all SLS hardening.returnturns on SLS hardening for function returns.indirect-jmpturns it on for indirect jumps.allturns on every single bit of SLS hardening ๐-mindirect-branch-cs-prefix: Adds a CS prefix to call and jmp to an indirect thunk when the branch target is in the r8-r15 registers ๐ That makes the call and jmp instruction length 6 bytes, so they can be swapped at run-time forlfence; call *%r8-r15orlfence; jmp *%r8-r15๐ฅ
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 ๐-m32setsint,long, and pointer types to 32 bits, and generates code that runs on any i386 system ๐ธ-m64setsintto 32 bits andlongand pointer types to 64 bits, and generates code for the x86-64 architecture ๐ฆ For Darwin only,-m64also turns off the-fno-picand-mdynamic-no-picoptions ๐-mx32setsint,long, and pointer types to 32 bits, and generates code for the x86-64 architecture ๐-m16is the same as-m32, except it outputs the.code16gccassembly directive at the beginning 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 touch, 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 ๐ฃ 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 ๐ท The program is linked in the lower 2 GB of the address space, and small symbols are placed there too. Symbols with sizes larger than-mlarge-data-thresholdare put into large data or BSS sections and can be located above 2GB. Programs can be statically or dynamically linked.-mcmodel=large: Generates code for the large model ๐ This model 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. 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. 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 ๐ท๏ธ It tells you the micro-architecture ISA level required to execute the binary.-mno-direct-extern-access: Without-fpicor-fPIC, always use the GOT pointer to access external symbols ๐๏ธ With-fpicor-fPIC, treat access to protected symbols as local symbols. The default is-mdirect-extern-access.
Warning: shared libraries compiled with-mno-direct-extern-accessand executables compiled with-mdirect-extern-accessmay not be binary compatible if protected symbols are used in shared libraries and executables ๐จ Be careful, bestie!
โจ x86 Windows Options โจ
These additional options are available for Microsoft Windows targets ๐ช
-mconsole: Specifies that a console application is to be generated ๐ฅ๏ธ This is done by instructing the linker to set the PE header subsystem type required for console applications. This option is available for Cygwin and MinGW targets and is enabled by default on those targets ๐-mdll: Available for Cygwin and MinGW targets ๐งฉ It specifies that a DLL---a dynamic link library---is to be generated, which enables the selection of the required runtime startup object and entry point.-mnop-fun-dllimport: Available for Cygwin and MinGW targets ๐ It specifies that the"dllimport"attribute should be ignored.-mthreads: Available for MinGW targets ๐งต It specifies that MinGW-specific thread support is to be used.-municode: Available for MinGW-w64 targets ๐ It causes the"UNICODE"preprocessor macro to be predefined, and chooses Unicode-capable runtime startup code.-mwin32: Available for Cygwin and MinGW targets ๐ช It specifies that the typical Microsoft Windows predefined macros are set in the preprocessor, but it doesn't influence the choice of runtime library or startup code.-mwindows: Available for Cygwin and MinGW targets ๐จ It specifies that a GUI application is to be generated, by instructing the linker to set the PE header subsystem type appropriately.-fno-set-stack-executable: Available for MinGW targets ๐ It specifies that the executable flag for the stack used by nested functions isn't set. This is necessary for binaries running in kernel mode of Microsoft Windows, since the User32 API (which is used to set executable privileges) isn't available there.-fwritable-relocated-rdata: Available for MinGW and Cygwin targets โ๏ธ It specifies that relocated data in a read-only section is put into the".data"section. This is necessary for older runtimes that don't support modification of".rdata"sections for pseudo-relocation.-mpe-aligned-commons: Available for Cygwin and MinGW targets ๐ It specifies that the GNU extension to the PE file format, which permits the correct alignment of COMMON variables, should be used when generating code. It's enabled by default if GCC detects that the target assembler found during configuration supports the feature.
See also under x86 Options for standard options ๐
โจ Xstormy16 Options โจ
These options are defined for Xstormy16 โก
-msim: Chooses startup files and a linker script suitable for the simulator ๐ฎ
โจ Xtensa Options โจ
These options are supported for Xtensa targets ๐
-mconst16,-mno-const16: Enables or disables use ofCONST16instructions for loading constant values ๐ข TheCONST16instruction is currently not a standard option from Tensilica. When enabled,CONST16instructions are always used in place of the standardL32Rinstructions. The use ofCONST16is enabled by default only if theL32Rinstruction is not available.-mfused-madd,-mno-fused-madd: Enables or disables use of fused multiply/add and multiply/subtract instructions in the floating-point option ๐งฎ This has no effect if the floating-point option isn't also enabled. Disabling them forces the compiler to use separate instructions for the multiply and add/subtract operations. This can be desirable when strict IEEE 754-compliant results are required ๐ฏ The fused multiply add/subtract instructions don't round the intermediate result, so they produce results with more bits of precision than the IEEE standard specifies. Disabling them also ensures the program output isn't sensitive to the compiler's ability to combine multiply and add/subtract operations โจ-mserialize-volatile,-mno-serialize-volatile: When enabled, GCC insertsMEMWinstructions beforevolatilememory references to guarantee sequential consistency ๐ The default is-mserialize-volatile. Use-mno-serialize-volatileto omit theMEMWinstructions.-mforce-no-pic: For targets like GNU/Linux, where all user-mode Xtensa code must be position-independent code (PIC), this option disables PIC for compiling kernel code ๐-mtext-section-literals,-mno-text-section-literalsโ okay so these two control where literal pools end up ๐ง The default is-mno-text-section-literals, which tucks literals into their own separate section in the output file ๐ฆ That lets the literal pool sit in a data RAM/ROM, and it also lets the linker merge literal pools from separate object files to kill redundant literals and shrink code size ๐ With-mtext-section-literals, the literals get interspersed right in the text section so they stay as close as possible to their references ๐ฆ This may be necessary for large assembly files ๐ญ Literals for each function are placed right before that function โจ-mauto-litpools,-mno-auto-litpoolsโ these are the literal pool vibes again, but make it assembler-driven ๐ The default is-mno-auto-litpools, which puts literals in a separate section in the output file unless-mtext-section-literalsis used ๐ With-mauto-litpools, the assembler interleaves the literals into the text section itself ๐ง The compiler doesn't produce explicit.literaldirectives and loads literals into registers withMOVIinstructions instead ofL32R, so the assembler can do relaxation and place literals wherever they're needed ๐ This lets the assembler create several literal pools per function and assemble very big functions, which may not be possible with-mtext-section-literals๐ฅ-mtarget-align,-mno-target-alignโ when this is enabled, GCC tells the assembler to auto-align instructions so branch penalties go down ๐ฆ The tradeoff is a little less code density, but it's giving performance โจ The assembler tries to widen density instructions so branch targets and the instructions right aftercallinstructions 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 touch auto-aligned instructions likeLOOP, which the assembler always aligns either by widening density instructions or by insertingNOPinstructions ๐ซถ-mlongcalls,-mno-longcallsโ when enabled, GCC tells the assembler to turn direct calls into indirect calls, unless it can prove the target is within the range the call instruction allows ๐ This usually happens for calls to functions in other source files ๐ง Specifically, the assembler swaps a directCALLfor anL32Rfollowed by aCALLXinstruction ๐ The default is-mno-longcalls๐ Use this option in programs where the call target might be out of range ๐ญ Fun twist: this is handled in the assembler, not the compiler, so the assembly GCC generates still shows direct call instructions. Look at the disassembled object code to see what's actually running ๐ Also note that the assembler uses an indirect call for every cross-file call, not just the ones that really are out of range ๐-mabi=nameโ generate code for the specified ABI ๐ The permissible values arecall0andwindowedโจ If you don't pick one, the default ABI is chosen by the Xtensa core configuration ๐ซถ-mabi=call0โ the main character ABI ๐ Function parameters are passed in registersa2througha7, registersa12througha15are caller-saved, and registera15may be used as a frame pointer ๐ง When this version of the ABI is enabled, the C preprocessor symbol__XTENSA_CALL0_ABI__is defined ๐ธ-mabi=windowedโ the other main character ABI ๐ฆ Function parameters are passed in registersa10througha15, and 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 enabled, the C preprocessor symbol__XTENSA_WINDOWED_ABI__is defined โจ
๐ zSeries Options ๐
These are listed under
โจ ENVIRONMENT โจ
okay bestie, this is where GCC tells you which environment variables it's gonna listen to ๐. some of them point it at directories or prefixes to hunt for files, and others tweak the whole compilation vibe ๐
ngl you can also tell GCC where to search with options like -B, -I and -L. those take precedence over environment variables ๐ซถ, and environment variables take precedence over whatever the GCC configuration says ๐. main character energy for the flags, honestly.
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL ๐
these are the localization ones ๐. they let GCC work with different national conventions. GCC looks at the locale categories LC_CTYPE and LC_MESSAGES if it's been configured to do that, and they can be set to any value your installation supports ๐ง. a typical value is en_GB.UTF-8 for English in the United Kingdom encoded in UTF-8.
LC_CTYPEโ character classification ๐ค. GCC uses it to figure out the character boundaries in a string. this matters for some multibyte encodings that have quote and escape characters that would otherwise get read as a string end or an escape ๐ญ.LC_MESSAGESโ picks the language for diagnostic messages ๐ฌ.LC_ALLโ if it's set, it overridesLC_CTYPEandLC_MESSAGES๐. otherwise those two default to the value ofLANG. if none of these are set, GCC defaults to traditional C English behavior ๐.
LANG (yes, again) ๐
this one passes locale info to the compiler ๐
. one thing it's used for is deciding which character set to use when character literals, string literals and comments get parsed in C and C++. when the compiler is configured to allow multibyte characters, these values for LANG are recognized:
C-JISโ recognizes JIS characters.C-SJISโ recognizes SJIS characters.C-EUCJPโ recognizes EUCJP characters.
if LANG isn't defined, or it has some other value, the compiler uses "mblen" and "mbtowc" as defined by the default locale to recognize and translate multibyte characters ๐ฆ.
TMPDIR ๐๏ธ
if TMPDIR is set, it tells GCC which directory to use for temporary files ๐ธ. GCC makes temp files to hold the output of one stage of compilation that's gonna be the input for the next stage. for example, the output of the preprocessor is the input to the compiler proper.
GCC_COMPARE_DEBUG ๐
setting GCC_COMPARE_DEBUG is nearly the same as passing -fcompare-debug to the compiler driver โจ. check out the docs for that option for the full tea.
GCC_EXEC_PREFIX ๐ง
if GCC_EXEC_PREFIX is set, it specifies 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, but you can totally end your prefix with a slash if you want one.
if GCC_EXEC_PREFIX isn't set, GCC tries to figure out an appropriate prefix based on the pathname it was invoked with ๐. and if it can't find the subprogram using the prefix you gave it, it tries the usual places instead ๐.
the default value is prefix/lib/gcc/, where prefix is the prefix of the installed compiler. in lots of cases that prefix is whatever "prefix" was 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 that get used for linking ๐.
here's the unusual bit ๐ตโ๐ซ: the prefix also gets used to find the directories to search for header files. for each standard directory whose name normally begins with /usr/local/lib/gcc (more precisely, with the value of GCC_INCLUDE_DIR), GCC tries swapping that beginning out for the specified prefix to make an alternate directory name. so with -Bfoo/, GCC searches foo/bar just before it searches the standard directory /usr/local/lib/bar. and if a standard directory begins with the configured prefix, the value of prefix gets replaced by GCC_EXEC_PREFIX when GCC looks for header files ๐คฏ.
COMPILER_PATH ๐บ๏ธ
the value is a colon-separated list of directories, kinda like PATH ๐. GCC tries these directories when it's searching for subprograms, but only if it can't find them using GCC_EXEC_PREFIX.
LIBRARY_PATH ๐
also a colon-separated list of directories, much like PATH ๐. when GCC is configured as a native compiler, it tries these directories when searching for special linker files, but only if it can't find them using GCC_EXEC_PREFIX. linking with GCC also checks these directories for ordinary libraries when you use the -l option, though directories given with -L come first ๐ซถ.
GCC_EXTRA_DIAGNOSTIC_OUTPUT ๐ฅ
if this is set to one of the values below, extra text gets printed to stderr whenever fix-it hints get emitted ๐ฌ. -fdiagnostics-parseable-fixits and -fno-diagnostics-parseable-fixits take precedence over this env var, so they win if you use them.
fixits-v1โ emits parseable fix-it hints, same as-fdiagnostics-parseable-fixits. columns are counted as a number of bytes, starting at byte 1 for the initial column ๐ข.fixits-v2โ same asfixits-v1, except columns are display columns, as per-fdiagnostics-column-unit=display๐.
Some more environment variables affect the preprocessor's behavior ๐ง.
CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH ๐
each of these is a list of directories, separated by a special character, kinda like PATH, and they're where GCC looks for header files ๐. that special character is called "PATH_SEPARATOR" and it's decided when GCC gets built. on Microsoft Windows-based targets it's a semicolon, and on almost every other target it's a colon.
CPATH is searched as if you'd passed -I, but after any -I paths on the command line ๐ธ. this one gets used no matter which language is being preprocessed.
the other three only apply when preprocessing the particular language they're named for ๐. each one gets searched as if you'd passed -isystem, but after any -isystem paths on the command line.
in all of these, 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 example, if the value of CPATH is ":/special/include", that has the same effect as -I. -I/special/include ๐ฆ.
DEPENDENCIES_OUTPUT ๐งพ
if this is set, its value says how to output Make dependencies based on the non-system header files the compiler processed ๐ ๏ธ. system header files get ignored in the dependency output.
the value can just be a file name. in that case the Make rules get written to that file, and the target name gets guessed from the source file name. or the value can have the form file target, in which case the rules get written to file using target as the target name ๐ฏ.
basically this env var is the same as combining -MM and -MF, with an optional -MT switch too ๐
.
SUNPRO_DEPENDENCIES ๐
this is the same as DEPENDENCIES_OUTPUT, except system header files are not ignored. so it implies -M instead of -MM ๐. the dependence on the main input file is left out, though.
SOURCE_DATE_EPOCH โณ
if this is set, its value is a UNIX timestamp that replaces the current date and time in the __DATE__ and __TIME__ macros ๐ฐ๏ธ. that way the embedded timestamps are reproducible ๐.
the value has to be a UNIX timestamp, which is the number of seconds (not counting leap seconds) since 01 Jan 1970 00:00:00, written in ASCII. it's the same output as date +%s on GNU/Linux and other systems whose date command supports the %s extension โ.
the value should be a known timestamp, like the last modification time of the source or package, and it should be set by the build process ๐ ๏ธ.
โจ BUGS โจ
for instructions on reporting bugs, check out <file:///usr/share/doc/gcc-12/README.Bugs> ๐.
โจ FOOTNOTES โจ
- On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work. On multi-libbed systems,gcc -sharedmust select the correct support libraries to link against.
Failing to supply the correct flags may lead to subtle defects ๐ฑ. Supplying them in cases where they are not necessary is innocuous.
โจ SEE ALSO โจ
ok the reading list ๐: gpl(7), gfdl(7), fsf-funding(7), cpp(1), gcov(1), as(1), ld(1), gdb(1), dbx(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 all the contributors to GCC ๐ซถ.
โจ COPYRIGHT โจ
Copyright (c) 1988-2022 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. the Invariant Sections are "GNU General Public License" and "Funding Free Software", the Front-Cover texts are (a) (see below), and the Back-Cover Texts are (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." ๐
bestie, that's the whole ENVIRONMENT page ๐ from gcc-12, dated 2022-02-22. you're literally so ready for compiling now ๐ โจ
๐ฆ where this page comes from
- ubuntu jammy: g++-12-i686-linux-gnu 12-20220222-1ubuntu1cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms