GCC(1)
๐ GCC(1) ๐
Okay bestie, this is the GCC(1) page from the GNU manual, and it is giving everything for anyone who compiles C and C++ ๐ฅ
โจ 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...
Okay so this is only the most useful options ๐ธ The rest are waiting for you further down. And g++ accepts mostly the same options as gcc, so you're not learning a whole new vibe ๐ฆ
โจ DESCRIPTION โจ
When you invoke GCC, it normally does preprocessing, compilation, assembly, and linking, all in one go ๐ง The "overall options" let you stop this process at an intermediate stage. For example, -c says not to run the linker, so the output is the object files the assembler spits out ๐
Other options get passed on to one or more stages of processing. Some control the preprocessor, some control the compiler itself, and some control the assembler and linker. Most of those last ones aren't documented here, because you rarely need to touch them, so no stress ๐ซถ
Most of the command-line options you can use with GCC are useful for C programs. When an option is only useful with another language (usually C++), the explanation says so explicitly. If an option's description doesn't mention a source language, then you can use it with all supported languages โจ
The usual way to run GCC is to run the executable called gcc, or machine-gcc when cross-compiling, or machine-gcc-version if you want a specific version of GCC. When you compile C++ programs, you should invoke GCC as g++ instead ๐
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so multiple single-letter options cannot be grouped together. -dv is very different from -d -v, so don't try to be clever ๐
You can mix options and other arguments. For the most part, the order doesn't matter. Order does matter when you use several options of the same kind: if you specify -L more than once, the directories are searched in the order you specified them. Also, where you place the -l option is significant ๐
Lots of options have long names that start with -f or with -W, like -fmove-loop-invariants or -Wformat. Most of these have both positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one is not the default ๐
Some options take one or more arguments, typically separated from the option name either by a space or by the equals sign (=). Unless documented otherwise, an argument can be either numeric or a string. Numeric arguments must typically be small unsigned decimal or hexadecimal integers. Hexadecimal arguments must begin with the 0x prefix ๐
Arguments to options that specify a size threshold of some sort can be arbitrarily large decimal or hexadecimal integers, followed by a byte size suffix that designates a multiple of bytes. So you've got kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, GB and GiB for gigabyte and gigibyte, and so on. These arguments are called byte-size in the rest of the text. For the full listing and explanation of the binary and decimal byte size prefixes, check the NIST, IEC, and other relevant national and international standards ๐ค
โจ OPTIONS โจ
โจ Option Summary โจ
Here's a summary of all the options, grouped by type. The explanations live in the following sections, so keep scrolling ๐
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 -fgnu89-inline
-fpermitted-flt-eval-methods=standard -aux-info filename
-fallow-parameterless-variadic-functions -fno-asm -fno-builtin
-fno-builtin-function -fgimple -fhosted -ffreestanding -fopenacc
-fopenacc-dim=geom -fopenmp -fopenmp-simd -fms-extensions
-fplan9-extensions -fsso-struct=endianness -fallow-single-precision
-fcond-mismatch -flax-vector-conversions -fsigned-bitfields
-fsigned-char -funsigned-bitfields -funsigned-char
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 -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
-Wno-mismatched-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
โจ Warning Options โจ
okay bestie, this list is absolutely unhinged in length ๐ but I promise I'm lining up every single flag so nothing gets dropped ๐ซถ
-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 -Wno-attributes -Wattribute-alias=n
-Wno-attribute-alias -Wno-attribute-warning -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 -Wcast-align -Wcast-align=strict
-Wcast-function-type -Wcast-qual -Wchar-subscripts -Wclobbered
-Wcomment -Wconversion -Wno-coverage-mismatch -Wno-cpp
-Wdangling-else -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 -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
-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 crew ๐ is up next, and these flags are giving main character energy ๐
-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-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-array-index -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 only for C and Objective-C ๐ธ so if you're not writing those, you can just vibe past them ๐ซถ
-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 โจ
ok and last but not least, the debugging squad ๐ these are all the -g and -f flags that handle debug info, and they are a whole mood ๐ฆ
-g -glevel -gdwarf -gdwarf-version -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 BIG tuning list ๐ every single flag, zero cap
-faggressive-loop-optimizationsโ loops get a glow-up ๐ฅ-falign-functions[=n[:m:[n2[:m2]]]]โ function alignment, very precise ๐-falign-jumps[=n[:m:[n2[:m2]]]]โ jump target alignment ๐ฆ-falign-labels[=n[:m:[n2[:m2]]]]โ label alignment ๐ท๏ธ-falign-loops[=n[:m:[n2[:m2]]]]โ loop alignment ๐-fno-allocation-dceโ the no-thanks version of allocation cleanup ๐ โโ๏ธ-fallow-store-data-racesโ allowing store data races, โ ๏ธ spicy-fassociative-mathโ math reshuffling vibes ๐งฎ-fauto-profileโ auto profile, hands-off ๐ช-fauto-profile[=path]โ same, but you pick the path ๐-fauto-inc-decโ auto increment and decrement ๐ธ-fbranch-probabilitiesโ branch odds, bestie ๐ฒ-fcaller-savesโ caller saves, very responsible ๐-fcombine-stack-adjustmentsโ stack adjustments, combined ๐งฉ-fconserve-stackโ stack-saving mode ๐ฟ-fcompare-elimโ comparison elimination โ๏ธ-fcprop-registersโ register propagation ๐-fcrossjumpingโ crossjumping, iconic ๐ฆ-fcse-follow-jumpsโ CSE that follows the jumps ๐ฃ-fcse-skip-blocksโ CSE that skips blocks โญ๏ธ-fcx-fortran-rulesโ Fortran complex rules ๐-fcx-limited-rangeโ limited range for complex math ๐-fdata-sectionsโ data gets its own sections ๐๏ธ-fdceโ dead code elimination, bye bye ๐-fdelayed-branchโ delayed branches ๐ฐ๏ธ-fdelete-null-pointer-checksโ null pointer checks get deleted ๐-fdevirtualizeโ devirtualization โจ-fdevirtualize-speculativelyโ speculative devirtualization ๐ฎ-fdevirtualize-at-ltransโ devirtualize at LTRANS time ๐-fdseโ dead store elimination ๐งน-fearly-inliningโ inlining, early edition ๐-fipa-sraโ interprocedural SRA ๐ง-fexpensive-optimizationsโ the pricey-but-worth-it ones ๐-ffat-lto-objectsโ fat LTO objects ๐-ffast-mathโ fast math, โ ๏ธ not for the faint-hearted-ffinite-math-onlyโ finite math only, no infinities ๐ง-ffloat-storeโ float storage rules ๐พ-fexcess-precision=styleโ excess precision, your call ๐๏ธ-ffinite-loopsโ loops that are finite ๐-fforward-propagateโ forward propagation โก๏ธ-ffp-contract=styleโ floating-point contraction, pick a style ๐ชก-ffunction-sectionsโ functions get their own sections ๐งบ-fgcseโ global CSE ๐-fgcse-after-reloadโ global CSE after reload ๐-fgcse-lasโ GCSE load after store ๐๏ธ-fgcse-lmโ GCSE load motion ๐-fgraphite-identityโ Graphite identity transform ๐ชช-fgcse-smโ GCSE store motion ๐ฆ-fhoist-adjacent-loadsโ hoisting adjacent loads ๐๏ธ-fif-conversionโ if-conversion ๐-fif-conversion2โ if-conversion, round two ๐โจ-findirect-inliningโ inlining the indirect calls ๐ฏ-finline-functionsโ inline all the functions ๐-finline-functions-called-onceโ inline the once-only functions 1๏ธโฃ-finline-limit=nโ set the inline limit ton๐ง-finline-small-functionsโ inline the small ones ๐ฃ-fipa-modrefโ mod/ref analysis across functions ๐ช-fipa-cpโ interprocedural constant propagation ๐ฌ-fipa-cp-cloneโ constant propagation with clones ๐ฏ-fipa-bit-cpโ bit-level constant propagation ๐ข-fipa-vrpโ interprocedural value range propagation ๐-fipa-ptaโ interprocedural pointer analysis ๐งญ-fipa-profileโ interprocedural profile use ๐-fipa-pure-constโ pure and const function detection ๐ง-fipa-referenceโ reference analysis ๐-fipa-reference-addressableโ reference analysis for addressable stuff ๐ฌ-fipa-stack-alignmentโ stack alignment, interprocedural ๐-fipa-icfโ identical code folding ๐ญ-fira-algorithm=algorithmโ pick the IRA algorithm ๐งโ๐ฌ-flive-patching=levelโ live patching level ๐ฉน-fira-region=regionโ IRA region choice ๐บ๏ธ-fira-hoist-pressureโ hoist pressure, IRA style โฐ๏ธ-fira-loop-pressureโ loop pressure, IRA style ๐-fno-ira-share-save-slotsโ don't share save slots ๐-fno-ira-share-spill-slotsโ don't share spill slots ๐ โโ๏ธ-fisolate-erroneous-paths-dereferenceโ isolate erroneous dereference paths ๐ง-fisolate-erroneous-paths-attributeโ isolate erroneous paths by attribute ๐ท๏ธ-fivoptsโ induction variable optimizations ๐โจ-fkeep-inline-functionsโ keep the inline functions around ๐งธ-fkeep-static-functionsโ keep the static functions ๐งธ-fkeep-static-constsโ keep the static consts ๐-flimit-function-alignmentโ limit function alignment ๐-flive-range-shrinkageโ live range shrinkage ๐ค-floop-blockโ loop blocking ๐งฑ-floop-interchangeโ loop interchange ๐-floop-strip-mineโ loop strip mining ๐ช-floop-unroll-and-jamโ unroll and jam loops ๐ฏ-floop-nest-optimizeโ loop nest optimization ๐ช-floop-parallelize-allโ parallelize all the loops ๐งต-flra-rematโ LRA rematerialization ๐-fltoโ link-time optimization ๐-flto-compression-levelโ LTO compression level ๐๏ธ-flto-partition=algโ LTO partitioning algorithm ๐ฐ-fmerge-all-constantsโ merge all the constants ๐ค-fmerge-constantsโ merge constants ๐ค-fmodulo-schedโ modulo scheduling ๐ถ-fmodulo-sched-allow-regmovesโ modulo scheduling with register moves ๐-fmove-loop-invariantsโ move loop invariants out ๐-fno-branch-count-regโ no branch count register ๐-fno-defer-popโ don't defer pops ๐ โโ๏ธ-fno-fp-int-builtin-inexactโ no inexact floating-point to integer builtins ๐-fno-function-cseโ no CSE on function addresses ๐-fno-guess-branch-probabilityโ don't guess branch probabilities ๐ โโ๏ธ-fno-inlineโ no inlining at all ๐-fno-math-errnoโ no errno for math ๐ โโ๏ธ-fno-peepholeโ no peephole optimizer ๐-fno-peephole2โ no second peephole optimizer ๐ โโ๏ธ-fno-printf-return-valueโ no printf return value tracking ๐-fno-sched-interblockโ no interblock scheduling ๐ โโ๏ธ-fno-sched-specโ no speculative scheduling ๐-fno-signed-zerosโ no signed zeros ๐ โโ๏ธ-fno-toplevel-reorderโ no top-level reordering ๐-fno-trapping-mathโ no trapping math ๐ โโ๏ธ-fno-zero-initialized-in-bssโ no zero-initialized data in BSS ๐-fomit-frame-pointerโ omit the frame pointer ๐ซฅ-foptimize-sibling-callsโ optimize sibling calls ๐ฏโโ๏ธ-fpartial-inliningโ partial inlining ๐งฉ-fpeel-loopsโ peel loops ๐-fpredictive-commoningโ predictive commoning ๐ฎ-fprefetch-loop-arraysโ prefetch loop arrays ๐โโ๏ธ-fprofile-correctionโ profile correction ๐ฉบ-fprofile-useโ use profile data ๐-fprofile-use=pathโ use profile data from a path ๐-fprofile-partial-trainingโ partial training profiles ๐๏ธ-fprofile-valuesโ profile values ๐ข-fprofile-reorder-functionsโ reorder functions by profile ๐ช-freciprocal-mathโ reciprocal math ๐-freeโ FREE, the SSA-based redundancy elimination ๐ชถ-frename-registersโ rename registers ๐ท๏ธ-freorder-blocksโ reorder blocks ๐งฑ-freorder-blocks-algorithm=algorithmโ pick the block reordering algorithm ๐งฎ-freorder-blocks-and-partitionโ reorder blocks and partition ๐-freorder-functionsโ reorder functions ๐๏ธ-frerun-cse-after-loopโ rerun CSE after loops ๐-freschedule-modulo-scheduled-loopsโ reschedule modulo-scheduled loops ๐๏ธ-frounding-mathโ rounding math ๐ฏ-fsave-optimization-recordโ save the optimization record ๐-fsched2-use-superblocksโ second scheduler with superblocks ๐ฆธ-fsched-pressureโ scheduling pressure ๐ซ-fsched-spec-loadโ speculative loads in scheduling ๐-fsched-spec-load-dangerousโ dangerous speculative loads โ ๏ธ๐-fsched-stalled-insns-dep[=n]โ stalled insn dependencies ๐ง-fsched-stalled-insns[=n]โ stalled insns ๐ง-fsched-group-heuristicโ group heuristic ๐ฏ-fsched-critical-path-heuristicโ critical path heuristic ๐ค๏ธ-fsched-spec-insn-heuristicโ speculative insn heuristic ๐-fsched-rank-heuristicโ rank heuristic ๐ฅ-fsched-last-insn-heuristicโ last insn heuristic ๐-fsched-dep-count-heuristicโ dependency count heuristic ๐ข-fschedule-fusionโ schedule fusion ๐ซถ-fschedule-insnsโ schedule instructions ๐๏ธ-fschedule-insns2โ schedule instructions, round two ๐๏ธโจ-fsection-anchorsโ section anchors โ-fselective-schedulingโ selective scheduling ๐ฏ-fselective-scheduling2โ selective scheduling, round two ๐ฏโจ-fsel-sched-pipeliningโ selective scheduler pipelining ๐ฐ-fsel-sched-pipelining-outer-loopsโ selective pipelining for outer loops ๐ช-fsemantic-interpositionโ semantic interposition ๐ช-fshrink-wrapโ shrink-wrapping ๐-fshrink-wrap-separateโ separate shrink-wrapping ๐โจ-fsignaling-nansโ signaling NaNs ๐ก-fsingle-precision-constantโ single precision constants ๐ฌ-fsplit-ivs-in-unrollerโ split induction variables in the unroller โ๏ธ-fsplit-loopsโ split loops โ๏ธ-fsplit-pathsโ split paths ๐ฃ๏ธ-fsplit-wide-typesโ split wide types ๐งฉ-fsplit-wide-types-earlyโ split wide types early ๐งฉโฐ-fssa-backpropโ SSA backward propagation โฌ ๏ธ-fssa-phioptโ SSA PHI optimization ๐งฉ-fstdarg-optโ stdarg optimization ๐ญ-fstore-mergingโ store merging ๐ค-fstrict-aliasingโ strict aliasing ๐งฑ-fthread-jumpsโ thread jumps ๐งต-ftracerโ tracer, leaves a trail ๐พ-ftree-bit-ccpโ tree bit constant propagation ๐ข-ftree-builtin-call-dceโ dead code elimination for builtin calls ๐-ftree-ccpโ tree constant propagation ๐ฌ-ftree-chโ tree loop header copying ๐-ftree-coalesce-varsโ coalesce variables ๐ค-ftree-copy-propโ tree copy propagation ๐-ftree-dceโ tree dead code elimination ๐-ftree-dominator-optsโ dominator optimizations ๐-ftree-dseโ tree dead store elimination ๐งน-ftree-forwpropโ tree forward propagation โก๏ธ-ftree-freโ tree full redundancy elimination โป๏ธ-fcode-hoistingโ code hoisting ๐๏ธ-ftree-loop-if-convertโ loop if-conversion ๐-ftree-loop-imโ loop invariant motion ๐-ftree-phipropโ tree PHI propagation ๐งฉ-ftree-loop-distributionโ loop distribution ๐ฑ-ftree-loop-distribute-patternsโ distribute loop patterns ๐ฑโจ-ftree-loop-ivcanonโ canonicalize loop induction variables ๐-ftree-loop-linearโ linear loop transformations ๐-ftree-loop-optimizeโ tree loop optimizations ๐-ftree-loop-vectorizeโ loop vectorization ๐-ftree-parallelize-loops=nโ parallelize loops acrossnthreads ๐งต-ftree-preโ tree partial redundancy elimination ๐-ftree-partial-preโ tree partial PRE ๐โจ-ftree-ptaโ tree pointer analysis ๐งญ-ftree-reassocโ tree reassociation ๐ชข-ftree-scev-cpropโ SCEV constant propagation ๐ข-ftree-sinkโ tree sinking โฌ๏ธ-ftree-slsrโ straight-line strength reduction ๐ช-ftree-sraโ tree scalar replacement of aggregates ๐งฉ-ftree-switch-conversionโ switch conversion ๐-ftree-tail-mergeโ tail merging ๐ชก-ftree-terโ temporary expression replacement ๐-ftree-vectorizeโ tree vectorization ๐-ftree-vrpโ tree value range propagation ๐-funconstrained-commonsโ unconstrained commons ๐-funit-at-a-timeโ unit at a time ๐ฐ๏ธ-funroll-all-loopsโ unroll all the loops ๐๐-funroll-loopsโ unroll loops ๐-funsafe-math-optimizationsโ unsafe math optimizations, โ ๏ธ spicy-funswitch-loopsโ loop unswitching ๐-fipa-raโ interprocedural register allocation ๐ง-fvariable-expansion-in-unrollerโ variable expansion in the unroller ๐ฑ-fvect-cost-modelโ vectorizer cost model ๐ฐ-fvptโ value profile transformations ๐-fwebโ webs for registers ๐ธ๏ธ-fwhole-programโ whole program mode ๐-fwpaโ whole program analysis ๐ญ-fuse-linker-pluginโ use the linker plugin ๐-fzero-call-used-regsโ zero call-used registers ๐งน--param name=valueโ set a tuning parameter ๐๏ธ-Oโ the basic optimization knob โ๏ธ-O0โ no optimization, zero glow-up ๐ด-O1โ a little optimization ๐ฑ-O2โ more optimization ๐ท-O3โ the maximum-effort level ๐ฅ-Osโ optimize for size ๐ค-Ofastโ fast, โ ๏ธ bends the rules-Ogโ optimize for debugging ๐
โจ Program Instrumentation Options โจ
this is the section where GCC gets nosy and starts taking notes ๐๐
-pโ profiling ๐ธ-pgโ profiling with gprof ๐-fprofile-arcsโ arc profiling ๐น--coverageโ coverage ๐ง-ftest-coverageโ test coverage ๐งช-fprofile-abs-pathโ absolute profile paths ๐บ๏ธ-fprofile-dir=pathโ put profile data inpath๐-fprofile-generateโ generate profile data ๐ช-fprofile-generate=pathโ generate profile data intopath๐-fprofile-info-sectionโ profile info section ๐๏ธ-fprofile-info-section=nameโ profile info section with a name ๐ท๏ธ-fprofile-note=pathโ profile notes atpath๐-fprofile-prefix-path=pathโ profile prefix path ๐ค๏ธ-fprofile-update=methodโ profile update method ๐-fprofile-filter-files=regexโ include only files matchingregex๐-fprofile-exclude-files=regexโ exclude files matchingregex๐-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ reproducible profiles, pick a mode ๐-fsanitize=styleโ sanitizer, pick a style ๐งผ-fsanitize-recoverโ sanitizer recovery ๐ฉน-fsanitize-recover=styleโ sanitizer recovery, pick a style ๐ฉนโจ-fasan-shadow-offset=numberโ ASan shadow offset ๐-fsanitize-sections=s1,s2,...โ sanitize these sections ๐งบ-fsanitize-undefined-trap-on-errorโ trap on undefined behaviour errors ๐ชค-fbounds-checkโ bounds checking ๐ง-fcf-protection=[full|branch|return|none|check]โ control-flow protection, pick a level ๐ก๏ธ-fstack-protectorโ stack protector ๐ก๏ธ-fstack-protector-allโ stack protector for everything ๐ก๏ธโจ-fstack-protector-strongโ stack protector, strong edition ๐ช-fstack-protector-explicitโ stack protector, explicit only ๐ฏ-fstack-checkโ stack checking ๐-fstack-limit-register=regโ stack limit register ๐-fstack-limit-symbol=symโ stack limit symbol ๐ท๏ธ-fno-stack-limitโ no stack limit ๐-fsplit-stackโ split stack ๐งต-fvtable-verify=[std|preinit|none]โ vtable verification, pick a mode ๐ชช-fvtv-countsโ vtable verification counts ๐ข-fvtv-debugโ vtable verification debugging ๐-finstrument-functionsโ instrument functions ๐ฌ-finstrument-functions-exclude-function-list=sym,sym,...โ skip these functions when instrumenting ๐-finstrument-functions-exclude-file-list=file,file,...โ skip these files when instrumenting ๐
โจ Preprocessor Options โจ
the preprocessor is basically the prep team before the main show ๐
-Aquestion=answerโ assert something ๐งพ-A-question[=answer]โ un-assert something ๐งพ-Cโ keep comments ๐ฌ-CCโ keep comments, even the sneaky ones ๐ฌโจ-Dmacro[=defn]โ define a macro ๐งฉ-dDโ dump defines ๐-dIโ dump includes ๐-dMโ dump macros ๐-dNโ dump names ๐-dUโ dump undefined macros ๐-fdebug-cppโ preprocessor debugging ๐-fdirectives-onlyโ directives only ๐ฏ-fdollars-in-identifiersโ dollar signs in identifiers ๐ฒ-fexec-charset=charsetโ execution character set ๐ค-fextended-identifiersโ extended identifiers ๐-finput-charset=charsetโ input character set ๐ค-flarge-source-filesโ large source files ๐-fmacro-prefix-map=old=newโ map macro prefixes fromoldtonew๐บ๏ธ-fmax-include-depth=depthโ max include depth ๐ช-fno-canonical-system-headersโ don't canonicalize system headers ๐-fpch-depsโ precompiled header dependencies ๐งฑ-fpch-preprocessโ precompiled header preprocessing ๐งฑโจ-fpreprocessedโ already preprocessed ๐ฅก-ftabstop=widthโ tab stop width ๐-ftrack-macro-expansionโ track macro expansion ๐ต๏ธ-fwide-exec-charset=charsetโ wide execution character set ๐คโจ-fworking-directoryโ working directory ๐-Hโ show the header chain ๐-imacros fileโ include macros fromfile๐ฅ-include fileโ includefilefirst ๐ฅ-Mโ output make dependencies ๐ ๏ธ-MDโ make dependencies, written to a file too ๐ ๏ธ๐-MFโ name the dependency file ๐ท๏ธ-MGโ treat missing headers as generated ๐งพ-MMโ make dependencies, skipping system headers ๐ ๏ธ-MMDโ like-MD, skipping system headers ๐ ๏ธ๐-MPโ phony targets for headers ๐ป-MQโ quoted make target ๐-MTโ make target name ๐ฏ-Mno-modulesโ no modules ๐-no-integrated-cppโ no integrated preprocessor ๐ โโ๏ธ-Pโ no line markers ๐งน-pthreadโ POSIX threads ๐งต-remapโ remap filenames ๐บ๏ธ-traditionalโ traditional preprocessing, very vintage ๐ผ-traditional-cppโ traditional C preprocessor ๐ผโจ-trigraphsโ trigraphs ๐บ-Umacroโ undefine a macro ๐๏ธ-undefโ undefine all the things ๐ฅ-Wp,optionโ passoptionto the preprocessor ๐-Xpreprocessor optionโ passoptionto the preprocessor ๐โจ
โจ Assembler Options โจ
short and sweet, just two of 'em ๐
-Wa,optionโ passoptionto the assembler ๐งต-Xassembler optionโ passoptionto the assembler ๐งตโจ
โจ Linker Options โจ
the linker is where everything comes together and clicks ๐๐
object-file-nameโ an object file to link ๐ฆ-fuse-ld=linkerโ pick the linker ๐-llibraryโ link againstlibrary๐-nostartfilesโ no startup files ๐ซ-nodefaultlibsโ no default libraries ๐ซ๐-nolibcโ no C library ๐ซ-nostdlibโ no standard libraries or startup files at all ๐ซโจ-e entryโ set the entry point toentry๐ช--entry=entryโ same entry point, long form ๐ชโจ-pieโ position-independent executable ๐ซง-pthreadโ POSIX threads ๐งต-rโ relocatable output ๐-rdynamicโ export dynamic symbols ๐ค-sโ strip the output ๐ช-staticโ static linking ๐งฑ-static-pieโ static position-independent executable ๐ซง๐งฑ-static-libgccโ static libgcc ๐งฑ-static-libstdc++โ static libstdc++ ๐งฑ-static-libasanโ static libasan ๐งฑ-static-libtsanโ static libtsan ๐งฑ-static-liblsanโ static liblsan ๐งฑ-static-libubsanโ static libubsan ๐งฑ-sharedโ make a shared library ๐ค-shared-libgccโ shared libgcc ๐ค-symbolicโ bind symbols locally ๐ช-T scriptโ use linkerscript๐-Wl,optionโ passoptionto the linker ๐-Xlinker optionโ passoptionto the linker ๐โจ-u symbolโ treatsymbolas undefined ๐ป-z keywordโ pass thekeywordoption to the linker ๐๏ธ
โจ Directory Options โจ
where should GCC look? bestie gives it directions ๐บ๏ธโจ
-Bprefixโ search prefix ๐งญ-Idirโ adddirto the include search path ๐-I-โ the old-I-behaviour ๐-idirafter dirโ searchdirafter the others ๐ฐ๏ธ-imacros fileโ macros fromfile๐ฅ-imultilib dirโ multilib directory ๐-iplugindir=dirโ plugin directory ๐-iprefix fileโ prefix for include directories ๐งพ-iquote dirโ quote-only include directory ๐ฌ-isysroot dirโ system rootdir๐-isystem dirโ system include directorydir๐๏ธ-iwithprefix dirโ includedirunder the prefix ๐งพ-iwithprefixbefore dirโ includedirunder the prefix, searched earlier ๐งพโจ-Ldirโ library search directorydir๐-no-canonical-prefixesโ no canonical prefixes ๐--no-sysroot-suffixโ no sysroot suffix ๐ โโ๏ธ-nostdincโ no standard include directories ๐ซ-nostdinc++โ no standard C++ include directories ๐ซโจ--sysroot=dirโ set the sysroot todir๐
โจ Code Generation Options โจ
this is where the machine code gets its whole personality ๐ค๐
-fcall-saved-regโ call-saved register ๐ซถ-fcall-used-regโ call-used register ๐ซถโจ-ffixed-regโ fixed register ๐-fexceptionsโ exceptions ๐งจ-fnon-call-exceptionsโ non-call exceptions ๐งจโจ-fdelete-dead-exceptionsโ delete dead exceptions ๐-funwind-tablesโ unwind tables ๐ช-fasynchronous-unwind-tablesโ asynchronous unwind tables ๐ชโฐ-fno-gnu-uniqueโ no GNU unique symbols ๐-finhibit-size-directiveโ inhibit size directive ๐ค-fcommonโ common symbols ๐ค-fno-identโ no ident ๐-fpcc-struct-returnโ PCC struct return ๐งพ-fpicโ position-independent code ๐ซง-fPICโ position-independent code, big edition ๐ซงโจ-fpieโ position-independent executable code ๐ซง-fPIEโ position-independent executable, big edition ๐ซงโจ-fno-pltโ no PLT ๐-fno-jump-tablesโ no jump tables ๐-fno-bit-testsโ no bit tests ๐ โโ๏ธ-frecord-gcc-switchesโ record GCC switches ๐-freg-struct-returnโ register struct return ๐งพ-fshort-enumsโ short enums ๐ชถ-fshort-wcharโ shortwchar_t๐ชถ-fverbose-asmโ verbose assembly ๐ฃ๏ธ-fpack-struct[=n]โ pack structs ๐ฆ-fleading-underscoreโ leading underscore ๐ซข-ftls-model=modelโ thread-local storage model ๐งต-fstack-reuse=reuse_levelโ stack reuse level โป๏ธ-ftrampolinesโ trampolines ๐คธ-ftrapvโ trap on signed overflow ๐ชค-fwrapvโ wrap on signed overflow ๐-fvisibility=[default|internal|hidden|protected]โ symbol visibility, pick one ๐-fstrict-volatile-bitfieldsโ strict volatile bitfields ๐งฑ-fsync-libcallsโ sync libcalls ๐
โจ Developer Options โจ
the developer zone, bestie. this is where the debugging magic lives ๐ช๐
-dlettersโ dump letters ๐ค-dumpspecsโ dump the specs ๐-dumpmachineโ dump the machine name ๐ฅ๏ธ-dumpversionโ dump the version ๐ท๏ธ-dumpfullversionโ dump the full version ๐ท๏ธโจ-fcallgraph-info[=su,da]โ call graph info ๐ธ๏ธ-fcheckingโ checking ๐-fchecking=nโ checking at leveln๐โจ-fdbg-cnt-listโ debug counter list ๐ข-fdbg-cnt=counter-value-listโ debug counter values ๐ขโจ-fdisable-ipa-pass_nameโ disable an IPA pass ๐ซ-fdisable-rtl-pass_nameโ disable an RTL pass ๐ซ-fdisable-rtl-pass-name=range-listโ disable RTL passes in a range list ๐ซโจ-fdisable-tree-pass_nameโ disable a tree pass ๐ซ-fdisable-tree-pass-name=range-listโ disable tree passes in a range list ๐ซโจ-fdump-debugโ dump debug info ๐-fdump-earlydebugโ dump early debug info ๐โฐ-fdump-noaddrโ dump without addresses ๐-fdump-unnumberedโ dump unnumbered ๐ข-fdump-unnumbered-linksโ dump unnumbered links ๐-fdump-final-insns[=file]โ dump the final insns ๐งพ-fdump-ipa-allโ dump all IPA info ๐๏ธ-fdump-ipa-cgraphโ dump the IPA call graph ๐ธ๏ธ-fdump-ipa-inlineโ dump IPA inlining ๐๏ธ-fdump-lang-allโ dump all language info ๐๏ธ-fdump-lang-switchโ dump language switch ๐-fdump-lang-switch-optionsโ dump language switch options ๐โจ-fdump-lang-switch-options=filenameโ dump language switch options tofilename๐๐-fdump-passesโ dump passes ๐๏ธ-fdump-rtl-passโ dump an RTL pass ๐๏ธ-fdump-rtl-pass=filenameโ dump an RTL pass tofilename๐๏ธ๐-fdump-statisticsโ dump statistics ๐-fdump-tree-allโ dump all tree info ๐ณ-fdump-tree-switchโ dump tree switch ๐ณ๐-fdump-tree-switch-optionsโ dump tree switch options ๐ณ๐โจ-fdump-tree-switch-options=filenameโ dump tree switch options tofilename๐ณ๐-fcompare-debug[=opts]โ compare debug output ๐-fcompare-debug-secondโ compare debug output, second run ๐โจ-fenable-kind-passโ enable a kind of pass โ-fenable-kind-pass=range-listโ enable passes in a range list โ โจ-fira-verbose=nโ IRA verbosity at leveln๐ฃ๏ธ-flto-reportโ LTO report ๐-flto-report-wpaโ LTO WPA report ๐๐ญ-fmem-report-wpaโ memory report for WPA ๐ง ๐ญ-fmem-reportโ memory report ๐ง-fpre-ipa-mem-reportโ memory report before IPA ๐ง โช-fpost-ipa-mem-reportโ memory report after IPA ๐ง โฉ-fopt-infoโ optimization info ๐ก-fopt-info-options[=file]โ optimization info options ๐กโจ-fprofile-reportโ profile report ๐-frandom-seed=stringโ random seed ๐ฒ-fsched-verbose=nโ scheduler verbosity at leveln๐ฃ๏ธ-fsel-sched-verboseโ selective scheduler verbose ๐ฃ๏ธ-fsel-sched-dump-cfgโ selective scheduler CFG dump ๐๏ธ-fsel-sched-pipelining-verboseโ selective pipelining verbose ๐ฃ๏ธ-fstatsโ stats ๐-fstack-usageโ stack usage ๐-ftime-reportโ time report โฑ๏ธ-ftime-report-detailsโ time report details โฑ๏ธโจ-fvar-tracking-assignments-toggleโ toggle variable tracking assignments ๐-gtoggleโ toggle debug info ๐-print-file-name=libraryโ print the path oflibrary๐จ๏ธ-print-libgcc-file-nameโ print the libgcc file name ๐จ๏ธ-print-multi-directoryโ print the multilib directory ๐จ๏ธ-print-multi-libโ print multilib info ๐จ๏ธ-print-multi-os-directoryโ print the multilib OS directory ๐จ๏ธ-print-prog-name=programโ print the path ofprogram๐จ๏ธ-print-search-dirsโ print search directories ๐จ๏ธ-Qโ print what's happening as it happens ๐ฃ๏ธ-print-sysrootโ print the sysroot ๐จ๏ธ-print-sysroot-headers-suffixโ print the sysroot headers suffix ๐จ๏ธ-save-tempsโ save temp files ๐พ-save-temps=cwdโ save temp files in the current directory ๐พ๐-save-temps=objโ save temp files in the object directory ๐พ๐ฆ-time[=file]โ time it โฑ๏ธ
โจ Machine-Dependent Options โจ
the hardware-specific section, where each chip gets its own main character moment ๐๐
AArch64 Options
-mabi=nameโ ABI name ๐งพ-mbig-endianโ big-endian ๐งฑ-mlittle-endianโ little-endian ๐งฑ-mgeneral-regs-onlyโ general registers only ๐ฏ-mcmodel=tinyโ tiny code model ๐-mcmodel=smallโ small code model ๐ญ-mcmodel=largeโ large code model ๐-mstrict-alignโ strict alignment ๐-mno-strict-alignโ no strict alignment ๐-momit-leaf-frame-pointerโ omit leaf frame pointer ๐ซฅ-mtls-dialect=descโ TLS dialect, descriptor style ๐งต-mtls-dialect=traditionalโ TLS dialect, traditional style ๐งต๐ผ-mtls-size=sizeโ TLS size ๐-mfix-cortex-a53-835769โ fix Cortex-A53 erratum 835769 ๐ฉน-mfix-cortex-a53-843419โ fix Cortex-A53 erratum 843419 ๐ฉน-mlow-precision-recip-sqrtโ low-precision reciprocal square root ๐งฎ-mlow-precision-sqrtโ low-precision square root ๐งฎ-mlow-precision-divโ low-precision division ๐งฎ-mpc-relative-literal-loadsโ PC-relative literal loads ๐-msign-return-address=scopeโ sign return address, pick a scope โ๏ธ-mbranch-protection=none|standard|pac-ret[+leaf +b-key]|btiโ branch protection, pick one ๐ก๏ธ-mharden-sls=optsโ harden SLS with these options ๐ก๏ธ-march=nameโ architecture name ๐๏ธ-mcpu=nameโ CPU name ๐ง-mtune=nameโ tune forname๐๏ธ-moverride=stringโ overridestring๐ง-mverbose-cost-dumpโ verbose cost dump ๐ฃ๏ธ-mstack-protector-guard=guardโ stack protector guard ๐ก๏ธ-mstack-protector-guard-reg=sysregโ stack protector guard register ๐ก๏ธ๐-mstack-protector-guard-offset=offsetโ stack protector guard offset ๐ก๏ธ๐-mtrack-speculationโ track speculation ๐ฎ-moutline-atomicsโ outline atomics โ๏ธ
Okay bestie, this is the target-specific lineup ๐ฆ every machine gets its own squad of flags, and this part is just the names, no descriptions yet ๐
๐ฆ Adapteva Epiphany Options ๐ฆ
-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 ๐ธ
-march=gpu-mtune=gpu-mstack-size=bytes
๐ง ARC Options ๐ง
-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-compactmlra-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 ๐
-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-munaligned-access-mneon-for-64bits-mslow-flash-data-masm-syntax-unified-mrestrict-it-mverbose-cost-dump-mpure-code-mcmse-mfix-cmse-cve-2021-35465-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-metrax4-metrax100-mpdebug-mcc-init-mno-side-effects-mstack-align-mdata-align-mconst-align-m32-bit-m16-bit-m8-bit-mno-prologue-epilogue-melf-maout-sim-sim2-mmul-bug-workaround-mno-mul-bug-workaround
๐ 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 ๐
-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
๐ FR30 Options ๐
-msmall-model-mno-lsim
๐ธ FT32 Options ๐ธ
-msim-mlra-mnodiv-mft32b-mcompress-mnopm
๐ FRV Options ๐
-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 ๐
-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 ๐ธ
-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 ๐ซถ
-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 ๐
-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
okay so MIPS has SO many flags ๐ bestie, this is a whole vibe. here's the full list, no cuts ๐
-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 -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
the MMIX crew is smaller but still iconic ๐
-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
tiny but mighty โจ
-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
๐ 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
no separate list here, bestie. the PowerPC flags live under the RS/6000 and PowerPC Options section, so see RS/6000 and PowerPC Options ๐
๐ฆ PRU Options
-mmcu=mcu -minrt -mno-relax -mloop -mabi=variant
๐ธ RISC-V Options
-mbranch-cost=N-instruction -mplt -mno-plt
-mabi=ABI-string -mfdiv -mno-fdiv -mdiv -mno-div -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 LONG, like full main character marathon ๐ญ every single flag is here:
-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
-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
-Qy -Qn -YP,paths -Ym,dir
๐ TILE-Gx Options
-mcpu=CPU -m32 -m64 -mbig-endian -mlittle-endian
-mcmodel=code-model
๐ธ TILEPro Options
-mcpu=cpu -m32
โจ V850 Options โจ
okay bestie, the V850 crew has its own little flag squad ๐ฆ here's every single one, copied exactly:
-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 ๐ธ
the VAX ones are small but mighty ๐
-mg -mgnu -munix
๐ง Visium Options ๐ง
Visium has a whole set of its own, no cap ๐ฅ
-mdebug -msim -mfpu -mno-fpu -mhard-float
-msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
๐ VMS Options ๐
for VMS, these are the ones you want ๐
-mvms-return-codes -mdebug-main=prefix -mmalloc64
-mpointer-size=size
๐ฆ VxWorks Options ๐ฆ
VxWorks is giving main character energy ๐
-mrtp -non-static -Bstatic -Bdynamic -Xbind-lazy
-Xbind-now
๐ x86 Options ๐
okay this is the big one, the x86 list is literally massive ๐ญ it covers tuning, architecture, floating point, SSE and AVX families, calling conventions, and so much more. bestie, grab a snack ๐
-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 -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 -mcldemote -mms-bitfields
-mno-align-stringops -minline-all-stringops
-minline-stringops-dynamically -mstringop-strategy=alg -mkl
-mwidekl -mmemcpy-strategy=strategy -mmemset-strategy=strategy
-mpush-args -maccumulate-outgoing-args -m128bit-long-double
-m96bit-long-double -mlong-double-64 -mlong-double-80
-mlong-double-128 -mregparm=num -msseregparm -mveclibabi=type
-mvect8-ret-in-mem -mpc32 -mpc64 -mpc80 -mdaz-ftz -mstackrealign
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs
-mcmodel=code-model -mabi=name -maddress-mode=mode -m32 -m64
-mx32 -m16 -miamcu -mlarge-data-threshold=num -msse2avx -mfentry
-mrecord-mcount -mnop-mcount -m8bit-idiv -minstrument-return=type
-mfentry-name=name -mfentry-section=name
-mavx256-split-unaligned-load -mavx256-split-unaligned-store
-malign-data=type -mstack-protector-guard=guard
-mstack-protector-guard-reg=reg
-mstack-protector-guard-offset=offset
-mstack-protector-guard-symbol=symbol -mgeneral-regs-only
-mcall-ms2sysv-xlogues -mindirect-branch=choice
-mfunction-return=choice -mindirect-branch-register
-mharden-sls=choice -mindirect-branch-cs-prefix -mneeded
๐ x86 Windows Options ๐
Windows x86 gets its own squad too ๐ชโจ
-mconsole -mcygwin -mno-cygwin -mdll
-mnop-fun-dllimport -mthread -municode -mwin32 -mwindows
-fno-set-stack-executable
๐ Xstormy16 Options ๐
only one flag for this one, but it's a serious one ๐ซถ
-msim
๐ Xtensa Options ๐
Xtensa has a whole cute collection of its own ๐ธ
-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 ๐ง
no flags of its own here, bestie. the zSeries stuff lives over at See S/390 and zSeries Options ๐
โจ Options Controlling the Kind of Output โจ
okay so compilation can have up to four stages: preprocessing, compilation proper, assembly, and linking, and they always happen in that order ๐ฅ GCC can preprocess and compile several files into several assembler input files, or into one assembler input file. then each assembler input file makes an object file, and linking smooshes all the object files together (the newly compiled ones and the ones you gave it as input) into an executable file ๐
for any given input file, the file name suffix decides what kind of compilation happens. iykyk ๐ซถ
file.cโ C source that still needs to go through the preprocessor first ๐งfile.iโ C source that should not be preprocessed.file.iiโ C++ source 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 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. Also,.Mrefers to a literal capital M.file.miiโ Objective-C++ source that should not be preprocessed.file.hโ a C, C++, Objective-C, or Objective-C++ header that gets turned into a precompiled header (this is the default), or a C or C++ header that gets 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 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 that must be preprocessed.file.miiโ Objective-C++ source that should not be preprocessed.file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ headers that get turned into a precompiled header or an Ada spec.file.f,file.for,file.ftnโ fixed form Fortran source that should not be preprocessed.file.F,file.FOR,file.fpp,file.FPP,file.FTNโ fixed form Fortran source that must be preprocessed (with the traditional preprocessor).file.f90,file.f95,file.f03,file.f08โ free form Fortran source that should not be preprocessed.file.F90,file.F95,file.F03,file.F08โ free form Fortran source that must be preprocessed (with the traditional preprocessor).file.goโ Go source code.file.brigโ BRIG files (binary representation of HSAIL).file.dโ D source code.file.diโ D interface file.file.ddโ D documentation code (Ddoc).file.adsโ Ada source that holds a library unit declaration (a declaration of a package, subprogram, or generic, or a generic instantiation), or a library unit renaming declaration (a package, generic, or subprogram renaming declaration). These are also called specs.file.adbโ Ada source that holds a library unit body (a subprogram or package body). These are also called bodies.file.sโ Assembler code.file.S,file.sxโ Assembler code that must be preprocessed.otherโ an object file that gets fed straight into linking. Any file name with no recognized suffix is treated this way.
you can also tell GCC the input language yourself with the -x option ๐
โจ -x language โจ
this lets you pick the language for the input files that follow, instead of letting the compiler guess from the file name suffix ๐
it applies to all following input files until the next -x option. the 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
brig
๐ฆ -x none
this turns off any language specification, so the files after it are handled by their file name suffixes, just like they would be if -x had never been used at all ๐ธ
if you only want some stages of compilation, you can use -x (or filename suffixes) to tell gcc where to start, and one of the options -c, -S, or -E to say where gcc should stop. heads up, some combos (for example, -x cpp-output -E) make gcc do absolutely nothing at all ๐
๐ซถ -c
compile or assemble the source files, but do not link ๐ the linking stage just doesn't happen. the final output is an object file for each source file.
by default, the object file name for a source file is made by swapping the suffix .c, .i, .s, etc. for .o.
unrecognized input files that don't need compiling or assembling are ignored.
๐ธ -S
stop after the compilation proper stage and skip assembling ๐ง the output is an assembler code file for each non-assembler input file you gave it.
by default, the assembler file name for a source file is made by swapping the suffix .c, .i, etc. for .s.
input files that don't need compiling are ignored.
๐ -E
stop after the preprocessing stage and don't run the compiler proper ๐ the output is preprocessed source code, sent to standard output.
input files that don't need preprocessing are ignored.
๐ -o file
place the primary output in file ๐ this applies to whatever kind of output you're making, whether that's an executable, an object file, an assembler file, or preprocessed C code.
if -o isn't specified, the defaults are: an executable goes in a.out, the object file for source.suffix goes in source.o, its assembler file goes in source.s, a precompiled header file goes in source.suffix.gch, and all preprocessed C source goes to standard output ๐
Okay so, this next bit is all about how -o quietly decides what your aux and dump files get named, and bestie, it's giving main character energy ๐
โจ
The primary output is just the one file -o names, but it also controls the naming of your auxiliary and dump outputs ๐ฆ Check the examples below, they're lowkey the best part. Unless you override it, aux and dump outputs land in the same directory as the primary output ๐ธ For auxiliary outputs, the input file's suffix gets swapped for the aux file type's suffix. For dump outputs, the dump file's suffix gets tacked onto the input file's suffix. In compilation commands, both aux and dump outputs use the primary output's base name. In compile and link commands, the primary output name (minus the executable suffix) gets mixed with the input file name. If both end up with the same base name once you ignore the suffix, the result is just that base name. If they don't match, they get smooshed together with a dash between them ๐
gcc -c foo.c ...
This will use foo.o as the primary output and drop aux outputs and dumps right next to it. For example, you get the aux file foo.dwo for -gsplit-dwarf, and the dump file foo.c.???r.final for -fdump-rtl-final ๐ง
If you explicitly give a non-linker output file, aux and dump files default to the same base name, and that's so clean ๐ซถ
gcc -c foo.c -o dir/foobar.o ...
This will name the aux outputs dir/foobar.* and the dump outputs dir/foobar.c.* ๐
A linker output works differently and prefixes the aux and dump outputs instead ๐
gcc foo.c bar.c -o dir/foobar ...
This will generally name the aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and the dump outputs dir/foobar-foo.c.* and dir/foobar-bar.c.* ๐
The one exception is when the executable shares its base name with the single input ๐
gcc foo.c -o dir/foo ...
In that case the aux outputs are dir/foo.* and the dump outputs are dir/foo.c.* โจ
You can tweak the location and names of aux and dump outputs with -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 touch the name of the primary output file ๐ Intermediate outputs, when you keep them, 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 as foo.i, then compiles to the (implied) output file foo.s. Iconic ๐ธ
gcc -save-temps -dumpbase save-foo -c foo.c
This one 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 get their names from the input file, or from the (non-linker) output file if you explicitly named one. Dump output files (like the ones from -fdump-* options) keep the input name suffix. Aux output files (the ones from 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 with an explicit -dumpbase basename.suf by also passing -dumpbase-ext .suf ๐ซถ
If you give dumpbase an explicit directory component, any dumppfx specification (like -dumpdir or -save-temps=*) gets ignored. Instead of appending to it, dumpbase fully overrides it ๐
gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
-dumpdir pfx- -save-temps=cwd ...
This creates aux and dump outputs named alt/foo.*. It totally ignores dir/ in -o, the ./ prefix implied by -save-temps=cwd, and pfx- in -dumpdir ๐
When you pass -dumpbase in a command that compiles multiple inputs, or compiles and then links, it can be combined with dumppfx, same as under -dumpdir. Each input file then gets compiled with the combined dumppfx, and its own default values for dumpbase and auxdropsuf ๐
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs. It also stops the aux and dump outputs from overwriting each other by using the dumpbase as a prefix, so you get main-foo.* and main-bar.* ๐ฆ
An empty string as dumpbase stops the output basename from influencing aux and dump names during compilation. The defaults get computed instead ๐
gcc -c foo.c -o dir/foobar.o -dumpbase " ...
This names the aux outputs dir/foo.* and the dump outputs dir/foo.c.*. Notice how the basenames come from the input name, but the directory still defaults to the output's directory ๐ง
The empty-string dumpbase doesn't stop the output basename from being used during linking, though ๐
gcc foo.c bar.c -o dir/foobar -dumpbase " -flto ...
The source file compilation names the aux outputs dir/foo.* and dir/bar.*, and the dump outputs dir/foo.c.* and dir/bar.c.*. LTO recompilation during linking uses dir/foobar. as the prefix for dumps and aux files ๐ฅ
๐ฆ -dumpbase-ext auxdropsuf
When you form the name of an auxiliary output file (but not a dump one), 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 input file's suffix 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.*. They sit where the primary output is, and the .c suffix gets dropped from the dumpbase. Dump outputs keep the suffix, so they're dir/x-foo.c.* ๐
This option gets ignored if it doesn't match the suffix of a specified dumpbase. The one exception is as an alternative to the executable suffix when 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. It stops the aux and dump outputs from overwriting each other by using the executable name minus auxdropsuf as a prefix. So you get aux outputs main-foo.* and main-bar.*, and dump outputs main-foo.c.* and main-bar.c.* ๐
๐ง -dumpdir dumppfx
When you form 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, which in turn comes from the input name. Dump outputs also take the input name suffix, so they're 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 take the input name suffix too, so they're dir/bar.c.* ๐ฆ
By default it's 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 option does. If you pass 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. 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, dumpbase (minus an auxdropsuf suffix) plus a dash gets appended to an explicit or defaulted dumppfx. If dumpbase has any directory components, it overrides dumppfx instead. This way each compilation gets its own 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, so they're dir/pfx-main-foo.c.* and dir/pfx-main-bar.c.*, respectively ๐ง
Compare that with single-input compilation:
gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
Applying -dumpbase to a single source doesn't compute and append a separate dumpbase per input file. Its aux and dump outputs go in dir/pfx-main.* ๐
When you compile and then link from multiple input files, a defaulted or explicitly specified dumppfx also goes through the dumpbase- transformation above. Think the compilation of foo.c and bar.c above, just without -c. If you specify neither -dumpdir nor -dumpbase, the linker output base name gets appended to the default dumppfx instead. That's the base name minus auxdropsuf if you gave one, or minus the executable suffix otherwise, plus a dash ๐
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
Heads up, though: unlike the earlier linking cases, this does not append the output name main to dumppfx, because -dumpdir is explicitly specified. The idea is that your explicit dumppfx can include the output name as part of the prefix if you want it to. Only an explicitly specified -dumpbase gets combined with it, so a meaningful option doesn't get quietly thrown away ๐ฅ
When you compile and 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 for an explicit -dumpdir that stops the combination, even when -save-temps=* overrides it:
gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
Aux outputs are named foo.*, and dump outputs foo.c.*, in the current working directory, as finally requested by -save-temps=cwd ๐
The dump-name stuff is kinda the boss level of this whole page, so here's the vibe ๐
: the main output name gets split into a directory part and a basename part. dumppfx takes the directory part, unless you override it with -dumpdir or -save-temps=*. dumpbase takes the basename, unless you override it with -dumpbase. If there are multiple inputs or you're linking, dumpbase can get combined with dumppfx and pulled from each input file ๐ง. Auxiliary output names for each input are made by mashing together dumppfx, dumpbase minus its suffix, and the auxiliary output suffix. Dump output names are basically the same, except they keep the suffix from dumpbase ๐ฆ
Okay, now the LTO recompilation bit ๐ฅ. Auxiliary and dump outputs made during LTO recompilation get a combo of dumppfx and dumpbase passed down to lto-wrapper as a -dumpdir option. That combo can come from what you gave it or from the linker output name (but not from the inputs), and it's sent this way even when it wouldn't normally be used like that. 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 it runs sub-compilers, lto-wrapper 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โ Print (on standard error output) the commands executed to run the stages of compilation. It also prints the version number of the compiler driver program and of the preprocessor and the compiler proper ๐ฃ-###โ Basically-v, but the commands don't actually run, and arguments get quoted unless they only contain alphanumeric characters or"./-_". This is perfect for shell scripts that want to capture the driver-generated command lines ๐ค--helpโ Print (on the standard output) a description of the command-line optionsgccunderstands. If-vis also specified,--helpgets passed on to the various processesgccinvokes, so they can show the command-line options they accept. If-Wextrawas also specified (before the--helpoption), command-line options with no documentation attached get displayed too ๐--target-helpโ Prints (on the standard output) a description of the target-specific command-line options for each tool. For some targets, extra target-specific information might get printed too ๐ธ--help={class|[^]qualifier}[,...]โ Print (on the standard output) a description of the command-line options the compiler understands that fit into all the specified classes and qualifiers. Here are the supported classes ๐optimizersโ Shows all the optimization options the compiler supports.warningsโ Shows all the options that control the warning messages the compiler produces.targetโ Shows target-specific options. Unlike--target-help, target-specific options of the linker and assembler aren't shown, because those tools don't currently support the extended--help=syntax.paramsโ Shows the values recognized by the--paramoption.languageโ Shows the options supported for language, where language is the name of one of the languages supported in this version of GCC. If an option is supported by all languages, you need to pick thecommonclass.commonโ Shows the options that are common to all languages.
Here are the supported 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 after the original option, like-o output-file.
Want all the undocumented target-specific switches the compiler supports? Use this ๐
--help=target,undocumented
The sense of a qualifier can be flipped by prefixing it with the ^ character. So if you want all the binary warning options (the ones that are either on or off and don't take an argument) that have a description, use this ๐
--help=warnings,^joined,^undocumented
The argument to --help= shouldn't consist solely of inverted qualifiers.
You can combine several classes, but that usually restricts the output so much there's nothing to display. One case where it does work is when one of the classes is target. For example, to display all the target-specific optimization options, use this ๐
--help=target,optimizers
The --help= option can be repeated on the command line. Each successive use displays its requested class of options, skipping any that have already been displayed. If --help is also specified anywhere on the command line, it takes precedence over any --help= option ๐
If the -Q option appears on the command line before the --help= option, the descriptive text shown by --help= changes. Instead of describing the displayed options, it gives an indication of whether each option is enabled, disabled, or set to a specific value (assuming the compiler knows this at the point where --help= is used) ๐ซถ
Here's a truncated example from the ARM port of gcc ๐ง
% gcc -Q -mabi=2 --help=target -c
The following options are target specific:
-mabi= 2
-mabort-on-noreturn [disabled]
-mapcs [disabled]
The output is sensitive to the effects of previous command-line options, so you can find out which optimizations are enabled at -O2 by using this ๐ฆ
-Q -O2 --help=optimizers
Or, if you want to discover which binary optimizations are enabled by -O3, do this ๐ฅ
gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
diff /tmp/O2-opts /tmp/O3-opts | grep enabled
--versionโ Displays the version number and copyrights of the GCC you invoked ๐-pass-exit-codesโ Normally, thegccprogram exits with the code of 1 if any phase of the compiler returns a non-success return code. If you specify-pass-exit-codes, thegccprogram instead returns the numerically highest error produced by any phase that returned an error indication. The C, C++, and Fortran front ends return 4 if they hit an internal compiler error ๐จ-pipeโ Uses pipes rather than temporary files for communication between the various stages of compilation. This fails on some systems where the assembler can't read from a pipe, but the GNU assembler has no trouble ๐-specs=fileโ Processes file after the compiler reads in the standard specs file, to override 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're processed in order, from left to right ๐-wrapperโ Invokes all subcommands under a wrapper program. The name of the wrapper program and its parameters are passed as a comma separated list ๐
gcc -c t.c -wrapper gdb,--args
This invokes all subprograms of gcc under gdb --args, so the invocation of cc1 becomes gdb --args cc1 ... ๐
-ffile-prefix-map=old=newโ When 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 option is equivalent to specifying all the individual-f*-prefix-mapoptions. It's a great way to make reproducible, location-independent builds ๐ธ See also-fmacro-prefix-mapand-fdebug-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 identifies 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 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 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 get inserted in place of the original@fileoption. If file doesn't exist or can't be read, the option gets treated literally and isn't removed ๐
Options in file are separated by whitespace. You can include a whitespace character 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 may 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, and preprocessed C++ files use the suffix .ii ๐ซถ. GCC recognizes files with these names and compiles them as C++ programs, even if you call the compiler the same way you would for C programs (usually with the name gcc) โจ
However, the use of gcc does not add the C++ library, bestie ๐. That's where g++ slides in โจ. g++ is a program that calls GCC and automatically specifies linking against the C++ library, so you don't have to remember it ๐
. It treats .c, .h and .i files as C++ source files instead of C source files unless -x is used. It's also handy for precompiling a C header file with a .h extension for use in C++ compilations ๐ง. On many systems, g++ is also installed with the name c++ ๐ธ.
When you compile C++ programs, you can use lots of the same command-line options you'd use for any language, or options meant for C and related languages, or options that only matter for C++ ๐ฆ.
โจ Options Controlling C Dialect โจ
These options control the dialect of C (or languages derived from C, like C++, Objective-C and Objective-C++) that the compiler accepts ๐:
-ansiโ In C mode this is the same as-std=c90, and in C++ mode it's the same as-std=c++98๐. It turns off GCC features that clash with ISO C90 (when compiling C) or standard C++ (when compiling C++), like theasmandtypeofkeywords, plus predefined macros likeunixandvaxthat tell you what system you're on ๐. It also switches on the undesirable and rarely used ISO trigraph feature ๐. For the C compiler, it also turns off recognition of C++ style//comments as well as theinlinekeyword. The alternate keywords__asm__,__extension__,__inline__and__typeof__still work even with-ansi. You wouldn't want them in an ISO C program, of course, but they're super useful in header files that might get included in compilations done with-ansi๐ง. Alternate predefined macros like__unix__and__vax__are available with or without-ansi๐.-ansidoesn't reject non-ISO programs gratuitously. For that, you need-Wpedanticon top of-ansi. The macro__STRICT_ANSI__is predefined when-ansiis used, and some header files notice it and skip declaring certain functions or defining certain macros that the ISO standard doesn't call for, so they don't interfere with programs using those names for other things ๐. Functions that are normally built in but don't have semantics defined by ISO C (likeallocaandffs) are not built-in functions when-ansiis used.-std=โ Determines the language standard ๐. This option is currently only supported when compiling C or C++. The compiler can accept several base standards, likec90orc++98, and GNU dialects of those, likegnu90orgnu++98. With a base standard, the compiler accepts all programs following that standard plus GNU extensions that don't contradict it. For example,-std=c90turns off GCC features that are incompatible with ISO C90, like theasmandtypeofkeywords, but not other GNU extensions that have no meaning in ISO C90, like omitting the middle term of a?:expression. With a GNU dialect, though, every feature the compiler supports is enabled, even when those features change the meaning of the base standard. So some strictly conforming programs may get rejected ๐ญ.-Wpedanticuses the particular standard to figure out which features are GNU extensions for that version. For example,-std=gnu90 -Wpedanticwarns about C++ style//comments, while-std=gnu99 -Wpedanticdoes not. A value for this option must be provided. Possible values are:c90,c89,iso9899:1990โ Supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code.iso9899:199409โ ISO C90 as modified in amendment 1.c99,c9x,iso9899:1999,iso9899:199xโ ISO C99. It's substantially completely supported, modulo bugs and floating-point issues (mainly but not entirely related to optional C99 features from Annexes F and G). Seehttp://gcc.gnu.org/c99status.htmlfor more info. The namesc9xandiso9899:199xare deprecated ๐ฅ.c11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard. It's substantially completely supported, modulo bugs, floating-point issues (mainly but not entirely related to optional C11 features from Annexes F and G), and the optional Annexes K (Bounds-checking interfaces) and L (Analyzability). The namec1xis deprecated.c17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision of the ISO C standard (published in 2018). 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 for this version is experimental and incomplete ๐งช.gnu90,gnu89โ GNU dialect of ISO C90 (including some C99 features).gnu99,gnu9xโ GNU dialect of ISO C99. The namegnu9xis deprecated.gnu11,gnu1xโ GNU dialect of ISO C11. The namegnu1xis deprecated.gnu17,gnu18โ GNU dialect of ISO C17. This is the default for C code ๐.gnu2xโ The next version of the ISO C standard, still under development, plus GNU extensions. Support for this version is experimental and incomplete.c++98,c++03โ The 1998 ISO C++ standard plus the 2003 technical corrigendum and some additional defect reports. Same as-ansifor C++ code.gnu++98,gnu++03โ GNU dialect of-std=c++98.c++11,c++0xโ The 2011 ISO C++ standard plus amendments. The namec++0xis deprecated.gnu++11,gnu++0xโ GNU dialect of-std=c++11. The namegnu++0xis deprecated.c++14,c++1yโ The 2014 ISO C++ standard plus amendments. The namec++1yis deprecated.gnu++14,gnu++1yโ GNU dialect of-std=c++14. The namegnu++1yis deprecated.c++17,c++1zโ The 2017 ISO C++ standard plus amendments. The namec++1zis deprecated.gnu++17,gnu++1zโ GNU dialect of-std=c++17. This is the default for C++ code ๐. The namegnu++1zis deprecated.c++20,c++2aโ The 2020 ISO C++ standard plus amendments. Support is experimental and could change in incompatible ways in future releases. The namec++2ais deprecated ๐งช.gnu++20,gnu++2aโ GNU dialect of-std=c++20. Support is experimental and could change in incompatible ways in future releases. The namegnu++2ais deprecated.c++2b,c++23โ 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.
-fgnu89-inlineโ Tells GCC to use the traditional GNU semantics forinlinefunctions when in C99 mode ๐ฆ. Using this option is roughly equivalent to adding thegnu_inlinefunction attribute to all inline functions. The option-fno-gnu89-inlineexplicitly tells GCC to use the C99 semantics forinlinewhen in C99 orgnu99mode (i.e., it specifies the default behavior). This option is not supported in-std=c90or-std=gnu90mode. The preprocessor macros__GNUC_GNU_INLINE__and__GNUC_STDC_INLINE__can be used to check which semantics are in effect forinlinefunctions.-fpermitted-flt-eval-methods=styleโ ISO/IEC TS 18661-3 defines new permissible values forFLT_EVAL_METHODthat indicate operations and constants with a semantic type that is an interchange or extended format should be evaluated to the precision and range of that type ๐ฅ. These new values are a superset of those permitted under C99/C11, which doesn't specify the meaning of other positive values ofFLT_EVAL_METHOD. So code conforming to C11 may not have been written expecting the new values ๐.-fpermitted-flt-eval-methodsspecifies whether the compiler should allow only the values ofFLT_EVAL_METHODspecified in C99/C11, or the extended set of values specified in ISO/IEC TS 18661-3.styleis eitherc11orts-18661-3, as appropriate. The default when in a standards-compliant mode (-std=c11or similar) is-fpermitted-flt-eval-methods=c11. The default when in a GNU dialect (-std=gnu11or similar) is-fpermitted-flt-eval-methods=ts-18661-3.-aux-info filenameโ Outputs to the given filename prototyped declarations for all functions declared and/or defined in a translation unit, including those in header files ๐. This option is silently ignored in any language other than C. Besides declarations, the file indicates, in comments, the origin of each declaration (source file and line), whether the declaration was implicit, prototyped or unprototyped (I,Nfor new orOfor old, respectively, in the first character after the line number and the colon), and whether it came from a declaration or a definition (CorF, respectively, in the following character). For function definitions, a K&R-style list of arguments followed by their declarations is also provided, inside comments, after the declaration.-fallow-parameterless-variadic-functionsโ Accepts variadic functions without named parameters ๐. Although it's possible to define such a function, it's not very useful, because it's not possible to read the arguments. This is only supported for C, as this construct is allowed by C++.-fno-asmโ okay so this one stops GCC from treatingasm,inlineortypeofas keywords ๐ That way your code can use those words as regular identifiers. You can use__asm__,__inline__and__typeof__instead.-ansiimplies-fno-asm.- In C++, this only affects the
typeofkeyword, sinceasmandinlineare standard keywords there. Bestie tip from the manual: you may want-fno-gnu-keywordsinstead, which does the same thing. - In C99 mode (
-std=c99or-std=gnu99), this only affectsasmandtypeof, sinceinlineis a standard keyword in ISO C99 ๐
- In C++, this only affects the
-fno-builtin,-fno-builtin-functionโ Stop recognizing built-in functions whose names don't start with the__builtin_prefix ๐ฆ- GCC normally makes special code for certain built-ins so they run more efficiently. For example,
allocacalls can turn into single instructions that adjust the stack directly, andmemcpycalls can become inline copy loops โจ - The result is often smaller and faster, but since those calls don't show up as calls anymore, you can't set a breakpoint on them. You also can't change what they do by linking with a different library ๐ญ
- Even when the code still contains calls, GCC may use what it knows about a built-in to warn you about problems or to generate better code. Like, warnings are given with
-Wformatfor bad calls toprintfwhenprintfis built in, and whenstrlenis known not to modify global memory ๐ฅ - With
-fno-builtin-function, only that one built-in gets switched off.functionmust not begin with__builtin_. If the function you name isn't a built-in in this version of GCC, the option just gets ignored ๐ธ - There's no
-fbuiltin-functioncounterpart. If you want to turn built-ins back on selectively while using-fno-builtinor-ffreestanding, you can define macros like these:
- GCC normally makes special code for certain built-ins so they run more efficiently. For example,
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fgimpleโ Turns on parsing of function definitions marked with__GIMPLE. It's an experimental feature that lets you unit test GIMPLE passes ๐งช-fhostedโ Asserts that compilation targets a hosted environment, which implies-fbuiltin. A hosted environment is one where the entire standard library is available andmainhas a return type ofint. Basically everything except a kernel is hosted ๐- This is equivalent to
-fno-freestanding.
- This is equivalent to
-ffreestandingโ Asserts that compilation targets a freestanding environment, which implies-fno-builtin. In a freestanding environment the standard library may not exist, and startup might not necessarily be atmain. The most obvious example is an OS kernel ๐- This is equivalent to
-fno-hosted.
- This is equivalent to
-fopenaccโ Turns on handling of OpenACC directives,#pragma accin C/C++ and!$accin Fortran ๐ With it, the compiler generates accelerated code following 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๐ซถ
- This option implies
-fopenacc-dim=geomโ Sets the default compute dimensions for parallel offload regions that don't explicitly specify their own โจ Thegeomvalue is a triple of':'-separated sizes, in the ordergang,workerandvector. A size can be left out to use a target-specific default value ๐ง-fopenmpโ Turns on handling of OpenMP directives,#pragma ompin C/C++ and!$ompin Fortran ๐ With it on, the compiler generates parallel code following the OpenMP Application Program Interface v4.5,https://www.openmp.org.- This option implies
-pthread, so it's only supported on targets that have support for-pthread. -fopenmpimplies-fopenmp-simd.
- This option implies
-fopenmp-simdโ Turns on handling of OpenMP's SIMD directives written as#pragma ompin C/C++ and!$ompin Fortran. Other OpenMP directives get ignored ๐-fgnu-tmโ When you specify-fgnu-tm, the compiler generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009) ๐ This is an experimental feature whose interface may change in future GCC versions as the official spec changes.- Not all architectures are supported for this feature, so check before you get too attached ๐
- For more information on GCC's support for transactional memory,
- > Heads up: the transactional memory feature is not supported with non-call exceptions (
-fnon-call-exceptions).
-fms-extensionsโ Accepts some non-standard constructs used in Microsoft header files ๐- In C++ code, this lets member names in structures be similar to previous type declarations. Iconic behavior, honestly:
typedef int UOW;
struct ABC {
UOW UOW;
};
- Some cases of unnamed fields in structures and unions are only accepted with this option.
- This option is off for all targets except x86 targets using
ms-abi.
-fplan9-extensionsโ Accepts some non-standard constructs used in Plan 9 code ๐ฆ- This enables
-fms-extensions. - It permits passing pointers to structures with anonymous fields to functions that expect pointers to elements of the type of the field.
- It also permits referring to anonymous fields declared using a
typedef. - This is only supported for C, not C++ ๐
- This enables
-fcond-mismatchโ Allows conditional expressions with mismatched types in the second and third arguments. The value of such an expression isvoid. This option is not supported for C++ ๐-flax-vector-conversionsโ Allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types. Don't use this for new code, bestie ๐ญ-funsigned-charโ Lets the typecharbe unsigned, likeunsigned char๐ธ- Every kind of machine has a default for what
charshould be. It's either likeunsigned charby default or likesigned charby default. - Ideally, a portable program should always use
signed charorunsigned charwhenever it depends on the signedness of an object. But loads of programs were written to use plaincharand expect it to be signed, or expect it to be unsigned, depending on the machines they were written for. This option, and its inverse, let you make such a program work with the opposite default. - The type
charis always a distinct type from each ofsigned charorunsigned char, even though its behavior is always just like one of those two.
- Every kind of machine has a default for what
-fsigned-charโ Lets the typecharbe signed, likesigned char๐- This is equivalent to
-fno-unsigned-char, which is the negative form of-funsigned-char. - Likewise, the option
-fno-signed-charis equivalent to-funsigned-char.
- This is equivalent to
-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: the basic integer types likeintare signed types.-fsso-struct=endiannessโ Sets the default scalar storage order of structures and unions to the specified endianness ๐ง The accepted values arebig-endian,little-endianandnativefor the native endianness of the target (the default). This option is not supported for C++.- > Warning: the
-fsso-structswitch 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. Don't say I didn't warn you ๐ญ
- > Warning: the
โจ Options Controlling C++ Dialect ๐
This section covers the command-line options that are only meaningful for C++ programs ๐ You can also 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 version 0 ๐ฆ- Version 0 refers to the version conforming most closely to the C++ ABI specification. That means the ABI you get with version 0 will change across different versions of G++ as ABI bugs get fixed ๐
- Version 1 is the version of the C++ ABI that first appeared in G++ 3.2.
- Version 2 is the version that first appeared in G++ 3.4, and it was the default through G++ 4.9 ๐
- Version 3 corrects an error in mangling a constant address as a template argument.
- Version 4, which first appeared in G++ 4.5, implements a standard mangling for vector types.
- Version 5, which first appeared in G++ 4.6, corrects the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and use of a function parameter in the declaration of another parameter.
- Version 6, which first appeared in G++ 4.7, corrects the promotion behavior of C++11 scoped enums and the mangling of template argument packs, const/static_cast, prefix ++ and --, and a class scope function used as a template argument.
- Version 7, which first appeared in G++ 4.8, treats
nullptr_tas a builtin type and corrects the mangling of lambdas in default argument scope. - Version 8, which first appeared in G++ 4.9, corrects the substitution behavior of function types with function-cv-qualifiers.
- Version 9, which first appeared in G++ 5.2, corrects the alignment of
nullptr_t. - Version 10, which first appeared in G++ 6.1, adds mangling of attributes that affect type identity, such as ia32 calling convention attributes (e.g.
stdcall) ๐
Version 11 first showed up in G++ 7 and fixed the mangling of sizeof... expressions and operator names ๐
. For multiple entities with the same name inside a function that are declared in different scopes, the mangling now changes starting with the twelfth occurrence. It also implies -fnew-inheriting-ctors ๐ธ.
Version 12 first appeared in G++ 8 and corrected the calling conventions for empty classes on the x86_64 target, plus classes with only deleted copy/move constructors ๐ฆ. It accidentally changes the calling convention for classes with a deleted copy constructor and a trivial move constructor, so ngl, that's a little oops ๐.
Version 13 first appeared in G++ 8.2 and fixes that accidental change from version 12 ๐ซถ.
Version 14 first appeared in G++ 10 and corrects the mangling of the nullptr expression โจ.
Version 15 first appeared in G++ 11 and changes the mangling of "__alignof__" so it's distinct from "alignof", plus dependent operator names ๐.
See also -Wabi ๐.
-fabi-compat-version=nโ okay so, 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 gets used for that alias. With-fabi-version=0(the default), it defaults to11(GCC 7 compatibility). If you explicitly select another ABI version, it defaults to0. For compatibility with GCC versions 3.2 through 4.9, use-fabi-compat-version=2๐. If you don't provide this option but do provide-Wabi=n, that version is used for the compatibility aliases. If you provide this option along with-Wabi(without a 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, so it's a bit of a last-resort vibe ๐.-faligned-newโ enables support for C++17"new"of types that need more alignment thanvoid* ::operator new(std::size_t)provides ๐ฅ. You can pass a numeric argument like-faligned-new=32to specify how much alignment (in bytes) that function provides, but few users will ever 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โ enableschar8_tas adopted for C++20 ๐ญ. This includes the addition of a brand-newchar8_tfundamental type, changes to the types of UTF-8 string and character literals, new signatures for user-defined literals, associated standard library updates, and new__cpp_char8_tand__cpp_lib_char8_tfeature test macros ๐.
This option lets functions get overloaded for ordinary and UTF-8 strings, and it's giving main character energy:
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
It also introduces new signatures for user-defined literals:
int operator""_udl1(char8_t);
int v3 = u8'x'_udl1;
int operator""_udl2(const char8_t*, std::size_t);
int v4 = u8"text"_udl2;
template<typename T, T...> int operator""_udl3();
int v5 = u8"text"_udl3;
Heads up bestie: the change to the types of UTF-8 string and character literals introduces incompatibilities with ISO C++11 and later standards ๐ฌ. For example, the following code is well-formed under ISO C++11, but it's ill-formed when -fchar8_t is specified:
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 by"operator new"is non-null before it tries to modify the storage it allocated ๐. This check is normally unnecessary, because the C++ standard says"operator new"only returns 0 if it's declaredthrow(). In that case the compiler always checks the return value, even without this option. In every other case, when"operator new"has a non-empty exception specification, memory exhaustion gets signalled by throwing"std::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++20and above, Concepts are part of the language standard, so-fconceptsdefaults 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 by-fconcepts-ts๐.-fconstexpr-depth=nโ sets the maximum nested evaluation depth for C++11 constexpr functions ton๐. A limit is needed to detect endless recursion during constant expression evaluation. The minimum the standard specifies is 512.-fconstexpr-cache-depth=nโ sets the maximum level of nested evaluation depth for C++11 constexpr functions 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 huge from highly recursive evaluations). The default is 8. Very few users will want to adjust it, but if your code does heavy constexpr calculations, you might wanna experiment to find which value works best for you ๐ .-fconstexpr-loop-limit=nโ sets the maximum number of iterations for a loop in C++14 constexpr functions ton๐. A limit is needed to detect infinite loops during constant expression evaluation. The default is 262144 (1<<18).-fconstexpr-ops-limit=nโ sets the maximum number of operations during a single constexpr evaluation ๐งฎ. Even when the iterations of a single loop are limited by the limit above, if there are several nested loops that each have lots of iterations (still under that limit), or if a loop body or code outside any loop needs too many expressions evaluated, the constexpr evaluation might take too long. The default is 33554432 (1<<25).-fcoroutinesโ enables support for the C++ coroutines extension ๐งช. It's experimental, so handle with care ๐ฅน.-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 ๐ช. Specifying this option disables that optimization and forces G++ to call the copy constructor in all cases. It also makes G++ call trivial member functions that would otherwise be expanded inline. In C++17 the compiler is required to omit these temporaries, but this option still affects trivial member functions.-fno-enforce-eh-specsโ don't generate code that checks for violations of exception specifications at run time ๐ซ. This option violates the C++ standard, but it may be useful for reducing code size in production builds, much like defining"NDEBUG". It 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โ the C++11 and OpenMP standards allow"thread_local"and"threadprivate"variables to have dynamic (runtime) initialization ๐งต. To support that, any use of such a variable goes through a wrapper function that does the necessary initialization. When the use and definition are in the same translation unit, this overhead can be optimized away. But when the use is in a different translation unit, there's significant overhead even if the variable doesn't actually need dynamic initialization. If the programmer can be sure that no use of the variable in a non-defining TU needs to trigger dynamic initialization (either because the variable is statically initialized, or because a use in the defining TU will be executed before any uses in another TU), they can avoid this overhead with the-fno-extern-tls-initoption ๐ฆ.
On targets that support symbol aliases, the default is -fextern-tls-init. On targets that don't support symbol aliases, the default is -fno-extern-tls-init โจ.
-fno-gnu-keywordsโ don't recognizetypeofas a keyword, so code can use that word as an identifier ๐. You can use the keyword__typeof__instead. This option is implied by the strict ISO C++ dialects:-ansi,-std=c++98,-std=c++11, etc.-fno-implicit-templatesโ never emit code for non-inline templates that are instantiated implicitly (i.e. by use). Only emit code for explicit instantiations ๐ฆ. If you use this option, you must take care to structure your code so it includes all the necessary explicit instantiations, or you'll end up with undefined symbols at link time ๐ต.-fno-implicit-inline-templatesโ don't emit code for implicit instantiations of inline templates either ๐ท. The default handles inlines differently so that compiles with and without optimization need the same set of explicit instantiations.-fno-implement-inlinesโ to save space, don't emit out-of-line copies of inline functions controlled by"#pragma implementation"๐งน. This causes linker errors if these functions aren't inlined everywhere they're called.-fmodules-ts,-fno-modules-tsโ enables support for C++20 modules ๐งฉ. The-fno-modules-tsoption is usually not needed, since that's the default. Even though this is a C++20 feature, it's not currently implicitly enabled by selecting that standard version ๐.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ โจ okay so this one compiles a header file so it can be imported as a header unit ๐-fmodule-implicit-inlineโ ๐ this one is lowkey a plot twist. Member functions defined right inside their class are not implicitly inline for modular code. That's different from traditional C++ behavior, and there are good reasons for it, but it can be a pain when you're porting code. This flag makes those definitions implicitly inline instead.
ABI warning ๐ this generates an ABI incompatibility, so you have to use it everywhere or nowhere. Definitions outside of a named module stay implicitly inline either way.
-fno-module-lazyโ ๐ธ disables lazy module importing and module mapper creation-fmodule-mapperfamily โ ๐ฎ this is the oracle you query for module name to filename mappings. If you don't specify one, theCXX_MODULE_MAPPERenvironment variable gets used, and if that's unset too, you get an in-process default. The six forms are:-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]
-fmodule-onlyโ ๐ only emits the Compiled Module Interface and skips the object file-fms-extensionsโ ๐ turns offWpedanticwarnings for MFC-style stuff, like implicitintand getting a pointer to a member function with non-standard syntax-fnew-inheriting-ctorsโ โจ enables the P0136 tweak to how C++11 constructor inheritance works. It's part of C++17 but also counts as a Defect Report against C++11 and C++14, so it's giving main character energy. This flag is on by default unless-fabi-version=10or lower is specified.-fnew-ttp-matchingโ ๐ฆ enables the P0522 resolution to Core issue 150. This lets a template with default template arguments be used as an argument for a template template parameter that has fewer template parameters. It's enabled by default for-std=c++17.-fno-nonansi-builtinsโ ๐ disables built-in declarations of functions that ANSI/ISO C doesn't mandate, like"ffs","alloca","_exit","index","bzero","conjf", and other related functions-fnothrow-optโ ๐ treats athrow()exception specification as if it were"noexcept", which cuts down or erases the text size overhead compared to a function with no exception specification. If the function has local variables with non-trivial destructors, the exception specification actually makes the function smaller, because the EH cleanups for those variables can get optimized away.
Semantic change ๐ an exception thrown out of a function with this exception specification results in a call to"terminate"rather than"unexpected".
-fno-operator-namesโ ๐ซ stopsand,bitand,bitor,compl,not,or, andxorfrom being treated as synonyms for the operator name keywords-fno-optional-diagsโ ๐คซ disables diagnostics the standard says a compiler doesn't have to issue. Right now, the only one G++ issues in this category is the one for a name having multiple meanings within a class.-fpermissiveโ ๐ downgrades some diagnostics about nonconformant code from errors to warnings, so some nonconforming code can still compile-fno-pretty-templatesโ ๐ง when an error message points at a specialization of a function template, the compiler normally prints the template signature followed by the template arguments and any typedefs or typenames in it (so you getvoid f(T) [with T = int]instead ofvoid f(int)) so you can tell which template is involved. For a specialization of a class template, it leaves out any template arguments that match the defaults. If either of those behaviors makes the error harder to read, use-fno-pretty-templatesto turn them off.-fno-rttiโ ๐ disables generating the information about every class with virtual functions that the C++ run-time type identification features (dynamic_castandtypeid) use. If you don't use those parts of the language, this can save some space. Exception handling uses the same information, but G++ generates it only as needed. Thedynamic_castoperator still works for casts that don't need run-time type information, meaning casts tovoid *or to unambiguous base classes.
Mixing warning โ ๏ธ 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 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 use the object's size to make deallocation faster. It's enabled by default under -std=c++14 and above. The -Wsized-deallocation flag warns about places that might want to add a definition.
-fstrict-enumsโ ๐งฎ lets the compiler optimize assuming that a value of an enumerated type can only be one of the enumeration's values (per the C++ standard, basically a value that fits in the minimum number of bits needed to represent all the enumerators). This assumption may not hold if the program uses a cast to convert an arbitrary integer into the enumerated type.-fstrong-eval-orderโ ๐ evaluates member access, array subscripting, and shift expressions left-to-right, and assignment right-to-left, as adopted for C++17. It's enabled by default with-std=c++17.-fstrong-eval-order=someonly enables the ordering for 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 for a single warning or error ton. The default is 10.-ftemplate-depth=nโ ๐ sets the maximum instantiation depth for template classes ton. A limit is needed to catch endless recursion during template class instantiation. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than 17 (changed to 1024 in C++11). The default is 900, because the compiler can run out of stack space before hitting 1024 in some situations.-fno-threadsafe-staticsโ ๐งต skips emitting the extra code that uses the routines from the C++ ABI for thread-safe initialization of local statics. It can shave off a bit of code size in code that doesn't need to be thread-safe.-fuse-cxa-atexitโ ๐งน registers destructors for objects with static storage duration with the__cxa_atexitfunction instead ofatexit. This is required for fully standards-compliant handling of static destructors, but it only works if your C library supports__cxa_atexit.-fno-use-cxa-get-exception-ptrโ ๐ โโ๏ธ stops using the__cxa_get_exception_ptrruntime routine. This makesstd::uncaught_exceptionincorrect, but it's necessary if that runtime routine isn't available.
โจ -fvisibility-inlines-hidden โจ
This switch tells GCC that you won't try to compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects. ๐ฆ
GCC may then, effectively, mark inline methods with __attribute__ ((visibility ("hidden"))), so they don't show up in the export table of a DSO and don't need a PLT indirection when they're used inside the 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 heavily on templates. ๐
The behavior isn't quite the same as marking the methods 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 explicitly give a method a visibility to cancel the effect of the switch for that method. For example, if you do want to compare pointers to a particular inline method, mark it with default visibility. Marking the enclosing class with explicit visibility has no effect.
Explicitly instantiated inline methods are unaffected by this option, because their linkage might otherwise cross a shared library boundary. ๐ซถ
โจ -fvisibility-ms-compat โจ
This flag tries to use visibility settings to make GCC's C++ linkage model compatible with Microsoft Visual Studio's. ๐
It makes these changes to GCC's linkage model:
- It sets the default visibility to
"hidden", like-fvisibility=hidden. - Types, 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're permitted when this option isn't 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 might rely (perhaps accidentally) on the Visual Studio behavior.
ODR danger ๐ among the consequences: static data members of the same type, with the same name, defined in different shared objects are different, so changing one doesn't change the other. Pointers to function members defined in different shared objects may also not compare equal. When this flag is given, it's a violation of the ODR to define types with the same name differently.
-fno-weakโ ๐ doesn't use weak symbol support, even if the linker provides it. By default, G++ uses weak symbols when they're available. This option exists only for testing and shouldn't be used by end-users, since it results in inferior code and has no benefits. It may be removed in a future release of G++.-fext-numeric-literals(C++ and Objective-C++ only) โ okay so this one lets you use imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions ๐ Turn it off and those suffixes get treated as C++11 user-defined literal numeric suffixes instead ๐ซถ It's on by default for all the pre-C++11 dialects and all the 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++โ this one tells GCC to skip the standard directories that are specific to C++ when it's looking for headers, but it still searches the other standard directories โจ It's the flag used when building the C++ library, so you know it's serious ๐ง
-flang-info-include-translate,-flang-info-include-translate-not,-flang-info-include-translate=headerโ these are the "tell me everything you did" flags ๐ฆ The first one informs you of accepted include translation events, and the second one spills the declined ones. Theheaderform only gives you the include translation info for that specific header. If header is"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โ main character energy for Compiled Module Interface pathnames ๐ The first one notes all the CMI pathnames that get read. The module form is for a specific module's CMI. module can be a named module or a header-unit, and you can tell it's a header-unit if it's a pathname containing directory separators or it's wrapped in<>or""๐-stdlib=libstdc++,libc++โ when G++ is configured to support this option, you can pick an alternate C++ runtime library ๐ฅ There are two choices:libstdc++(the default, native C++ runtime for G++) andlibc++, which is the C++ runtime installed on some operating systems (e.g. Darwin versions from Darwin11 onwards) ๐ Picking one switches G++ over to the headers from that library, and it'll emit-lstdc++or-lc++respectively when a C++ runtime is needed for linking. Iconic โจ
In addition, these warning options only have meanings for C++ programs, so they're giving very specific vibes ๐
-Wabi-tag(C++ and Objective-C++ only) โ warns you when a type with an ABI tag gets used somewhere that doesn't have that ABI tag ๐ท๏ธ Check out C++ Attributes for more info about ABI tags.-Wcomma-subscript(C++ and Objective-C++ only) โ warns about comma expressions inside a subscripting expression ๐ This usage got deprecated in C++20, but a comma expression wrapped in( )is not deprecated, so you're safe there ๐ซถ Here's the example:
void f(int *a, int b, int c) {
a[b,c]; // deprecated
a[(b,c)]; // OK
}
This one is enabled by default with -std=c++20 ๐
-Wctad-maybe-unsupported(C++ and Objective-C++ only) โ warns you when you do class template argument deduction (CTAD) on a type that doesn't have any explicitly written deduction guides ๐ง This is the one that points out when CTAD only worked because the compiler made up the implicit deduction guides, which might not be what the programmer actually meant. Some style guides only allow CTAD on types that specifically "opt-in" (aka types that are designed to support CTAD), so this warning helps with that. You can suppress it with this pattern (any name works for the tag, btw):
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 no friends and no 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, so please listen to this one. 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'll also deprecate if the class has a user-provided destructor.-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only) โ disables the warning about when the usual arithmetic conversions get applied to operands where one is an enumeration type and the other is a different enumeration type ๐ โโ๏ธ This conversion was deprecated in C++20. For example:
enum E1 { e };
enum E2 { f };
int k = f - e;
-Wdeprecated-enum-enum-conversion is enabled by default with -std=c++20. In pre-C++20 dialects, you can turn this warning on with -Wenum-conversion ๐ธ
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only) โ disables the warning for when the usual arithmetic conversions get applied to operands where one is an enumeration type and the other is a floating-point type ๐ซ This conversion was deprecated in C++20. For example:
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7;
-Wdeprecated-enum-float-conversion is enabled by default with -std=c++20. In pre-C++20 dialects, you can enable this warning with -Wenum-conversion ๐
-Wno-init-list-lifetime(C++ and Objective-C++ only) โ this one turns off warnings about uses ofstd::initializer_listthat are likely to end up with 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. Some examples of how this happens:- If a function returns a temporary
initializer_list, or a localinitializer_listvariable, the array's lifetime ends at the end of the return statement, so the value returned has a dangling pointer. - If a new-expression creates an
initializer_list, the array only lives until the end of the enclosing full-expression, so theinitializer_listin the heap has a dangling pointer. - When an
initializer_listvariable is assigned from a brace-enclosed initializer list, the temporary array created for the right side of the assignment only lives until the end of the full-expression. So at the next statement, theinitializer_listvariable has a dangling pointer. - When a list constructor stores the
beginpointer from theinitializer_listargument, that doesn't extend the lifetime of the array. So if a class variable is constructed from a temporaryinitializer_list, the pointer is left dangling by the end of the variable declaration statement.
- If a function returns a temporary
Here's the code for the assignment one:
// 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
โ ๏ธ That last line is undefined behavior, bestie. Don't let your initializer_list go past its lifetime ๐
-Winvalid-imported-macrosโ verifies that all imported macro definitions are valid at the end of compilation ๐ This one is not enabled by default, because it needs additional processing to figure that out. It may be useful when you're preparing sets of header-units to make sure the macros are consistent ๐ง-Wno-literal-suffix(C++ and Objective-C++ only) โ doesn't warn when a string or character literal is followed by a ud-suffix that doesn't begin with an underscore ๐ As a conforming extension, GCC treats these suffixes as separate preprocessing tokens so that old code using 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 is treated as a separate preprocessing token ๐ฆ
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 these warnings are enabled by default โ ๏ธ
-Wno-narrowing(C++ and Objective-C++ only) โ for C++11 and later standards, narrowing conversions are diagnosed by default, as the standard requires ๐ A narrowing conversion from a constant gives you an error, and a narrowing conversion from a non-constant gives you a warning.-Wno-narrowingsuppresses that diagnostic. Heads up: this doesn't change the meaning of well-formed code, since narrowing conversions are still considered ill-formed in SFINAE contexts ๐ โโ๏ธ
With -Wnarrowing in C++98, you get a warning when a narrowing conversion that C++11 prohibits happens within { }, e.g.:
int i = { 2.2 }; // error: narrowing from double to int
This flag is included in -Wall and -Wc++11-compat ๐
-Wnoexcept(C++ and Objective-C++ only) โ warns when anoexcept-expression evaluates to false because of a call to a function that doesn't have a non-throwing exception specification (i.e.throw()or"noexcept"), but the compiler knows it never 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 ๐งฌ This one is enabled by-Wabiand-Wc++17-compat. Here's an example:
template <class T> void f(T t) { t(); };
void g() noexcept;
void h() { f(g); }
In C++14, f calls f<void(*)()>, but in C++17 it calls f<void(*)()noexcept> โจ
-Wclass-memaccess(C++ and Objective-C++ only) โ okay bestie, this one is ALARM ๐จ It warns when you hand a raw memory function likememsetormemcpya class-type object as its destination, and writing into it could bypass the class's non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers. Messing with the raw bytes of these objects can violate invariants the class's member functions are supposed to keep ๐ For example, thememsetcall below is undefined because it modifies a non-trivial class object, so it gets diagnosed ๐
std::string str = "abc";
memset (&str, 0, sizeof str);
The slay way to initialize or clear the storage of these objects is to use the appropriate constructor or assignment operator, if one is available ๐ The -Wclass-memaccess option is enabled by -Wall. Casting the pointer to the class object to void *, or to a type that the raw memory function can safely access, suppresses the warning ๐
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ 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 or 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. Usingregisteras 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 actually have to run in. For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler rearranges the member initializers for i and j to match the declaration order of the members, and emits a warning to that effect ๐ง This warning is enabled by -Wall.
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this one warns when a call tostd::moveprevents copy elision ๐ โโ๏ธ The classic situation where copy elision can happen is returning from a function with a class return type, when the returned expression is the name of a non-volatile automatic object that isn't a function parameter and has the same type as the function's return type. Here's the vibe:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
But in this example, the std::move call prevents copy elision ๐ญ This warning is enabled by -Wall.
-Wno-redundant-move(C++ and Objective-C++ only) โ this one warns about redundant calls tostd::move, which means cases where a move operation would have happened even without thestd::movecall ๐ธ That's because the compiler is forced to treat the object as if it were an rvalue in certain situations, like returning a local variable where copy elision isn't applicable. Consider:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant ๐
Because G++ implements Core Issue 1579, another example is:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this example, copy elision isn't applicable because the type of the returned expression and the function's return type differ. Even so, G++ treats the return value as if it were designated by an rvalue, which is the main character plot twist ๐ This warning is enabled by -Wextra.
-Wrange-loop-construct(C++ and Objective-C++ only) โ this one warns when a C++ range-based for loop is making an unnecessary copy ๐ That can happen when the range declaration isn't a reference, but honestly 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 fires when a loop variable in a range-based for-loop is initialized with a value of a different type, which causes a copy. For example:
void fn() {
int arr[10];
for (const double &x : arr) { ... }
}
In the example above, every iteration creates and destroys a temporary value of type double, and the reference const double & is bound to 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, because the keyword is actually needed there ๐
struct foo;
void foo (); // "hides" struct foo
void bar (struct foo&); // no warning, keyword struct is necessary
-Wno-subobject-linkage(C++ and Objective-C++ only) โ don't warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐ If 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. The compiler doesn't give this warning for types defined in the main.Cfile, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default ๐-Weffc++(C++ and Objective-C++ only) โ warns about violations of these 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 ๐ซถ
When you select this option, be aware that the standard library headers don't obey all of these guidelines. Use grep -v to filter out those warnings, bestie ๐งน
-Wno-exceptions(C++ and Objective-C++ only) โ disables the warning for when an exception handler is shadowed by another handler, which can point out a wrong ordering of exception handlers ๐-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about using an uncastedNULLas a sentinel. When compiling only with GCC, this is a valid sentinel, becauseNULLis defined to__null. Although it's a null pointer constant rather than a null pointer, it's guaranteed to be the same size as a pointer. But this use isn't portable across different compilers, so watch out ๐-Wno-non-template-friend(C++ and Objective-C++ only) โ disables warnings when non-template friend functions are declared within a template. In very old versions of GCC that predate the ISO standard implementation, declarations such asfriend int foo(int), where the name of the friend is an unqualified-id, could be interpreted as a particular specialization of a template function. The warning exists to diagnose those compatibility problems, and it's enabled by default ๐ฐ๏ธ-Wold-style-cast(C++ and Objective-C++ only) โ warns if an old-style (C-style) cast to a non-void type is used in a C++ program. The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are less vulnerable to unintended effects and much easier to search for ๐-Woverloaded-virtual(C++ and Objective-C++ only) โ warns when a function declaration hides virtual functions from a base class. For example:
struct A {
virtual void f();
};
struct B: public A {
void f(int);
};
The A class version of f is 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 to a plain pointer ๐งฉ-Wsign-promo(C++ and Objective-C++ only) โ warns when overload resolution picks a promotion from an unsigned or enumerated type to a signed type, over a conversion to an unsigned type of the same size. Previous versions of G++ tried to preserve unsignedness, but the standard mandates the current behavior ๐-Wtemplates(C++ and Objective-C++ only) โ warns when a primary template declaration is encountered. Some coding rules disallow templates, and this can be used to enforce that rule ๐ซ The warning is inactive inside a system header file, such as the STL, so you can still use the STL ๐ซง You're also allowed to instantiate or specialize templates.-Wno-mismatched-new-delete(C++ and Objective-C++ only) โ okay bestie, this one is all about catching mix-ups betweenoperator newandoperator delete๐ง. It warns when those calls don't match the allocation or deallocation function they go with. That includes C++operator deletegetting a pointer from a mismatched form ofoperator new, or from some other function that allocates objectsoperator deleteisn't a suitable deallocator for. It also flags other deallocation functions handed a pointer fromoperator newwhen they aren't the right match ๐ .
For example, the delete expression in the function below gets flagged because it doesn't match the array form of the new expression the pointer came from. The free call 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 enabled by default โจ.
-Wmismatched-tags(C++ and Objective-C++ only) โ this one warns when a struct, class, or class template (or one of its specializations) gets declared with a class-key that doesn't match its definition, or its first declaration if there's no definition yet ๐. Keeping the vibes consistent, bestie.
In the example below, the declaration of struct Object in the argument list of draw triggers the warning. To avoid it, either remove the redundant class-key struct or swap it for class to match the definition.
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
It's not wrong to declare a class with the class-key struct, as shown above. -Wmismatched-tags just exists to help you achieve a consistent style of class declarations ๐
. In code meant to be portable to Windows-based compilers, the warning also helps prevent unresolved references caused by the difference in the mangling of symbols declared with different class-keys ๐ฅ. The option can be used on its own or together with -Wredundant-tags.
-Wmultiple-inheritance(C++ and Objective-C++ only) โ warns when a class is defined with multiple direct base classes ๐ฆ. Some coding rules ban multiple inheritance, so this helps enforce that rule. The warning is inactive inside a system header file, like the STL, so you can still use the STL ๐. You're also allowed to define classes that indirectly use multiple inheritance.-Wvirtual-inheritanceโ warns when a class is defined with a virtual direct base class ๐. Same deal as above: some coding rules disallow multiple inheritance, and this can be used to enforce that rule. It's inactive inside a system header file like the STL, so the STL is still good to go โจ. You can also define classes that indirectly use virtual inheritance.-Wno-virtual-move-assignโ suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator ๐.
Heads up, bestie: this is dangerous ๐. If the virtual base can be reached along more than one path, it gets moved multiple times, which can mean both objects end up in the moved-from state. If the move assignment operator is written to avoid moving from a moved-from object, though, this warning can be disabled safely ๐ซถ.
-Wnamespacesโ warns when a namespace definition is opened ๐ธ. Some coding rules disallow namespaces, so this helps enforce that. It's inactive inside system header files like the STL, so the STL keeps working. You can still use using directives and qualified names, too ๐ง.-Wno-terminate(C++ and Objective-C++ only) โ disables the warning about a throw-expression that will immediately result in a call toterminate๐ .-Wno-vexing-parse(C++ and Objective-C++ only) โ warns about the most vexing parse syntactic ambiguity ๐คฏ. This is when a declaration looks like a variable definition, but C++ requires it to be read as a function declaration. For instance:
void f(double a) {
int i(); // extern int i (void);
int n(int(a)); // extern int n (int);
}
Another example:
struct S { S(int); };
void f(double a) {
S x(int(a)); // extern struct S x (int);
S y(int()); // extern struct S y (int (*) (void));
S z(); // extern struct S z (void);
}
The warning suggests ways to deal with the ambiguity, like removing the parentheses or using braces instead ๐. This warning is enabled by default โจ.
-Wno-class-conversion(C++ and Objective-C++ only) โ don't warn when a conversion function converts an object to the same type, to a base class of that type, or tovoid๐ฆ. Such a conversion function will never be called, so this is one for the "I know what I'm doing" crowd ๐ .-Wvolatile(C++ and Objective-C++ only) โ warns about deprecated uses of thevolatilequalifier ๐ฅ. That includes postfix and prefix++and--expressions ofvolatile-qualified types, simple assignments where the left operand is avolatile-qualified non-class type (for their value), compound assignments where the left operand is avolatile-qualified non-class type,volatile-qualified function return types,volatile-qualified parameter types, and structured bindings of avolatile-qualified type. This usage was deprecated in C++20 ๐.
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 helpful when you're converting over tonullptrin C++11 ๐.-Waligned-newโ warns about a new-expression of a type that needs greater alignment thanalignof(std::max_align_t), but uses an allocation function without an explicit alignment parameter ๐. This option is enabled by-Wallโจ.
Normally 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 ๐, like constructing an object in a buffer that's smaller than the object's type. For example, 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 of-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]();
-Wplacement-new=2โ at this level, GCC diagnoses all the same constructs as level 1, plus placement new expressions that construct an object in the last member of a structure whose type is an array of a single element, when that size is less than the size of the object being constructed ๐ฅ. The previous example gets diagnosed at this level. The construct below uses the flexible member array extension to avoid the warning at level 2 ๐.
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ warns about catch handlers that don't catch via reference ๐ฆ. With-Wcatch-value=1(or just-Wcatch-value), it warns about polymorphic class types that are caught by value. With-Wcatch-value=2, it warns about all class types caught by value. With-Wcatch-value=3, it warns about all types that aren't caught by reference ๐.-Wcatch-valueis enabled by-Wallโจ.-Wconditionally-supported(C++ and Objective-C++ only) โ warns for conditionally-supported constructs (C++11[intro.defs]) ๐.-Wno-delete-incomplete(C++ and Objective-C++ only) โ don't warn when deleting a pointer to an incomplete type, which may cause undefined behavior at runtime ๐. This warning is enabled by default, so this option is how you turn it off ๐.-Wextra-semi(C++, Objective-C++ only) โ warns about redundant semicolons after in-class function definitions ๐ง.-Wno-inaccessible-base(C++, Objective-C++ only) โ this option controls warnings when a base class is inaccessible in a class derived from it because of ambiguity ๐ธ. The warning is enabled by default. Note that the warning for ambiguous virtual bases is enabled by the-Wextraoption. Here's the ambiguity in action:
struct A { int a; };
struct B : A { };
struct C : B, A { };
-Wno-inherited-variadic-ctorโ suppresses warnings about using C++11 inheriting constructors when the base class being inherited from has a C variadic constructor ๐ . The warning is on by default because the ellipsis is not inherited ๐.-Wno-invalid-offsetof(C++ and Objective-C++ only) โ suppresses warnings from applying theoffsetofmacro to a non-POD type ๐. According to the 2014 ISO C++ standard, applyingoffsetofto a non-standard-layout type is undefined. In existing C++ implementations, though,offsetoftypically gives meaningful results. This flag is for users who know they're writing nonportable code and have deliberately chosen to ignore the warning ๐.
The restrictions on offsetof may be relaxed in a future version of the C++ standard ๐.
-Wsized-deallocation(C++ and Objective-C++ only) โ warns about a definition of an unsized deallocation function ๐ฆ.
Okay so this is where the warning list gets spicy ๐ถ๏ธ GCC is watching for a class that defines one of these deallocators:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
...but doesn't define the matching sized one:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
...or the other way around, bestie ๐ It's enabled by -Wextra along with -fsized-deallocation ๐ง
-Wsuggest-final-typesโ Okay, this one's for types with virtual methods that would look cleaner marked with the C++11"final"specifier. If it's possible, it'll also suggest putting the type in an anonymous namespace instead ๐ฆ Doing that lets GCC devirtualize polymorphic calls way more aggressively, which is so big brain of it ๐ง This warning hits harder with link-time optimization, since GCC has a fuller picture of the class hierarchy then โจ-Wsuggest-final-methodsโ Same energy, but for individual virtual methods ๐ It'll nudge you to mark a method"final", or, if it's possible, put its type in an anonymous namespace or give it the"final"specifier. Also works better with link-time optimization for the same reason, since the class hierarchy graph is more complete there ๐ Pro tip (from the manual, not me ๐): look at-Wsuggest-final-typessuggestions first, then rebuild with the new annotations.-Wsuggest-overrideโ Warns when you override a virtual function without slapping the"override"keyword on it ๐ซถ No more sneaky overrides, periodt ๐-Wuseless-cast(C++ and Objective-C++ only) โ Warns when an expression gets cast to its own type. Literally pointless, so GCC will call it out ๐-Wno-conversion-null(C++ and Objective-C++ only) โ Turns off the warning for conversions between"NULL"and non-pointer types. Heads up,-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, okay? This section is just 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, compiling a file called some_class.m might look like this:
gcc -g -fgnu-runtime -O -c some_class.m
In that example, -fgnu-runtime is a flag meant only for Objective-C and Objective-C++ programs, but you can use the other options with any language GCC supports ๐ธ
Since Objective-C is an extension of C, Objective-C compiles can also use C front-end options (like -Wtraditional). Similarly, Objective-C++ compiles 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โ Picks the class that gets instantiated for every literal string written as"@"...""๐ The default is"NXConstantString"when the GNU runtime is in use, and"NSConstantString"when the NeXT runtime is in use (more on that below). On Darwin (macOS, MacOS X), if-fconstant-cfstringsis also there, it overrides-fconstant-string-classand makes"@"...""literals get laid out as constant CoreFoundation strings โจ Also,-fconstant-cfstringsis just an alias for the target-specific-mconstant-cfstringsequivalent.-fgnu-runtimeโ Generates object code that works with the standard GNU Objective-C runtime ๐ This is the default for most systems.-fnext-runtimeโ Generates output compatible with the NeXT runtime ๐ This is the default for NeXT-based systems, including Darwin and Mac OS X. The macro__NEXT_RUNTIME__is predefined if, and only if, this option is used.-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 is only available with the NeXT runtime and ABI version 0 or 1.-fobjc-abi-version=nโ Uses versionnof the Objective-C ABI for the runtime you picked. Right now this is only supported for the NeXT runtime, where:- Version 0 is the traditional (32-bit) ABI, no properties or other Objective-C 2.0 extras ๐
- Version 1 is the traditional (32-bit) ABI with properties and other Objective-C 2.0 additions ๐
- Version 2 is the modern (64-bit) ABI ๐
- If you don't specify anything, the default is Version 0 on 32-bit target machines and Version 2 on 64-bit target machines.
-fobjc-call-cxx-cdtorsโ For each Objective-C class, GCC checks whether any of its instance variables is a C++ object with a non-trivial default constructor. If so, it synthesizes a special- (id) .cxx_constructinstance method that runs those non-trivial default constructors on those instance variables, in order, then returnsself๐ง It also checks for instance variables that are C++ objects with a non-trivial destructor, and if it finds any, it synthesizes a- (void) .cxx_destructmethod that runs all those default destructors in reverse order ๐
The - (id) .cxx_construct and - (void) .cxx_destruct methods generated this way only touch instance variables declared in the current Objective-C class, not the ones inherited from superclasses. It's the Objective-C runtime's job to call all of these methods across an object's inheritance hierarchy ๐ซถ The - (id) .cxx_construct methods get invoked by the runtime right after a new object instance is allocated, and the - (void) .cxx_destruct methods get invoked right before the runtime deallocates an object instance.
As of this writing, only the NeXT runtime on Mac OS X 10.4 and later can invoke the - (id) .cxx_construct and - (void) .cxx_destruct methods ๐
-fobjc-direct-dispatchโ Allows fast jumps to the message dispatcher โก On Darwin, this is done through the comm page.-fobjc-exceptionsโ Turns on syntax support for structured exception handling in Objective-C, kind of like C++ ๐ซง You need this to use the Objective-C keywords@try,@throw,@catch,@finally, and@synchronized. It works with both the GNU runtime and the NeXT runtime, but not with the NeXT runtime on Mac OS X 10.2 and earlier ๐-fobjc-gcโ Enables garbage collection (GC) in Objective-C and Objective-C++ programs ๐๏ธ This is only available with the NeXT runtime. The GNU runtime has its own GC implementation that doesn't need any special compiler flags.-fobjc-nilcheckโ For the NeXT runtime with version 2 of the ABI, checks for anilreceiver in method invocations before the actual method call happens ๐ก๏ธ This is the default, and you can turn it off with-fno-objc-nilcheck. Class methods and super calls are never checked fornilthis way, no matter what this flag is set to. Right now this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is in use.-fobjc-std=objc1โ Makes your code follow the language syntax of Objective-C 1.0, the one GCC 4.0 recognized ๐ This only changes 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 this on, any Objective-C syntax GCC 4.0 doesn't recognize gets rejected, so it's super useful if you need your code to still compile with older versions of GCC ๐ฐ๏ธ-freplace-objc-classesโ Emits a special marker tellingld(1)not to statically link the resulting object file, and letsdyld(1)load it at run time instead ๐ฆ This pairs with the Fix-and-Continue debugging mode, where the object file can be recompiled and dynamically reloaded during execution without restarting the whole program. 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, the compiler usually swaps out calls toobjc_getClass("...")(when the class name is known at compile time) for static class references that get initialized at load time, which is faster at run time ๐ Using-fzero-linkturns that off, so calls toobjc_getClass("...")stick around. This is handy in Zero-Link debugging mode, since it lets you modify individual class implementations while the program is running. The GNU runtime always keeps calls toobjc_get_class("...")no matter what command-line options you pass ๐คทโโ๏ธ-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 with the same name, either declared locally inside a class method or globally. Specifying-fno-local-ivarsturns this behavior off, so you dodge those shadowing issues ๐-fivar-visibility=[public|protected|private|package]โ Sets the default instance variable visibility to whatever option you pick ๐ So instance variables declared outside the scope of any access modifier directives default to that visibility.-gen-declsโ Dumps the interface declarations for all classes seen in the source file into a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ Warns whenever an Objective-C assignment gets intercepted by the garbage collector ๐๏ธโจ-Wno-property-assign-default(Objective-C and Objective-C++ only) โ Stops the warning for Objective-C object properties that don't have assign semantics specified ๐-Wno-protocol(Objective-C and Objective-C++ only) โ okay so if a class says it implements a protocol, GCC warns you for every protocol method the class doesn't implement ๐ซถ By default it also warns about methods the class doesn't explicitly implement, even when the superclass already handles them ๐ With-Wno-protocol, inherited methods from the superclass count as implemented, so no warning for those โจ-Wobjc-root-class(Objective-C and Objective-C++ only) โ warns if a class interface has no superclass ๐ Most classes inherit from"NSObject"(or"Object"), for example. If you're making a root class on purpose, you can shush 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 show up for the same selector during compilation ๐ This check runs on the method list in the final stage of compilation. It also checks each selector used in a@selector(...)expression when a matching method was found during compilation. Since these checks only scan the method table at the very end, the warnings won't appear if the final stage never happens, like when an error stops things early or you're using-fsyntax-only๐-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if a selector has multiple methods with different argument and/or return types when you try to send a message with it to a receiver of typeidorClass๐ When this flag is off (the default), the compiler skips these warnings if the differences are only between types with the same size and alignment ๐คทโโ๏ธ-Wundeclared-selector(Objective-C and Objective-C++ only) โ warns when 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 the moment it spots a@selector(...)expression, while-Wselectoronly checks in the final stage. 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 โจ
Back in the day, diagnostic messages got formatted without caring what the output device looked like (its width, ...) ๐ These options let you control the formatting algorithm, like how many characters go on a line and how often source location info gets reported ๐ Heads up: some language front ends might not honor these options ๐ซ
-fmessage-length=nโ tries to format error messages so they fit on lines about n characters wide ๐ If n is zero, no line-wrapping happens and each error message sits on a single line. That's the default for all front ends ๐
Note - this option also affects the display of the#errorand#warningpre-processor directives, and the deprecated function/type/variable attribute. It does not however affect thepragma GCC warningandpragma GCC errorpragmas.
-fdiagnostics-plain-outputโ requests that diagnostic output look as plain as possible ๐งผ This is handy when you're running dejagnu or other tools that parse diagnostics and need the output to stay stable over time ๐ซถ Right now it's equivalent to these options:
-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never -fdiagnostics-urls=never -fdiagnostics-path-format=separate-events
In the future, if GCC 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 reporter to emit source location info just once. If a message is too long and has to wrap, the location prefix won't get stuck on every continuation line again and again. This is the default ๐-fdiagnostics-show-location=every-lineโ only matters in line-wrapping mode ๐ฆ It tells the reporter to put the same source location prefix on every physical line that results from breaking up a message that's too long to fit on one line ๐-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ turns on color in diagnostics ๐WHENcan benever,always, orauto. The default depends on how the compiler was configured. It can be any of thoseWHENoptions, orneverif theGCC_COLORSenvironment variable isn't present, andautootherwise.autoonly uses color when standard error is a terminal and you're not running in an emacs shell ๐ธ The forms-fdiagnostics-colorand-fno-diagnostics-colorare aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively ๐ฅ
The colors are defined by the environment variable GCC_COLORS. Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings ๐จ SGR commands are interpreted by the terminal or terminal emulator, so check the docs for your text terminal to see the permitted values and what they mean as character attributes ๐ These substring values are integers in decimal and can be concatenated with semicolons. Common values to concatenate include 1 for bold, 4 for underline, 5 for blink, 7 for inverse, 39 for default foreground color, 30 to 37 for foreground colors, 90 to 97 for 16-color mode foreground colors, 38;5;0 to 38;5;255 for 88-color and 256-color modes foreground colors, 49 for default background color, 40 to 47 for background colors, 100 to 107 for 16-color mode background colors, and 48;5;0 to 48;5;255 for 88-color and 256-color modes background colors ๐
The default GCC_COLORS is ๐
error=01;31:warning=01;35:note=01;36:range1=32:range2=34:locus=01:\
quote=01:path=01;36:fixit-insert=32:fixit-delete=31:\
diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
type-diff=01;32
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 โจ Supported capabilities are as follows ๐
error=โ the SGR substring forerror:markers ๐ฅwarning=โ the SGR substring forwarning:markers โ ๏ธnote=โ the SGR substring fornote:markers ๐path=โ the SGR substring for colorizing 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=โ the SGR substring for the first additional range 1๏ธโฃrange2=โ the SGR substring for the second additional range 2๏ธโฃlocus=โ the SGR substring for location info, likefile:lineorfile:line:columnetc. ๐quote=โ the SGR substring for info printed within quotes ๐ฌfixit-insert=โ the SGR substring for fix-it hints suggesting text to be inserted or replaced โfixit-delete=โ the SGR substring for fix-it hints suggesting text to be deleted โdiff-filename=โ the SGR substring for filename headers within generated patches ๐diff-hunk=โ the SGR substring for the starts of hunks within generated patches ๐งฉdiff-delete=โ the SGR substring for deleted lines within generated patches ๐๏ธdiff-insert=โ the SGR substring for inserted lines within generated patches ๐ฑtype-diff=โ the SGR substring for highlighting mismatching types within template arguments in the C++ frontend ๐
-fdiagnostics-urls[=WHEN]โ uses escape sequences to embed URLs in diagnostics ๐ For example, when-fdiagnostics-show-optionshows the command-line option controlling a diagnostic, GCC embeds 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 any graphical terminal known to be incompatible with this feature (see below) ๐ฅ๏ธ
The default depends on how the compiler was configured. 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 configuration, GCC defaults to auto if either the GCC_URLS or TERM_URLS environment variables are present and non-empty in the environment of the compiler, or never if neither are ๐ง
However, even with -fdiagnostics-urls=always, the behavior still depends on those environment variables ๐ If GCC_URLS is set to empty or no, URLs are not embedded in diagnostics. If it's set to st, URLs use ST escape sequences. If it's set to bel, which is the default, URLs use BEL escape sequences. Any other non-empty value enables the feature. If GCC_URLS isn't set, TERM_URLS is used as a fallback ๐
Note: ST is an ANSI escape sequence, string terminator ESC \, BEL is an ASCII character, CTRL-G that usually sounds like a beep ๐
Okay so, GCC also tries to sniff out a few terminals that don't play nice with the URL feature ๐. Some of them have bugs (or at least had bugs in versions people still use) where the URL escapes are likely to misbehave and print garbage all over your screen ๐. The current hit list is xfce4-terminal, certain known-buggy gnome-terminal versions, the linux console, and mingw ๐ญ. If you're sure your setup is fine, you can skip this check with -fdiagnostics-urls=always โจ
-fno-diagnostics-show-optionโ By default, every diagnostic includes a little hint naming the command-line option that directly controls it (if GCC knows about that option) ๐. Add this flag and that hint gets suppressed ๐ .-fno-diagnostics-show-caretโ Normally each diagnostic shows the original source line plus a caret^pointing at the column ๐ฏ. This option hides all of that. If you pass-fmessage-length=n, the source line gets truncated toncharacters. When the output is going to a terminal, the width is limited to the width given by theCOLUMNSenvironment variable or, if that isn't set, to the terminal width ๐.-fno-diagnostics-show-labelsโ When GCC prints source code (via-fdiagnostics-show-caret), diagnostics can slap labels on ranges of code with pertinent info, like expression types. Peep this:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option kills those labels, so no vertical bars and no "char *" or "long int" text in the example above ๐ท๏ธ๐ซ.
-fno-diagnostics-show-cweโ Diagnostics can optionally carry a CWE identifier (seehttps://cwe.mitre.org/index.html) ๐ก๏ธ. GCC itself only provides this metadata for some of the-fanalyzerdiagnostics, and GCC plugins may provide it too. By default, if the info is there, it gets printed along with the diagnostic. This option stops that metadata from showing up.-fno-diagnostics-show-line-numbersโ By default, when printing source code (via-fdiagnostics-show-caret), GCC prints a left margin showing line numbers ๐ข. This option gets rid of that margin.-fdiagnostics-minimum-margin-width=widthโ 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, which is perfect for IDEs ๐ ๏ธ. For each fix-it, a line gets printed after the relevant diagnostic, starting with the stringfix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
The location is a half-open range measured in bytes, starting at byte 1 for the initial column. In the example above, bytes 3 through 20 of line 45 of "test.c" get replaced with the given string:
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape backslash as "\\", tab as "\t", newline as "\n", double quotes as "\"", and non-printable characters as octal (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 diagnostics show mismatching template types, such as:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
this flag enables a tree-like structure showing the common and differing parts of the types, such as:
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 about mismatching template types, the common parts get printed as[...]so the error message stays short ๐ค. For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying -fno-elide-type suppresses that behavior ๐ซ. This flag also affects the output of -fdiagnostics-show-template-tree.
-fdiagnostics-path-format=KINDโ Specifies how to print paths of control-flow events for diagnostics that have one attached ๐ค๏ธ.
KIND is none, separate-events, or inline-events, the default.
none means to not print diagnostic paths.
separate-events means to print a separate note diagnostic for each event within the diagnostic. For example:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-events means to print the events "inline" within the source code. This view tries to consolidate the events into runs of sufficiently-close events, printing them as labelled ranges within the source. For example, the same events as above might be printed as:
'test': events 1-3
|
| 25 | list = PyList_New(0);
| | ^~~~~~~~~~~~~
| | |
| | (1) when 'PyList_New' fails, returning NULL
| 26 |
| 27 | for (i = 0; i < count; i++) {
| | ~~~
| | |
| | (2) when 'i < count'
| 28 | item = PyLong_FromLong(random());
| 29 | PyList_Append(list, item);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
|
Interprocedural control flow is shown by grouping the events by stack frame, and using indentation to show how stack frames are nested, pushed, and popped ๐ช. For example:
'test': events 1-2
|
| 133 | {
| | ^
| | |
| | (1) entering 'test'
| 134 | boxed_int *obj = make_boxed_int (i);
| | ~~~~~~~~~~~~~~~~~~
| | |
| | (2) calling 'make_boxed_int'
|
+--> 'make_boxed_int': events 3-4
|
| 120 | {
| | ^
| | |
| | (3) entering 'make_boxed_int'
| 121 | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (4) calling 'wrapped_malloc'
|
+--> 'wrapped_malloc': events 5-6
|
| 7 | {
| | ^
| | |
| | (5) entering 'wrapped_malloc'
| 8 | return malloc (size);
| | ~~~~~~~~~~~~~
| | |
| | (6) calling 'malloc'
|
<-------------+
|
'test': event 7
|
| 138 | free_boxed_int (obj);
| | ^~~~~~~~~~~~~~~~~~~~
| | |
| | (7) calling 'free_boxed_int'
|
(etc)
-fdiagnostics-show-path-depthsโ Adds extra info when printing control-flow paths associated with a diagnostic ๐งญ. If this option is given, the stack depth gets printed for each run of events within-fdiagnostics-path-format=separate-events. It's intended for GCC developers and plugin developers debugging diagnostics that report interprocedural control flow ๐งช.-fno-show-columnโ Don't print column numbers in diagnostics ๐. This may be necessary if diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu.-fdiagnostics-column-unit=UNITโ Selects the units for the column number ๐. This affects traditional diagnostics (as long as-fno-show-columnisn't in use), as well as JSON format diagnostics if they're requested ๐.
Okay so the default UNIT is display, which means GCC counts how many display columns each character actually takes up ๐
. That can be bigger than the bytes needed to encode it (hi, tab characters ๐) or smaller (multibyte characters are sneaky โจ). Like, GREEK SMALL LETTER PI (U+03C0) takes up one display column but its UTF-8 encoding needs two bytes ๐ธ. Meanwhile SLIGHTLY SMILING FACE (U+1F642) takes up two display columns and needs four bytes ๐.
Setting UNIT to byte switches the column number to the raw byte count in every single case. That's what GCC used to output before version 11.1.0, so if you're giving old-school vibes ๐ฐ๏ธ, this is your setting ๐.
๐ -fdiagnostics-column-origin=ORIGIN
This picks the origin for column numbers, which is basically the number given to the first column ๐ข. The default is 1, which matches traditional GCC behaviour and the GNU style guide ๐. Some utilities work better with an origin of 0, so any non-negative value is allowed ๐ฆ.
๐ฆ -fdiagnostics-format=FORMAT
This changes how diagnostics get printed. FORMAT is either text or json, and the default is text ๐
.
The json format is a top-level JSON array full of JSON objects, one for each diagnostic ๐ง.
The JSON gets emitted as one single line with no formatting at all ๐ญ, so the examples below have been dressed up for clarity โจ.
Diagnostics can have child diagnostics too. For example, this error and note:
misleading-indentation.c:15:3: warning: this 'if' clause does not
guard... [-Wmisleading-indentation]
15 | if (flag)
| ^~
misleading-indentation.c:17:5: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
17 | y = 2;
| ^
might be printed in JSON form (after formatting) like this:
[
{
"kind": "warning",
"locations": [
{
"caret": {
"display-column": 3,
"byte-column": 3,
"column": 3,
"file": "misleading-indentation.c",
"line": 15
},
"finish": {
"display-column": 4,
"byte-column": 4,
"column": 4,
"file": "misleading-indentation.c",
"line": 15
}
}
],
"message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"display-column": 5,
"byte-column": 5,
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"message": "...this statement, but the latter is ..."
}
]
"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 ๐ฅ.
A diagnostic can contain zero or more locations. Each location has an optional "label" string and up to three positions inside it: a "caret" position and optional "start" and "finish" positions. A position is described by a "file" name, a "line" number, and three numbers indicating a column position ๐:
"display-column"counts display columns, accounting for tabs and multibyte characters."byte-column"counts raw bytes."column"is equal to one of the previous two, as dictated by the-fdiagnostics-column-unitoption.
All three columns are relative to the origin specified by -fdiagnostics-column-origin, which is typically equal to 1 but may be set, for instance, to 0 for compatibility with other utilities that number columns from 0 ๐. The column origin is recorded in the JSON output in the "column-origin" tag. In the remaining examples below, the extra column number outputs have been left out for brevity ๐.
For example, this error:
bad-binary-ops.c:64:23: error: invalid operands to binary + (have 'S' {aka
'struct s'} and 'T' {aka 'struct t'})
64 | return callee_4a () + callee_4b ();
| ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| | |
| | T {aka struct t}
| S {aka struct s}
has three locations ๐. Its primary location is at the + token at column 23. It has two secondary locations, describing the left and right-hand sides of the expression, and those have labels. It might be printed in JSON form as:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"message": "invalid operands to binary + ..."
}
If a diagnostic contains fix-it hints, it has a "fixits" array, made of half-open intervals, similar to the output of -fdiagnostics-parseable-fixits ๐ฉน. For example, this diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
might be printed in JSON form as:
{
"children": [],
"fixits": [
{
"next": {
"column": 21,
"file": "demo.c",
"line": 8
},
"start": {
"column": 15,
"file": "demo.c",
"line": 8
},
"string": "color"
}
],
"kind": "error",
"locations": [
{
"caret": {
"column": 15,
"file": "demo.c",
"line": 8
},
"finish": {
"column": 20,
"file": "demo.c",
"line": 8
}
}
],
"message": "\u2018struct s\u2019 has no member named ..."
}
where the fix-it hint suggests replacing the text from "start" up to but not including "next" with the value of "string". Deletions are expressed via an empty value for "string", and insertions by having "start" equal "next" โจ.
If the diagnostic has a path of control-flow events associated with it, it has a "path" array of objects representing those events ๐ฆ. Each event object has a "description" string and a "location" object, along with a "function" string and a "depth" number for representing interprocedural paths. The "function" represents the current function at that event, and the "depth" represents the stack depth relative to some baseline: the higher the number, the more frames are within the stack ๐ธ.
For example, the intraprocedural example shown for -fdiagnostics-path-format= might have this JSON for its path:
"path": [
{
"depth": 0,
"description": "when 'PyList_New' fails, returning NULL",
"function": "test",
"location": {
"column": 10,
"file": "test.c",
"line": 25
}
},
{
"depth": 0,
"description": "when 'i < count'",
"function": "test",
"location": {
"column": 3,
"file": "test.c",
"line": 27
}
},
{
"depth": 0,
"description": "when calling 'PyList_Append', passing NULL from (1) as argument 1",
"function": "test",
"location": {
"column": 5,
"file": "test.c",
"line": 29
}
}
]
โจ Options to Request or Suppress Warnings โจ
okay so warnings are the compiler's little "hmm, are you sure about that?" messages ๐ They're for constructions that aren't technically wrong, but are risky or might mean you goofed somewhere. ๐
The options below are language-independent, which means they don't switch on any specific warning. Instead, they control what kinds of diagnostics GCC produces. ๐ซถ
-fsyntax-onlyโ bestie, this just checks your code for syntax errors and then stops right there. Nothing extra, no drama. ๐ง-fmax-errors=nโ the vibe check for error floods ๐ญ Cap the number of error messages at n, and GCC bails out instead of trying to keep going through the source. The default is 0, which means no limit at all, so the errors just keep coming. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option ๐-wโ mutes every single warning message. Total silence, no cap. ๐คซ-Werrorโ turns every warning into an actual error. Main character energy, but make it strict ๐จ-Werror=โ targets one specific warning and makes it an error. You append the warning's name, so-Werror=switchturns the warnings controlled by-Wswitchinto errors ๐ฅ There's a negative form too:-Wno-error=switchmeans-Wswitchwarnings are not errors, even when-Werroris in effect ๐
Each controllable warning's message includes the option that controls it, and you can plug that option right into -Werror= and -Wno-error= like we just covered ๐ Printing of the option in the warning message can be disabled using the -fno-diagnostics-show-option flag if you want it hidden ๐
Note that specifying -Werror=foo automatically implies -Wfoo. However, -Wno-error=foo does not imply anything. ๐ง
-Wfatal-errorsโ the compiler aborts on the very first error it hits, instead of pushing on and printing more. One and done ๐
You can request many specific warnings with options beginning with -W. For example, -Wimplicit requests warnings on implicit declarations ๐ธ Each of these specific warning options also has a negative form beginning -Wno- to turn the warnings off, like -Wno-implicit. This manual only lists one of the two forms, whichever one is not the default. For further language-specific options, also refer to C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. Additional warnings can be produced by enabling the static analyzer;
Some options, such as -Wall and -Wextra, turn on other options, such as -Wunused, which may turn on further options, such as -Wunused-value. The combined effect of positive and negative forms is that more specific options have priority over less specific ones, independently of their position on the command line. For options of the same specificity, the last one takes effect. Options enabled or disabled via pragmas take effect as if they appeared at the end of the command line. โจ
When an unrecognized warning option is requested (e.g., -Wunknown-warning), GCC emits a diagnostic stating that the option is not recognized. ๐คจ However, if the -Wno- form is used, the behavior is slightly different: no diagnostic is produced for -Wno-unknown-warning unless other diagnostics are being produced. This lets you use new -Wno- options with old compilers, but if something goes wrong, the compiler warns that an unrecognized option is present ๐ฆ
The effectiveness of some warnings depends on optimizations also being enabled. For example, -Wsuggest-final-types is more effective with link-time optimization, and -Wmaybe-uninitialized does not warn at all unless optimization is enabled. โก
-Wpedantic,-pedanticโ issue all the warnings demanded by strict ISO C and ISO C++, reject all programs that use forbidden extensions, and reject some other programs that don't follow ISO C and ISO C++ ๐ For ISO C, it follows the version of the ISO C standard specified by any-stdoption used.
Valid ISO C and ISO C++ programs should compile properly with or without this option, though a rare few require -ansi or a -std option specifying the required version of ISO C. However, without this option, certain GNU extensions and traditional C and C++ features are supported as well. With this option, they are rejected. ๐
โโ๏ธ
-Wpedantic does not cause warning messages for use of the alternate keywords whose names begin and end with __. This alternate format can also be used to disable warnings for non-ISO __intN types, i.e. __intN__. Pedantic warnings are also disabled in the expression that follows "__extension__". However, only system header files should use these escape routes; application programs should avoid them. ๐ซ
Some users try to use -Wpedantic to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all. It only catches the ones for which ISO C requires a diagnostic, plus some others for which diagnostics have been added. ๐ฅฒ
A feature to report any failure to conform to ISO C might be useful in some instances, but it would require considerable additional work and would be quite different from -Wpedantic. We don't have plans to support such a feature in the near future. ๐ซ
Where the standard specified with -std represents a GNU extended dialect of C, such as gnu90 or gnu99, there is a corresponding base standard: the version of ISO C on which the GNU extended dialect is based. Warnings from -Wpedantic are given where they are required by the base standard. (It does not make sense for such warnings to be given only for features not in the specified GNU C dialect, since by definition the GNU dialects of C include all features the compiler supports with the given option, and there would be nothing to warn about.) ๐
-pedantic-errorsโ gives an error whenever the base standard (see-Wpedantic) requires a diagnostic. That includes some cases where there is undefined behavior at compile time, and some other cases that do not prevent compilation of programs that are valid according to the standard. This is not equivalent to-Werror=pedantic, since there are errors enabled by this option and not enabled by the latter, and vice versa. ๐-Wallโ enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros ๐ This 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-parameter=2 (C
and Objective-C only) -Wbool-compare -Wbool-operation -Wc++11-compat
-Wc++14-compat -Wcatch-value (C++ and Objective-C++ only)
-Wchar-subscripts -Wcomment -Wduplicate-decl-specifier (C and
Objective-C only) -Wenum-compare (in C/ObjC; this is on by default
in C++) -Wformat -Wformat-overflow -Wformat-truncation
-Wint-in-bool-context -Wimplicit (C and Objective-C only)
-Wimplicit-int (C and Objective-C only)
-Wimplicit-function-declaration (C and Objective-C only) -Winit-self
(only for C++) -Wlogical-not-parentheses -Wmain (only for C/ObjC and
unless -ffreestanding) -Wmaybe-uninitialized -Wmemset-elt-size
-Wmemset-transposed-args -Wmisleading-indentation (only for C/C++)
-Wmissing-attributes -Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros -Wnarrowing (only for C++) -Wnonnull
-Wnonnull-compare -Wopenmp-simd -Wparentheses -Wpessimizing-move
(only for C++) -Wpointer-sign -Wrange-loop-construct (only for C++)
-Wreorder -Wrestrict -Wreturn-type -Wsequence-point -Wsign-compare
(only in C++) -Wsizeof-array-div -Wsizeof-pointer-div
-Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-overflow=1
-Wswitch -Wtautological-compare -Wtrigraphs -Wuninitialized
-Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value
-Wunused-variable -Wvla-parameter (C and Objective-C only)
-Wvolatile-register-var -Wzero-length-bounds
Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally do not consider questionable, but which you might occasionally wish to check for. Others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra, but many of them must be enabled individually. ๐ต๏ธโโ๏ธ
-Wextraโ enables some extra warning flags that are not enabled by-Wall. (This option used to be called-W. The older name is still supported, but the newer name is more descriptive ๐)
-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++11 to C++17 and in C99 and newer)
-Wunused-parameter (only with -Wunused or -Wall)
-Wunused-but-set-parameter (only with -Wunused or -Wall)
Okay bestie, -Wextra is giving extra ๐
and also flags these sneaky 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 is all about ABI changes. It warns about code that gets affected by them, including code that might not be compatible with the vendor-neutral C++ ABI, plus the psABI for your particular target ๐.
Since G++ now defaults to updating the ABI with each major release, normally -Wabi only warns about C++ ABI compatibility problems if there's a check added later in a release series for an ABI issue found after the initial release. -Wabi warns about more things if an older ABI version is selected with -fabi-version=n.
You can also give -Wabi an explicit version number to warn about C++ ABI compatibility with a particular -fabi-version level. For example, -Wabi=2 warns about changes relative to -fabi-version=2 โจ.
If you give an explicit version number and don't specify -fabi-compat-version, the version number from this option gets used for compatibility aliases. If you don't give a version number with this option but do specify -fabi-compat-version, that version number is used for C++ ABI warnings.
Now the honest tea โ: GCC tried super hard to warn about every case, but there are probably some cases that slip through even though G++ is generating incompatible code ๐ฌ. There may also be cases where warnings pop up even though the generated code is actually compatible.
If you're worried that G++ output might not be binary compatible with code from other compilers, rewrite your code to dodge 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 got fixed in -fabi-version=3 ๐ฉน.
- SIMD vector types declared using
__attribute ((vector_size))were mangled in a non-standard way, which doesn't allow for overloading of functions taking vectors of different sizes ๐.
The mangling changed in -fabi-version=4 ๐.
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration was folded away ๐ซ .
These mangling issues got 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๐คทโโ๏ธ.
The ABI also changed the mangling of template argument packs, const_cast, static_cast, prefix increment/decrement, and a class scope function used as a template argument ๐.
These issues were corrected in -fabi-version=6 โจ.
- Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t๐.
These issues were corrected in -fabi-version=7 ๐ท.
- When mangling a function type 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. This didn't affect the ABI of a function with anullptr_tparameter, since parameters have a minimum alignment ๐ง .
This was fixed in -fabi-version=9, the default for GCC 5.2 ๐.
- Target-specific attributes that affect the identity of a type, like ia32 calling conventions on a function type (stdcall, regparm, etc.), didn't affect the mangled name. That led to name collisions when function pointers were used as template arguments ๐ฅ.
This was fixed in -fabi-version=10, the default for 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 doublemembers are passed in memory as specified in psABI. Before GCC 4.4 this wasn't the case ๐. For example:
union U {
long double ld;
int i;
};
union U is now always passed in memory, no cap ๐ซถ.
๐ -Wchar-subscripts
Warn if an array subscript has type char. This is a super common source of errors, because programmers often forget that this type is signed on some machines ๐. This warning is enabled by -Wall ๐.
๐ -Wno-coverage-mismatch
Warn if feedback profiles don't match when you use the -fprofile-use option. If a source file changes between compiling with -fprofile-generate and with -fprofile-use, the profile feedback files can fail to match the source file, and GCC can't use the profile feedback information ๐ฉ. By default this warning is enabled and is treated as an error.
You can use -Wno-coverage-mismatch to disable the warning, or -Wno-error=coverage-mismatch to disable the error. Disabling the error can lead to poorly optimized code, so it's only useful for very minor changes like bug fixes to an existing code-base ๐งน.
Completely disabling the warning is not recommended ๐ซ.
๐ธ -Wno-cpp
(C, Objective-C, C++, Objective-C++ and Fortran only) Suppress warning messages emitted by #warning directives ๐คซ.
๐ฆ -Wdouble-promotion (C, C++, Objective-C and Objective-C++ only)
Give a warning when a value of type float is implicitly promoted to double ๐. CPUs with a 32-bit single-precision floating-point unit implement float in hardware, but emulate double in software ๐ป. On a machine like that, doing computations with double values is way more expensive because of the overhead of software emulation ๐ค.
It's SO easy to accidentally do computations with double, because floating-point literals are implicitly of type double ๐ซ . For example, in:
float area(float radius)
{
return 3.14159 * radius * radius;
}
the compiler performs the entire computation with double, because the floating-point literal is a double ๐
.
๐ง -Wduplicate-decl-specifier (C and Objective-C only)
Warn if a declaration has a duplicate const, volatile, restrict or _Atomic specifier. This warning is enabled by -Wall ๐.
๐ช -Wformat, -Wformat=n
Check calls to printf and scanf, etc., to make sure the arguments supplied have types that match the format string, and that the conversions in the format string make sense โจ. This covers standard functions, plus others specified by format attributes, in the printf, scanf, strftime and strfmon (an X/Open extension, not in the C standard) families (or other target-specific families) ๐.
Which functions get checked without format attributes specified depends on the standard version you picked. Those checks for functions without the attribute are disabled by -ffreestanding or -fno-builtin ๐ง.
The formats are checked against the format features supported by GNU libc version 2.2. That includes all ISO C90 and C99 features, plus features from the Single Unix Specification and some BSD and GNU extensions ๐. Other library implementations might not support all of these, and GCC doesn't warn about features that go beyond a particular library's limits ๐ซถ.
However, if you use -Wpedantic with -Wformat, you get warnings about format features that aren't in the selected standard version. (This doesn't apply to strfmon formats, since those aren't in any version of the C standard ๐.)
๐ -Wformat=1, -Wformat
-Wformat is equivalent to -Wformat=1, and -Wno-format is equivalent to -Wformat=0 ๐ฅ. Since -Wformat also checks for null format arguments for several functions, it also implies -Wnonnull ๐ท.
Some parts of this level of format checking can be turned off with -Wno-format-contains-nul, -Wno-format-extra-args, and -Wno-format-zero-length ๐. -Wformat is enabled by -Wall ๐.
๐ท -Wformat=2
Enable -Wformat plus additional format checks. Right now it's equivalent to -Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k ๐
.
๐ซง -Wno-format-contains-nul
If -Wformat is specified, don't warn about format strings that contain NUL bytes ๐
โโ๏ธ.
๐ -Wno-format-extra-args
If -Wformat is specified, don't warn about excess arguments to a printf or scanf format function ๐ธ. The C standard says those extra arguments get ignored, so it's chill ๐ซถ.
Where unused arguments sit between used arguments that are specified with $ operand number specifications, warnings still get given as usual. The implementation can't know what type to pass to va_arg to skip the unused arguments ๐ค. However, for scanf formats, this option suppresses the warning if the unused arguments are all pointers, because the Single Unix Specification says those unused arguments are allowed โจ.
๐ฅ -Wformat-overflow, -Wformat-overflow=level
Warn about calls to formatted input/output functions like sprintf and vsprintf that might overflow the destination buffer ๐ฑ. When the exact number of bytes written by a format directive can't be figured out at compile-time, it's estimated using heuristics that depend on the level argument and on optimization ๐ง .
Turning on optimization will usually make the warning more accurate, but it may also result in false positives ๐.
-Wformat-overflow,-Wformat-overflow=1โ okay so level 1 is the chill one ๐ It's switched on by-Wformatand only yells when a call will most likely overflow the buffer ๐ซถ Unknown numeric arguments get treated like1, and strings of unknown length get treated as empty. Numbers that are bounded to a subrange of their type, or strings whose output is capped by a precision or a finite set of string literals, get assumed to take whatever value makes the most bytes of output โจ
The sus one here is the sprintf call ๐ Even with a and b both at zero, the terminating NUL ('\0') the function tacks onto the end still gets written past the buffer ๐ญ
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
Bump the buffer up by a single byte and the warning goes away ๐ but heads up, that might not actually stop the overflow ๐
-Wformat-overflow=2โ level 2 is the drama queen ๐ It warns about calls that might overflow given an argument of sufficient length or magnitude. Unknown numeric arguments get assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments that can't be bounded by the directive's precision, a finite set of string literals they might evaluate to, or the character array they might point to, get assumed to be 1 character long ๐ธ
At level 2 the example call gets flagged again ๐ This time it's because with a equal to a 32-bit INT_MIN, the first %i directive spills some digits past the end of the buffer. To keep the call safe no matter what the two variables hold, the destination buffer has to be at least 34 bytes. GCC even includes that minimum size in an informational note right after the warning ๐
An alternative to just making the buffer bigger is to constrain the range of the formatted values ๐ฆ You can bound the maximum length of string arguments by putting a precision in the format directive. If 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 shrinks the required buffer size. For example, if a and b can be assumed to fit within the precision of the short int type, then either using the %hi directive or casting the argument to short brings the maximum required size down to 24 bytes ๐
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
-Wno-format-zero-lengthโ if-Wformatis on, this tells GCC to chill about zero-length formats ๐ง The C standard says zero-length formats are allowed, so no drama needed.-Wformat-nonliteralโ if-Wformatis on, GCC also warns when the format string isn't a string literal, since it can't be checked that way ๐ The exception is when the format function takes its format arguments as ava_list.-Wformat-securityโ if-Wformatis on, this one also warns about format function calls that could be a security problem ๐ Right now it flagsprintfandscanfcalls where the format string isn't a string literal and there are no format arguments, likeprintf (foo);.
Super important: thatprintf (foo);pattern can be a security hole if the format string came from untrusted input and contains%n. This is currently a subset of what-Wformat-nonliteralcatches, but future versions may add-Wformat-securitywarnings that aren't in-Wformat-nonliteral.
-Wformat-signednessโ if-Wformatis on, this warns when the format string wants an unsigned argument but you pass a signed one, and vice versa ๐-Wformat-truncation,-Wformat-truncation=levelโ this warns about formatted input/output calls likesnprintfandvsnprintfthat might end up truncating their output โ๏ธ When the exact number of bytes a format directive writes can't be figured out at compile time, GCC estimates it using heuristics that depend on the level argument and on optimization. Turning on optimization usually makes the warning more accurate, but it can also cause false positives. Unless noted otherwise, this option uses the same logic as-Wformat-overflow.-Wformat-truncation,-Wformat-truncation=1โ level 1 is conservative ๐ซถ It only warns about calls to bounded functions whose return value is unused and that will most likely result in truncation.-Wformat-truncation=2โ level 2 also warns about calls to bounded functions whose return value is used, if they might truncate given an argument of sufficient length or magnitude ๐ฅ
-Wformat-y2kโ if-Wformatis on, this warns aboutstrftimeformats that might only give you a two-digit year ๐ Y2K vibes, no thank you ๐-Wnonnullโ warns when you pass a null pointer to an argument that thenonnullfunction attribute says must be non-null ๐ซ-Wnonnullis included in-Walland-Wformat, and you can turn it off with-Wno-nonnull.-Wnonnull-compareโ warns when you compare an argument marked with thenonnullfunction attribute against null inside the function ๐ It's included in-Wall, and you can disable it with-Wno-nonnull-compare.-Wnull-dereferenceโ warns if the compiler finds paths that trigger erroneous or undefined behavior because a null pointer gets dereferenced ๐ This only works when-fdelete-null-pointer-checksis active, which optimizations turn on for most targets. How precise the warnings are depends on the optimization options you use.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ warns about uninitialized variables that get initialized with themselves ๐ This option can only be used together with-Wuninitialized.
For example, GCC warns about i being uninitialized in this snippet only when -Winit-self is specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++ ๐
-Wno-implicit-int(C and Objective-C only) โ controls warnings for when a declaration doesn't specify a type ๐ง This warning is on by default in C99 and later dialects of C, and also turned on by-Wall.-Wno-implicit-function-declaration(C and Objective-C only) โ controls warnings for when a function gets used before it's declared ๐ซ This warning is on by default in C99 and later dialects of C, and also turned on by-Wall. It gets upgraded to an error by-pedantic-errors.-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declarationtogether โจ This warning is enabled by-Wall.-Wimplicit-fallthroughโ this is the same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0๐-Wimplicit-fallthrough=nโ warns when a switch case falls through ๐ For example:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
This warning does not go off when the last statement of a case can't fall through, like when there's a return statement or a call to a function declared with the noreturn attribute ๐ -Wimplicit-fallthrough= also takes control flow statements into account, such as ifs, and only warns when it's appropriate. For example:
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a switch case falling through is exactly what you want ๐ฆ For those times GCC provides an attribute, __attribute__ ((fallthrough)), which goes along with a null statement to suppress the warning that would otherwise show up:
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 gives you a standard way to suppress the -Wimplicit-fallthrough warning using [[fallthrough]]; instead of the GNU attribute ๐
In C++11 or C++14 you can use [[gnu::fallthrough]];, which is a GNU extension. Instead of these attributes, you can also add a fallthrough comment to silence the warning ๐ The whole body of the C or C++ style comment has to match the regular expressions listed below. The option argument n specifies what kinds of comments are accepted:
-Wimplicit-fallthrough=0disables the warning altogether ๐-Wimplicit-fallthrough=1matches the".*"regular expression, so any comment counts as a fallthrough comment ๐ฌ-Wimplicit-fallthrough=2case insensitively matches the".*falls?[ \t-]*thr(ough|u).*"regular expression โจ-Wimplicit-fallthrough=3case sensitively matches one of the following regular expressions:
Okay, the =3 list keeps going, bestie ๐
here are the rest of the regexes it'll match:
"-fallthrough"
"@fallthrough@"
"lint -fallthrough[ \t]*"
"[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?"
"[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?"
"[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4 case sensitively matches one of these regexes ๐ฅ:
"-fallthrough"
"@fallthrough@"
"lint -fallthrough[ \t]*"
"[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5 doesn't recognize any comments as fallthrough comments ๐. Only attributes disable the warning โจ.
The comment needs to be followed, after optional whitespace and other comments, by case or default keywords, or by a user label that precedes some case or default label ๐. Like this:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is enabled by -Wextra ๐ง
-Wno-if-not-aligned(C, C++, Objective-C and Objective-C++ only) โ this one controls whether warnings triggered by thewarn_if_not_alignedattribute get issued ๐ซถ. They're on by default โจ.-Wignored-qualifiers(C and C++ only) โ warns if a function's return type has a type qualifier likeconst๐ . In ISO C that qualifier has no effect, since the value a function returns isn't an lvalue ๐. In C++ the warning only pops up for scalar types orvoid๐ธ. ISO C also 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 gets ignored ๐. This is different from-Wattributes๐ฆ, because it fires whenever the compiler decides to drop an attribute.-Wattributesis about the attribute being unknown, used in the wrong place, and so on. This warning is enabled by default ๐.-Wmainโ warns if the type ofmainlooks sus ๐.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 it's enabled 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 ๐.
In the following example, the call to bar is misleadingly indented as if it were guarded by the if conditional ๐:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
With mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up ๐. It defaults to 8 ๐ง.
The warning is not issued for code involving multiline preprocessor logic, such as this ๐ง:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
The warning is also not issued after a #line directive ๐
โโ๏ธ. That typically means autogenerated code, and no assumptions can be made about the layout of the file that the directive references ๐คทโโ๏ธ.
This warning is enabled by -Wall in C and C++ ๐
.
-Wmissing-attributesโ warns when a function declaration is missing one or more attributes that a related function is declared with, and whose absence may adversely affect the correctness or efficiency of the generated code ๐ค. For example, it's issued for alias declarations that use attributes to specify less restrictive requirements than their targets. That typically represents a potential optimization opportunity ๐ธ.
The -Wattribute-alias=2 option is the opposite vibe ๐. It controls warnings issued when the alias is more restrictive than the target, which could lead to incorrect code generation. The attributes considered are alloc_align, alloc_size, cold, const, hot, leaf, malloc, nonnull, noreturn, nothrow, pure, returns_nonnull, and returns_twice ๐.
In C++, the warning is issued 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 deprecated, error, and warning attributes suppress the warning ๐ซถ.
You can use the copy attribute to apply the same set of attributes to a declaration as another declaration has, without explicitly listing them ๐
. It can be applied to declarations of functions, variables, or types โจ.
-Wmissing-attributes is enabled by -Wall ๐.
For example, since the declaration of the primary function template below uses both the malloc and alloc_size attributes, the declaration of the explicit specialization of the template gets diagnosed ๐ญ. It's missing one of the attributes:
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
-Wmissing-bracesโ warns if an aggregate or union initializer is not fully bracketed ๐งธ. In the following example, the initializer 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 and Objective-C++ only) โ warns if a user-supplied include directory doesn't exist ๐.-Wno-missing-profileโ controls warnings when feedback profiles are missing while using the-fprofile-useoption ๐. This one diagnoses cases where a new function or a new file gets added between compiling with-fprofile-generateand with-fprofile-use, without regenerating the profiles ๐ฌ. The profile feedback data files then don't contain any profile feedback information 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, warnings are issued to let you know a profile generation step is due ๐. Ignoring the warning can result in poorly optimized code ๐ฅฒ. -Wno-missing-profile can be used to disable the warning, but that's not recommended, and it should only be done when non-existent profile data is justified ๐
โโ๏ธ.
-Wno-mismatched-deallocโ warns for calls to deallocation functions with pointer arguments returned from allocation functions that the former isn't a suitable deallocator for ๐งน. A pair of functions can be associated as matching allocators and deallocators by using themallocattribute ๐. Unless-fno-builtindisables it, the standard functionscalloc,malloc,realloc, andfree, along with the corresponding forms of C++operator newandoperator delete, are implicitly associated as matching allocators and deallocators ๐ซถ. In the following example,mydeallocis the deallocator for pointers returned frommyalloc๐ง:
void mydealloc (void*);
__attribute__ ((malloc (mydealloc, 1))) void*
myalloc (size_t);
void f (void)
{
void *p = myalloc (32);
// ...use p...
free (p); // warning: not a matching deallocator for myalloc
mydealloc (p); // ok
}
In C++, the related option -Wmismatched-new-delete diagnoses mismatches involving either operator new or operator delete ๐ฆ.
Option -Wmismatched-dealloc is enabled by default ๐.
-Wmultistatement-macrosโ warns about unsafe multiple statement macros that appear to be guarded by a clause likeif,else,for,switch, orwhile, where only the first statement is actually guarded after the macro is expanded ๐ฑ. For example:
#define DOIT x++; y++
if (c)
DOIT;
That 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 ๐, such as when there's an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about ๐ค.
It also warns if a comparison like x<=y<=z appears ๐จ. That's equivalent to (x<=y ? 1 : 0) <= z, which is a different interpretation from ordinary mathematical notation ๐ต.
It also warns for dangerous uses of the GNU extension to ?: with the 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 for some cases of unnecessary parentheses in declarations, which can indicate 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โ warns about code that may have undefined semantics because of violations of the sequence point rules in the C and C++ standards ๐ญ๐ฅ.
okay so the C and C++ standards have this whole rule about the order stuff in an expression gets evaluated ๐ง, and it's all tied to sequence points โจ. These are checkpoints in the program. Everything before one has been evaluated and everything after it hasn't, which makes it a partial ordering between parts of the program ๐. Sequence points happen after a full expression is evaluated (one that isn't part of a larger expression), after the first operand of a &&, ||, ? : or , (comma) operator is evaluated, before a function is called (but after its arguments and the expression that names the called function are evaluated), and in a few other spots too. Outside of what the sequence point rules say, the order in which subexpressions of an expression get evaluated is not specified ๐. These rules only give a partial order, not a total one. So if two functions get called inside one expression with no sequence point between them, the order they run in is not specified. The standards committee did rule that function calls don't overlap though ๐ซถ
It's not specified when, between sequence points, changes to object values actually take effect. Programs whose behavior depends on this have undefined behavior ๐ญ The 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. Not cute, bestie ๐
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 pretty effective at catching this sort of problem in programs ๐ฅ
The C++17 standard is going to define the order of evaluation of operands in more cases ๐. In particular, it requires that the right-hand side of an assignment gets evaluated before the left-hand side, so the examples above are no longer undefined. But this option will still warn about them, to help people avoid writing code that's undefined in C and in earlier revisions of C++ ๐
The standard is worded confusingly, so there's some debate over the precise meaning of the sequence point rules in subtle cases ๐ตโ๐ซ Links to discussions of the problem, including proposed formal definitions, can be found on the GCC readings page, at <http://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). For C only, it warns about areturnstatement with an expression in a function whose return type isvoid, unless the expression type is alsovoid. As a GNU extension, that latter case is accepted without a warning unless-Wpedanticis used. Attempting to use the return value of a non-voidfunction other thanmainthat flows off the end by reaching the closing curly brace that terminates the function is undefined ๐ญ Unlike in C, in C++, flowing off the end of a non-voidfunction other thanmainresults in undefined behavior even when the function's value isn't used. This warning is enabled by default in C++ and by-Wallotherwise. ๐-Wno-shift-count-negativeโ Controls warnings if a shift count is negative. This warning is enabled by default ๐-Wno-shift-count-overflowโ Controls warnings if a shift count is greater than or equal to the bit width of the type. This warning is enabled by default ๐-Wshift-negative-valueโ Warns if you left shift a negative value. This warning is enabled by-Wextrain C99 (and newer) and C++11 to C++17 modes ๐ฆ-Wno-shift-overflow,-Wshift-overflow=nโ These options control warnings about left shift overflows โจ-Wshift-overflow=1โ This is the warning level of-Wshift-overflowand is enabled by default in C99 and C++11 modes (and newer). This level doesn't warn about left-shifting 1 into the sign bit. (However, in C, such an overflow is still rejected in contexts where an integer constant expression is required.) No warning is emitted in C++20 mode (and newer), since signed left shifts always wrap.-Wshift-overflow=2โ This level also warns about left-shifting 1 into the sign bit, unless C++14 mode (or newer) is active ๐ธ
-Wswitchโ Warns whenever 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 trigger warnings when this option is used, even if there's adefaultlabel. This warning is enabled by-Wall๐-Wswitch-defaultโ Warns whenever aswitchstatement doesn't have adefaultcase ๐ง-Wswitch-enumโ Warns whenever aswitchstatement has an index of enumerated type and lacks acasefor one or more of the named codes of that enumeration.caselabels outside the enumeration range also trigger warnings when this option is used. The only difference between-Wswitchand this option is that this one warns about an omitted enumeration code even if there's adefaultlabel ๐-Wno-switch-boolโ Don't warn when aswitchstatement has an index of boolean type and the case values are outside the range of a boolean type. You can suppress this warning by casting the controlling expression to a type other thanbool. For example:
switch ((int) (a == 4))
{
...
}
This warning is enabled by default for C and C++ programs. ๐
-Wno-switch-outside-rangeโ Controls warnings when aswitchcasehas a value that's outside of its respective type range. This warning is enabled by default for C and C++ programs ๐-Wno-switch-unreachableโ Don't warn when 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 doesn't 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 ๐ฅบ-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 warning 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). This warning is enabled by-Wall๐ฅ To suppress it, use theunusedattribute. It's also enabled by-Wunused, which is enabled by-Wall.-Wunused-functionโ Warns whenever a static function is declared but not defined, or a non-inline static function is unused. This warning is enabled by-Wall๐ธ-Wunused-labelโ Warns whenever a label is declared but not used. This warning is enabled by-Wall๐ฆ To suppress it, use theunusedattribute.-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ Warns when a typedef defined locally inside a function isn't used. This warning is 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 or static variable is unused aside from its declaration. This option implies-Wunused-const-variable=1for C, but not for C++. This warning is enabled by-Wall๐ To suppress it, use theunusedattribute.-Wunused-const-variable,-Wunused-const-variable=nโ Warns whenever a constant static variable is unused aside from its declaration.-Wunused-const-variable=1is enabled by-Wunused-variablefor C, but not for C++. In C this declares variable storage, but in C++ it isn't an error, sinceconstvariables take the place of#defines ๐ To suppress this warning, use theunusedattribute.-Wunused-const-variable=1โ This is the warning level that-Wunused-variableenables for C. It only warns about unused staticconstvariables defined in the main compilation unit, not about staticconstvariables declared in any header that's included ๐-Wunused-const-variable=2โ This level also warns about unused constant static variables in headers (excluding system headers). This is the warning level of-Wunused-const-variableand must be explicitly requested, since in C++ this isn't an error and in C it might be harder to clean up all the headers included ๐
-Wunused-valueโ okay bestie, this one yells when a statement works out a result and then just throws it away ๐๏ธ. To shush it, cast the unused expression tovoid๐คซ. That covers an expression-statement or the left-hand side of a comma expression with no side effects. Sox[i,j]gets flagged ๐ฉ, butx[(void)i,j]slides right through โจ. This warning is enabled by-Wall๐ .-Wunusedโ the whole squad of-Wunusedoptions combined ๐
If you want a warning about an unused function parameter, you have to either use -Wextra -Wunused (note that -Wall already implies -Wunused) ๐ซถ, or turn on -Wunused-parameter separately ๐.
-Wuninitializedโ this one warns if you use an object with automatic or allocated storage duration before you've given it a value ๐ญ. In C++, it also warns if a non-static reference or a non-staticconstmember shows up in a class that has no constructors ๐ฆ.
It's also diagnosed when you pass a pointer (or, in C++, a reference) to an uninitialized object into a const-qualified argument of a built-in function that's known to read the object ๐ฅ. (-Wmaybe-uninitialized handles ordinary functions ๐.)
If you want to catch code that uses the uninitialized value of a variable inside its own initializer, use the -Winit-self option ๐ธ.
These warnings show up for individual uninitialized elements of structure, union, or array variables, as well as for variables that are uninitialized as a whole ๐. They do not occur for variables or elements declared volatile ๐ง. Because these warnings depend on optimization, the exact variables or elements that get warnings depend on the precise optimization options and the GCC version you're using ๐.
Also, there may be no warning about a variable that's only used to compute a value that's never used itself, since data flow analysis can delete those computations before the warnings get printed ๐.
-Wno-invalid-memory-modelโ this option controls warnings for calls to__atomicbuiltins,__syncbuiltins, and the C11 atomic generic functions when their memory consistency argument is either invalid for the operation or outside the range of values in thememory_orderenumeration ๐ง . For example, the__atomic_storeand__atomic_store_nbuilt-ins are only defined for the relaxed, release, and sequentially consistent memory orders, so the following code gets diagnosed ๐:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
Heads up: -Winvalid-memory-model is enabled by default โจ.
-Wmaybe-uninitializedโ for an object with automatic or allocated storage duration, this one warns if there's a path from the function entry to a use of the object where it's initialized, but some other paths leave it uninitialized ๐ฌ. The compiler emits the warning if it can't prove those uninitialized paths never run at run time ๐ซฃ.
It also diagnoses passing a pointer (or, in C++, a reference) to an uninitialized object into a const-qualified function argument ๐
. (-Wuninitialized is the one issued for built-in functions known to read the object ๐.) If you annotate the function with the attribute access (none), that tells the compiler the argument isn't used to access the object, and it avoids the warning ๐ซถ.
These warnings are only possible in optimizing compilation, because otherwise GCC doesn't keep track of the state of variables ๐ง. They're made optional because GCC may not be able to tell when the code is correct even though it looks like there's an error ๐คทโโ๏ธ. Here's one example of how that can happen:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know that ๐ฅน. To suppress the warning, provide a default case with assert(0) or similar code ๐ท.
This option also warns when a non-volatile automatic variable might be changed by a call to longjmp ๐. The compiler 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 ๐ฑ). So you may get a warning even when there's no real problem, because longjmp can't actually be called at the place that would cause one ๐.
Some spurious warnings can be avoided if you declare all the functions you use that never return as noreturn ๐งน.
This warning is enabled by -Wall or -Wextra ๐.
-Wunknown-pragmasโ warns when a#pragmadirective shows up that GCC doesn't understand ๐. If you use this command-line option, warnings get issued even for unknown pragmas in system header files ๐. That's not the case when the warnings are only enabled by the-Wallcommand-line option ๐ โโ๏ธ.-Wno-pragmasโ do not warn about misuses of pragmas, like incorrect parameters, invalid syntax, or conflicts between pragmas ๐ธ. See also-Wunknown-pragmas๐.-Wno-prio-ctor-dtorโ do not warn if a priority from0to100is used for a constructor or destructor ๐ฆ. The constructor and destructor attributes let you assign a priority to control their order of execution beforemainis called or after it returns ๐๏ธ. The priority values must be greater than100, because the compiler reserves the priority values0--100for the implementation ๐.-Wstrict-aliasingโ this one is only active when-fstrict-aliasingis active ๐ฏ. It warns about code that might break the strict aliasing rules the compiler uses for optimization ๐งฉ. It doesn't catch every case, but it does try to catch the more common pitfalls ๐. It's included in-Wallโจ, and it's equivalent to-Wstrict-aliasing=3๐.-Wstrict-aliasing=nโ same deal, only active when-fstrict-aliasingis active ๐. It warns about code that might break the strict aliasing rules the compiler uses for optimization. Higher levels mean higher accuracy (fewer false positives), and they also take more effort, kind of like how-Oworks ๐ง .-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3๐.- Level 1 โ most aggressive, quick, and least accurate ๐ค. It's possibly useful when higher levels don't warn but
-fstrict-aliasingstill breaks your 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 the pointer is never dereferenced. It runs in the front end only ๐ฅ๏ธ. - Level 2 โ aggressive, quick, and not too precise ๐โโ๏ธ. It may still have many false positives (though not as many as level 1), and few false negatives (possibly more than level 1) ๐ซค. Unlike level 1, it only warns when an address is taken ๐. It warns about incomplete types ๐. It runs in the front end only ๐ฅ๏ธ.
- Level 3 (default for
-Wstrict-aliasing) โ should have very few false positives and few false negatives ๐. It's slightly slower than levels 1 or 2 when optimization is enabled ๐ข. It takes care of the common pun+dereference pattern in the front end, like*(int*)&some_float๐. If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information ๐ฌ. It only warns when the converted pointer is dereferenced, and it does not warn about incomplete types ๐ .
- Level 1 โ most aggressive, quick, and least accurate ๐ค. It's possibly useful when higher levels don't warn but
-Wstrict-overflowand-Wstrict-overflow=nโ this one is only active when signed overflow is undefined ๐ช๏ธ. It warns about cases where the compiler optimizes based on the assumption that signed overflow never happens ๐ค. It doesn't warn about every case where the code might overflow, only where the compiler actually implements some optimization, so the warning depends on your optimization level ๐๏ธ.
An optimization that assumes signed overflow doesn't occur is perfectly safe if the values involved never actually overflow ๐ซง. That means this warning can easily give a false positive, which is a warning about code that isn't really a problem ๐ . To help you focus on the important stuff, several warning levels are defined ๐ฅ. No warnings are issued for the use of undefined signed overflow when estimating how many iterations a loop requires, in particular when figuring out whether a loop will run at all ๐.
-Wstrict-overflow=1โ warns about cases that are both questionable and easy to avoid ๐ท. For example, the compiler simplifiesx + 1 > xto1๐งฎ. This level is enabled by-Wall, while higher levels are not, so you have to request them explicitly ๐โโ๏ธ.-Wstrict-overflow=2โ also warns about other cases where a comparison gets simplified to a constant ๐ซ. For example:abs (x) >= 0. This can only be simplified when signed integer overflow is undefined, becauseabs (INT_MIN)overflows toINT_MIN, which is less than zero ๐คฏ.-Wstrict-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 cases above ๐ง. For example:(x * 10) / 5is simplified tox * 2๐ญ.-Wstrict-overflow=5โ also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison ๐. For example:x + 2 > yis simplified tox + 1 >= y๐งฉ. This is only reported at the highest warning level, because this simplification applies to many comparisons, so this level gives a very large number of false positives ๐ญ๐ .
-Wstring-compareโ ๐ okay bestie, this one is a whole vibe check. It warns when astrcmporstrncmpequality test is locked to one answer, zero or non-zero, because one argument is longer than the array the other one lives in (or longer than the bound, forstrncmp). Those calls could totally be mistakes ๐ญ. Here's the example, where thestrcmpcall gets flagged 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โ ๐ this one watches string-handling functions likememcpyandstrcpyand yells if they'd overflow the destination buffer. The optional type is one more than the Object Size Checking type used to figure out how big the destination is. It only matters for functions that work on character arrays, not raw memory functions likememcpy, which always use Object Size type-0. It also warns about calls asking for a size bigger than the largest possible object, or for more thanSIZE_MAX / 2bytes. The best results come with optimization turned on, but it can still catch a small set of simple overflows without optimization in GCC built-ins like__builtin_memcpythat match the standard functions. Either way, it only catches a subset of the overflows the matching overflow-checking built-ins can find. Check out this one, wherestrcpycopies at least 5 characters (the string"blue"plus the terminating NUL) into a buffer of size 4 ๐:
enum Color { blue, purple, yellow };
const char* f (enum Color clr)
{
static char buf [4];
const char *str;
switch (clr)
{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
}
return strcpy (buf, str); // warning here
}
-Wstringop-overflow=2 is enabled by default ๐.
-Wstringop-overflow,-Wstringop-overflow=1โ ๐ธ this setting uses type-zero Object Size Checking to figure out destination sizes. It won't warn about writes past the end of subobjects of bigger objects reached through pointers unless the size of the largest surrounding object is known. If the destination could be one of several objects, it's assumed to be the largest one. On Linux, when optimization is on at this level, it warns for the same code as when the_FORTIFY_SOURCEmacro is defined to a non-zero value.-Wstringop-overflow=2โ ๐ฆ this one uses type-one Object Size Checking. It warns about overflows when writing to members of the largest complete objects whose exact size is known. It does not warn about excessive writes to the same members of unknown objects reached through pointers, since those might point to arrays with unknown numbers of elements. This is the default setting ๐.-Wstringop-overflow=3โ ๐ง this one uses type-two Object Size Checking and warns about overflowing the smallest object or data member. It's the most restrictive setting that can still warn about code that's actually safe ๐ญ.-Wstringop-overflow=4โ ๐ฅ this one uses type-three Object Size Checking and warns about overflowing any data members. When the destination could be one of several objects, it uses the size of the largest one to decide whether to warn. Just like-Wstringop-overflow=3, this setting can warn about totally benign code ๐.
-Wno-stringop-overread,-Wstringop-overreadโ ๐ this one warns about string-handling calls likememchrorstrcpythat get determined to read past the end of the source sequence.
-Wstringop-overread is enabled by default ๐.
-Wno-stringop-truncationโ ๐ซถ this option tells GCC to stop warning about bounded string functions likestrncat,strncpy, andstpncpythat might either truncate the copied string or leave the destination unchanged.
In this first example, the strncat call has a bound smaller than the length of the source string. So the copy gets truncated, and the call is diagnosed. To dodge the warning, use bufsize - strlen (buf) - 1) as the bound:
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Here's another one. This strncpy call copies only the characters before the terminating NUL into d, so the NUL never gets appended to the end. Assuming the result of strncpy is always a NUL-terminated string is a super common mistake, so this call is diagnosed. If the result isn't supposed to be NUL-terminated, call memcpy instead to avoid the warning ๐:
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
In this example, the strncpy call uses the size of the destination buffer as its bound. If the source string's length is equal to or greater than that size, the copy won't be NUL-terminated. So this one 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 a character array is meant to hold a sequence of bytes with no terminating NUL, you can annotate it with the attribute nonstring to avoid this warning โจ. But those arrays aren't suitable arguments for functions that expect NUL-terminated strings. To help catch accidental misuse of these arrays, GCC issues warnings unless it can prove the use is safe ๐ฅ.
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]โ ๐ this one warns when adding an attribute might be beneficial. The attributes supported right now are listed below ๐ฆ.-Wsuggest-attribute=pure,-Wsuggest-attribute=const,-Wsuggest-attribute=noreturn,-Wmissing-noreturn,-Wsuggest-attribute=mallocโ ๐ธ this group warns about functions that might be good candidates for the attributespure,const,noreturn, ormalloc. GCC 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 have an infinite loop and doesn't return abnormally by throwing, callingabort, or trapping. This analysis needs the option-fipa-pure-const, which is enabled by default at-Oand higher. Higher optimization levels make the analysis more accurate ๐ง .-Wsuggest-attribute=format,-Wmissing-format-attributeโ ๐ this warns about function pointers that might be candidates forformatattributes. These are only possible candidates, not guaranteed ones. GCC guesses that function pointers withformatattributes used in assignment, initialization, parameter passing, or return statements should also have a matchingformatattribute in the resulting type. So the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function should have aformatattribute too, 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 that a format attribute might fit any function that calls something like vprintf or vscanf, but that isn't always true. Some functions that really should have format attributes might not get detected ๐.
-Wsuggest-attribute=coldโ ๐ง this warns about functions that might be candidates for thecoldattribute. It's based on static detection and 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-zeroโ ๐ผ this 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. The behavior of these functions with a zero size differs between implementations (andrealloc's version of this has been deprecated), so relying on it can cause subtle portability bugs. Avoid it ๐ซ.-Walloc-size-larger-than=byte-sizeโ ๐ this warns about calls to functions decorated with the attributealloc_sizethat try to allocate objects bigger than the number of bytes you specify. It also warns when the size computation, done in an integer type with infinite precision, would go past the value ofPTRDIFF_MAXon the target.-Walloc-size-larger-than=PTRDIFF_MAXis enabled by default. You can disable warnings from this option either by specifying a byte-size ofSIZE_MAXor more, or with-Wno-alloc-size-larger-than๐.-Wno-alloc-size-larger-thanโ okay bestie, this one silences the-Walloc-size-larger-than=warnings ๐ It works the same as-Walloc-size-larger-than=SIZE_MAXor anything bigger, so basically you're saying "I'm not worried about huge sizes" ๐-Wallocaโ this one warns on every single use ofallocain your source. No exceptions, no vibe check, just warnings ๐ซ-Walloca-larger-than=byte-sizeโ ngl this is the big one ๐ฅ It warns on calls toallocawhere the integer argument is either zero, or isn't bounded by some controlling check that keeps it at most byte-size. It also warns when the bound is unknown. Heads up: non-integer arguments count as unbounded, even if they look like they're in range ๐
Here's a bounded case that's totally fine:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
Passing -Walloca-larger-than=1000 won't warn here, because the alloca call is known to be at most 1000 bytes. But if you pass -Walloca-larger-than=500, the compiler will warn ๐
Unbounded uses are the ones with no controlling predicate limiting the integer argument. For example:
void func ()
{
void *p = alloca (n);
f (p);
}
With -Walloca-larger-than=500, this one triggers a warning too, but this time it's because there's no bounds checking at all ๐ญ
Even code that looks correct with signed integers can warn:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
Here n could be negative, which means a larger-than-expected argument gets implicitly cast into the alloca call. Wild, right? ๐ช๏ธ
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 really effective when -ftree-vrp is active (the default for -O2 and above) โจ
See also -Wvla-larger-than=byte-size.
-Wno-alloca-larger-thanโ turns off the-Walloca-larger-than=warnings. It's the same as-Walloca-larger-than=SIZE_MAXor larger ๐ธ-Warith-conversionโ bestie wants you to know this one is extra. It warns about implicit conversions from arithmetic operations, even when converting the operands to the same type can't change their values ๐ง It affects the 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โ only active when-ftree-vrpis active (default for-O2and above). It warns about subscripts to arrays that are always out of bounds ๐ This warning is enabled by-Wall.-Warray-bounds=1โ the warning level of-Warray-bounds, enabled by-Wall. Higher levels aren't enabled by it and have to be explicitly requested.-Warray-bounds=2โ this level also warns about out-of-bounds access for arrays at the end of a struct and for arrays accessed through pointers. It can give a bigger pile of false positives, so it's deactivated by default ๐
-Warray-parameter,-Warray-parameter=nโ warns about redeclarations of functions that have array or pointer arguments in inconsistent kinds or forms. It also turns on detection of out-of-bounds accesses to those parameters through warnings like-Warray-bounds๐
If the first function declaration uses the array form, the bound in the array is assumed to be the minimum number of elements expected in calls to the function, and also the maximum number of elements it accesses. Giving too-small arguments, or accessing more than the maximum, may get diagnosed by warnings like -Warray-bounds. At level 1, the warning catches inconsistencies involving array parameters declared with the T[static N] form.
This triggers for the redeclarations below, because the first one lets an array of any size get 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 for redeclarations involving any other inconsistency in array or pointer argument forms that denote array sizes. Pointers and arrays of unspecified bound are considered equivalent and 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 thealiasand similar attributes whose target is incompatible with the type of the alias ๐ฆ-Wattribute-alias=1โ this is the default warning level. It diagnoses incompatibilities between the type of the alias declaration and the type of its target. Those are usually signs 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 mismatches can lead to incorrect code generation. Other times they're harmless and could be fixed by just adding the missing attribute to the target. For comparison,-Wmissing-attributesis the one that handles the opposite case, where the alias is less restrictive than the target.
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 the same as -Wattribute-alias=1, which is the default. You can turn these warnings off with either -Wno-attribute-alias or -Wattribute-alias=0 ๐
โโ๏ธ
-Wbool-compareโ warns about a boolean expression being compared with an integer value that isn'ttrueorfalse. 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 example, bitwise negation of a boolean is very likely a bug ๐ For C, this also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing one is invalid in C++17, and deprecated otherwise.)
This warning is enabled by -Wall.
-Wduplicated-branchesโ warns when an if-else has identical branches. It catches cases like this:
if (p != NULL)
return 0;
else
return 0;
It doesn't warn when both branches contain just a null statement. This warning also covers conditional operators:
int i = x ? *p : *p;
-Wduplicated-condโ warns about duplicated conditions in an if-else-if chain. For example, it'll warn on this:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ warns when__builtin_frame_addressor__builtin_return_addressis called with an argument greater than 0. Those calls might return indeterminate values or crash the program ๐ This warning is included in-Wall.-Wno-discarded-qualifiers(C and Objective-C only) โ stops the compiler from warning when type qualifiers on pointers get discarded. Normally it warns if aconst char *variable is passed to a function that takes achar *parameter. This option suppresses that warning ๐ซถ-Wno-discarded-array-qualifiers(C and Objective-C only) โ same idea, but for qualifiers on arrays that are pointer targets. Normally it warns if aconst int (*)[]variable is passed to a function that takes anint (*)[]parameter. This option suppresses that warning too ๐ธ-Wno-incompatible-pointer-types(C and Objective-C only) โ no warning when there's a conversion between pointers with incompatible types. This is for the cases that-Wno-pointer-signdoesn't cover, since that one handles pointer argument passing or assignment with different signedness.-Wno-int-conversion(C and Objective-C only) โ no warnings about incompatible integer-to-pointer and pointer-to-integer conversions. This is only about implicit conversions. For explicit ones, 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
Accesses to interior zero-length arrays are undefined, so please don't ๐ โโ๏ธ
For example, the first two stores in function bad are diagnosed, because the array elements overlap the subsequent members b and c. The third store gets diagnosed by -Warray-bounds, because it's past the bounds of the enclosing object:
struct X { int a[0]; int b, c; };
struct X x;
void bad (void)
{
x.a[0] = 0; // -Wzero-length-bounds
x.a[1] = 1; // -Wzero-length-bounds
x.a[2] = 2; // -Warray-bounds
}
Okay so -Wzero-length-bounds is enabled by -Warray-bounds ๐ it's giving layered protection, bestie ๐
-Wno-div-by-zeroโ Bestie, this one tells GCC to chill and stop warning about compile-time integer division by zero ๐ โโ๏ธ Floating-point division by zero doesn't get flagged either, because it can be a legit way to get infinities and NaNs โจ no cap, that's a whole vibe.-Wsystem-headersโ This makes GCC print warnings for stuff found in system header files ๐ Normally those warnings are muted, because they usually aren't real problems and would just make the output harder to read ๐ฅฑ With this flag on, GCC treats system header warnings like they came from your own code ๐ซถ
Heads up though: using -Wall together with this option does not warn about unknown pragmas in system headers ๐ญ For that tea, you also need -Wunknown-pragmas.
-Wtautological-compareโ Warns if a self-comparison always evaluates to true or false ๐ This catches sneaky mistakes like:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always come out true or false, for example:
if ((a & 16) == 10) { ... }
That one will always be false ๐ This warning is enabled by -Wall ๐
-Wtrampolinesโ Warns about trampolines generated for pointers to nested functions โจ A trampoline is a tiny bit of data or code that gets made at run time on the stack when the address of a nested function is taken, and it's used to call that nested function indirectly ๐ง On some targets it's just data, so no special treatment is needed. But on most targets it's code, which means the stack has to be made executable for the program to work properly ๐ฌ very sus, be careful.-Wfloat-equalโ Warns if floating-point values are used in equality comparisons ๐ฆ
The thinking behind this is that sometimes it's convenient to treat floating-point values as approximations of infinitely precise real numbers ๐ธ If you're doing that, you need to figure out (by analyzing the code, or some other way) the maximum or likely maximum error the computation introduces, and allow for it when you compare things (and when producing output, but that's a different problem ๐). Instead of testing for equality, you should check whether the two values have ranges that overlap, which is done with the relational operators. So equality comparisons are probably mistaken ๐
-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 about problematic constructs you should avoid ๐ซ Here's the full list of things it's looking out for:- Macro parameters that show up inside string literals in the macro body. Traditional C does macro replacement inside string literals, but ISO C doesn't ๐ โโ๏ธ
- 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 hiding directives like#pragmathat traditional C doesn't understand by indenting them. Some traditional implementations don't recognize#elif, so this option suggests avoiding it altogether ๐ง - A function-like macro that appears without arguments.
- The unary plus operator.
- The
Uinteger constant suffix, or theForLfloating-point constant suffixes. (Traditional C does support theLsuffix on integer constants.) These suffixes show up in macros defined in the system headers of most modern systems, like the_MIN/_MAXmacros in"<limits.h>". Using those macros in user code might normally cause spurious warnings, but GCC's integrated preprocessor has enough context to avoid warning in these cases ๐ฅน - A function declared external in one block and then used after the end of that block.
- A
switchstatement with an operand of typelong. - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this construct ๐ซ - The ISO type of an integer constant has a different width or signedness from its traditional type. This warning is only issued if the base of the constant is ten. Hexadecimal and octal values, which usually represent bit patterns, aren't warned about ๐ข
- ISO string concatenation 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 is skipped. This assumes that a zero initializer in user code is conditioned on something like
"__STDC__"to avoid missing-initializer warnings, and relies on default initialization to zero in the traditional C case ๐ - Conversions by prototypes between fixed-point and floating-point values, and vice versa. Missing these prototypes when compiling with traditional C causes serious problems ๐ฑ This is a subset of the possible conversion warnings. For the full set, use
-Wtraditional-conversion. - Use of ISO C style function definitions. This warning is intentionally not 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,
"PARAMS"and"VPARAMS"๐ It's also bypassed for nested functions, because that feature is already a GCC extension and isn't relevant to traditional C compatibility.
-Wtraditional-conversion(C and Objective-C only) โ Warns if a prototype causes a type conversion that's different from what would happen to the same argument without a prototype ๐ This includes conversions of fixed-point to floating-point and vice versa, plus conversions that change the width or signedness of a fixed-point argument, except when it matches the default promotion.-Wdeclaration-after-statement(C and Objective-C only) โ Warns when a declaration is found after a statement in a block ๐ This construct comes from C++ and was introduced with ISO C99. GCC allows it by default, but it's not 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. That means-Wno-shadow=localand-Wno-shadow=compatible-localget ignored when-Wshadowis used. Same as-Wshadow=globalโจ-Wno-shadow-ivar(Objective-C only) โ Don't warn when a local variable shadows an instance variable in an Objective-C method ๐ โโ๏ธ-Wshadow=globalโ Warns for any shadowing. Same as-Wshadow๐-Wshadow=localโ Warns when a local variable shadows another local variable or parameter ๐ซถ-Wshadow=compatible-localโ Warns when a local variable shadows another local variable or parameter whose type is compatible with the shadowing variable's type. In C++, type compatibility here means the type of the shadowing variable can be converted to the type of the shadowed variable ๐ This flag exists because when a local variable shadows another one of an 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, turning on only -Wshadow=compatible-local won't emit a warning ๐ง Because the types are incompatible, if a programmer accidentally uses one in place of the other, type checking is expected to catch it and emit an error or warning. Using this flag instead of -Wshadow=local can reduce the number of warnings triggered by intentional shadowing ๐ธ It also means that shadowing "const char *i" by "char *i" does not emit a warning.
This warning is also enabled by -Wshadow=local โจ
-Wlarger-than=byte-sizeโ Warns whenever an object is defined whose size is bigger thanbyte-size๐-Wlarger-than=PTRDIFF_MAXis enabled by default. You can turn these warnings off either by specifying abyte-sizeofSIZE_MAXor more, or by using-Wno-larger-than๐ฆ
Also it warns for calls to bounded functions like "memchr" or "strnlen" that specify a bound greater than the largest possible object, which is PTRDIFF_MAX bytes by default ๐ฅบ These warnings can only be disabled by -Wno-larger-than.
-Wno-larger-thanโ Disables-Wlarger-than=warnings ๐ This is equivalent to-Wlarger-than=SIZE_MAXor larger ๐-Wframe-larger-than=byte-sizeโ okay so this one warns you if a function's frame gets bigger than byte-size ๐ฆ. Heads up, the math used to figure out the frame size is approximate and not conservative ๐, so the real requirements might be a bit bigger than byte-size even when you get no warning. Also, space fromalloca, variable-length arrays, or related constructs isn't counted when the compiler decides whether to warn ๐.-Wframe-larger-than=PTRDIFF_MAXis on by default โจ. You can turn these warnings off by giving a byte-size ofSIZE_MAXor more, or by using-Wno-frame-larger-than๐ซถ-Wno-frame-larger-thanโ bye bye to all-Wframe-larger-than=warnings ๐ โโ๏ธ. It's the same as-Wframe-larger-than=SIZE_MAXor bigger ๐-Wno-free-nonheap-objectโ hmm, this is the one that yells when you try to free something that either never lived on the heap, or came from a pointer that wasn't handed back by the matching allocation function earlier ๐ญ. Like,stpcpygives you a pointer to the terminating nul character instead of the start of the object, so thefreecall below gets flagged ๐ฉ
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wfree-nonheap-object is on by default ๐ธ
-Wstack-usage=byte-sizeโ warns if a function's stack usage might go over byte-size ๐. This math is conservative, soalloca, variable-length arrays, and related constructs do get counted here ๐ง
The message matches what -fstack-usage prints, and it comes in three flavors ๐:
- If the stack usage is fully static but goes over the limit, you'll see:
warning: stack usage is 1120 bytes
- If the stack usage is (partly) dynamic but bounded, you'll see:
warning: stack usage might be 1648 bytes
- If the stack usage is (partly) dynamic and not bounded, you'll see:
warning: stack usage might be unbounded
-Wstack-usage=PTRDIFF_MAX is on by default ๐ฆ You can disable these warnings by giving a byte-size of SIZE_MAX or more, or by using -Wno-stack-usage ๐ซถ
-Wno-stack-usageโ the "shh, no more stack warnings" option ๐คซ It's the same as-Wstack-usage=SIZE_MAXor bigger ๐-Wunsafe-loop-optimizationsโ warns if a loop can't be optimized because the compiler can't assume anything about the bounds of the loop indices ๐. With-funsafe-loop-optimizations, it warns whenever the compiler does make those assumptions ๐
-Wno-pedantic-ms-format(MinGW targets only) โ when you use it together with-Wformatand-pedanticwithout GNU extensions, this turns off the warnings about the non-ISOprintf/scanfformat width specifiersI32,I64, andIon Windows targets ๐ช. Those depend on the MS runtime, so they're kinda the Windows-only drama ๐-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 sovoid *pointers and pointers to functions are easier to do math with ๐. In C++, it also warns when an arithmetic operation involvesNULLโ ๏ธ. This one is also turned on by-Wpedanticโญ-Wno-pointer-compareโ don't warn if a pointer is compared with a zero character constant ๐. This 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 features ThreadSanitizer doesn't support ๐งต. It doesn't supportstd::atomic_thread_fence, and it can report false positives, so be careful bestie ๐ฌ
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, but not for constant expressions ๐. For example, it'll warn if an unsigned variable gets compared against zero with<or>=๐ This warning is also turned on by-Wextra๐ฅ-Wabsolute-value(C and Objective-C only) โ warns when you call standard functions that compute an absolute value, but there's a more appropriate standard function available ๐ง. For example, callingabs(3.14)triggers it, because the right function for a double isfabs๐. It also warns when the argument to one of these calls has an unsigned type. You can shut it up with an explicit type cast, and it's also turned on by-Wextra๐-Wcomment,-Wcommentsโ warns whenever a comment-start sequence/*shows up inside a/* comment, or whenever a backslash-newline shows up in a//comment ๐ฌ. This warning is turned on by-Wall๐ธ-Wtrigraphsโ warns if any trigraphs show up that might change what the program means ๐. Trigraphs inside comments don't get warned about, except the ones that would form escaped newlines ๐ง
This option is implied by -Wall. If you don't pass -Wall, this option is still on unless trigraphs are enabled ๐. If you want trigraph conversion without the warnings, but still want the other -Wall warnings, use:
-trigraphs -Wall -Wno-trigraphs
-Wundefโ warns if an undefined identifier gets evaluated in an#ifdirective ๐ต๏ธโโ๏ธ. Those identifiers get replaced with zero 0๏ธโฃ-Wexpansion-to-definedโ warns wheneverdefinedshows up in the expansion of a macro, including when the macro is expanded by an#ifdirective ๐ โโ๏ธ. That usage isn't portable ๐ This warning is also turned on by-Wpedanticand-Wextra๐-Wunused-macrosโ warns about macros defined in the main file that never get used ๐๏ธ. A macro counts as used if it'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 warned about ๐โโ๏ธ
Note: if a macro is actually used, but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐ญ To dodge the warning in that case, you might improve the scope of the macro's definition, for example by moving it into the first skipped block ๐งฉ Or you could provide a dummy use with something like:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ don't warn when an#elseor an#endifis followed by text ๐ This happens sometimes in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO are supposed to be in comments ๐ This warning is on by default ๐
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a type that doesn't match ๐ญ. 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 are in ISO C99 but not in ISO C90 ๐ฐ๏ธ. Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on ๐งธ This option doesn't care what standards mode you're in ๐ Warnings are turned off in the expression that follows__extension__๐คซ-Wc99-c11-compat(C and Objective-C only) โ warns about features that are in ISO C11 but not in ISO C99 ๐ง. Like anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on ๐ฆ This option is also independent of the standards mode ๐ Warnings are turned off in the expression that follows__extension__๐ซ-Wc11-c2x-compat(C and Objective-C only) โ warns about features that are in ISO C2X but not in ISO C11 ๐ฎ. Like omitting the string in_Static_assert, using[[]]syntax for attributes, using decimal floating-point types, and so on ๐งฎ This option doesn't care about the standards mode either ๐ Warnings are turned off in the expression that follows__extension__๐ค-Wc++-compat(C and Objective-C only) โ warns about ISO C constructs that are outside the common subset of ISO C and ISO C++ ๐งฉ. For example, requesting an implicit conversion fromvoid *to a pointer to a non-voidtype ๐-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning is different between ISO C++ 1998 and ISO C++ 2011 ๐. For example, identifiers that are fine in ISO C++ 1998 but are keywords in ISO C++ 2011 ๐ This warning turns on-Wnarrowingand is enabled by-Wall๐ซถ-Wc++14-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning differs 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 differs 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 differs between ISO C++ 2017 and ISO C++ 2020 ๐ฆ This warning is enabled by-Wall๐-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 *gets cast to an ordinarychar *๐ โโ๏ธ
It also warns when you make a cast that adds 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 so the required alignment of the target goes up ๐. For example, it warns if achar *gets cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries ๐งฑ-Wcast-align=strictโ okay bestie, this one is all about pointers getting cast into a stricter alignment ๐ง. It warns whenever a pointer is cast so that the target's required alignment goes up. For example, it warns if achar *gets cast to anint *โจ regardless of the target machine.-Wcast-function-typeโ this one checks function pointer casts ๐ง. It warns when a function pointer gets cast into an incompatible function pointer ๐ . For functions with a variable argument list, only the types of the initial arguments you actually provide get considered. Any pointer parameter is happy to match any other pointer type ๐, and harmless integer differences get ignored, likeintvs.longon ILP32 targets. Type qualifiers get ignored too. The function typevoid (*) (void)is the VIP ๐ of this warning, because it matches everything, so you can use it to shut the warning up. For casts involving pointer-to-member types, it warns whenever the cast changes the pointer-to-member type. This warning is turned on by-Wextra.-Wwrite-stringsโ when you're compiling C, string constants get the typeconst char[length], so copying one's address into a non-constchar *pointer gives you a warning ๐. These warnings 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 they're just a nuisance ๐, which is exactly why-Walldoesn't ask for them.
When compiling C++, it warns about the deprecated conversion from string literals to char *. This warning is enabled by default for C++ programs.
-Wclobberedโ this one warns about variables that might get changed bylongjmporvfork๐. It's also turned on by-Wextra.-Wconversionโ this warns about implicit conversions that might alter a value ๐ฅ. That includes conversions between real and integer, likeabs (x)whenxisdouble. It also covers conversions between signed and unsigned, likeunsigned ui = -1, and conversions to smaller types, likesqrtf (M_PI). It won't bother you about explicit casts likeabs ((int) x)andui = (unsigned) -1, or about conversions that don't change the value, likeabs (2.0). If the signed/unsigned warnings are too much, you can turn them off with-Wno-sign-conversion.
For C++, it also warns about confusing overload resolution for user-defined conversions, and about conversions that never use a type conversion operator: conversions to void, the same type, a base class or a reference to them. Signed/unsigned integer conversion warnings are disabled by default in C++ unless you explicitly enable -Wsign-conversion ๐
.
Warnings about conversion from arithmetic on a small type back to that type are only given with -Warith-conversion.
-Wdangling-elseโ this is for constructions where it's unclear whichifstatement anelsebranch belongs to ๐. Here's an example of such a case:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C/C++, every else branch belongs to the innermost possible if statement, which in this example is if (b). That's often not what the programmer expected, as the indentation in the example above shows. When there's potential for this confusion, GCC issues a warning if you pass this flag. To get rid of the warning, add explicit braces around the innermost if statement, so there's no way the else can belong to the enclosing if. The resulting code looks like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses.
-Wdate-timeโ this warns when the macros__TIME__,__DATE__or__TIMESTAMP__show up โฐ. They might stop your compilations from being bit-wise-identical and reproducible, so keep an eye on them.-Wempty-bodyโ warns if an empty body shows up in anif,elseordo whilestatement ๐ซฅ. It's also turned on by-Wextra.-Wno-endif-labelsโ stops GCC from complaining about stray tokens after#elseand#endif๐ซถ.-Wenum-compareโ warns about a comparison between values of different enumerated types ๐ฆ. In C++, enumerated type mismatches in conditional expressions get diagnosed too, and this warning is on by default there. In C, it's enabled by-Wall.-Wenum-conversionโ warns when a value of enumerated type gets implicitly converted to a different enumerated type ๐ธ. In C, this warning is enabled by-Wextra.-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 been initialized ๐ง. It only warns about variables that get initialized when they're declared. This warning is only supported for C and Objective-C. In C++, this sort of branch is an error anyway, so no need to worry there.
-Wjump-misses-init is included in -Wc++-compat. You can disable it with the -Wno-jump-misses-init option.
-Wsign-compareโ warns when a comparison between signed and unsigned values could give an incorrect result because the signed value gets converted to unsigned โ๏ธ. In C++, this is also enabled by-Wall. In C, it's also 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 the warning. 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 conversions from real to integer, and from higher precision real to lower precision real values. This option is also enabled by-Wconversion.-Wno-scalar-storage-orderโ stops the warnings 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 not what you meant. This warning catches stuff like this:
int fn ()
{
int arr[10];
return sizeof (arr) / sizeof (short);
}
This warning is enabled by -Wall.
-Wsizeof-pointer-divโ warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size ๐. That's the usual way to compute an array size, but it won't work out correctly with pointers. For example, it warns 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 passed to certain string and memory built-in functions when the argument usessizeof๐ง . It triggers, for example, formemset (ptr, 0, sizeof (ptr));ifptris a pointer and not an array. It'll even suggest a possible fix. It also warns about stuff likememcpy (&foo, ptr, sizeof (&foo));.
-Wsizeof-pointer-memaccess also warns about calls to bounded string copy functions like strncat or strncpy that use a sizeof expression of the source array as the bound. In the following function, the call to strncat uses the size of the source string as the bound. That's almost certainly a mistake, so the call gets diagnosed ๐.
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall.
-Wno-sizeof-array-argumentโ stops the warning when thesizeofoperator gets applied to a parameter 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 ๐งบ. It triggers when the first argument references an array, and the third argument is a number equal to the number of elements but not equal to the array's size in memory. That means you probably forgot to multiply by the element size. This warning is enabled by-Wall.-Wmemset-transposed-argsโ warns about suspicious calls to thememsetbuilt-in function where the second argument is not zero and the third argument is zero ๐. For example, the callmemset (buf, sizeof buf, 0)gets diagnosed, becausememset (buf, 0, sizeof buf)was what you meant. The diagnostic is only emitted if the third argument is a literal zero. If it's an expression that folds to zero, or a cast of zero to some type, it's far less likely that the arguments got mistakenly transposed, so no warning is emitted. This warning is enabled by-Wall.-Waddressโ warns about suspicious uses of memory addresses ๐. These include using the address of a function in a conditional expression, likevoid func(void); if (func), and comparing against the memory address of a string literal, likeif (x == "abc"). These usually point to a programmer error. The address of a function always evaluates to true, so using it in a conditional usually means you forgot the parentheses in a function call. Comparisons against string literals have unspecified behavior and aren't portable in C, so they usually mean you meant to usestrcmp. This warning is enabled by-Wall.-Wno-address-of-packed-memberโ stops the warning when the address of a packed member of a struct or union is taken, which usually results in an unaligned pointer value ๐ฆ. This is enabled by default.-Wlogical-opโ warns about suspicious uses of logical operators in expressions ๐ง. That includes using logical operators in contexts where a bit-wise operator is likely expected. It also warns when the operands of a logical operator are the same:
extern int a;
if (a < 0 && a < 0) { ... }
Okay that's the bestie-level mistake ๐ comparing the same thing twice, and the compiler is literally begging you to double check.
-Wlogical-not-parenthesesโ okay so this one screams when you slap a!on the left side of a comparison ๐ It doesn't scream if the right side is a boolean expression. The whole point is to catch sus code like this:
int a;
...
if (!a > 1) { ... }
If you want it to chill, wrap the LHS in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall โจ
-Waggregate-returnโ warns if any functions that return structures or unions get defined or called ๐ (In languages where you can return an array, this also gets a warning too, ngl.)-Wno-aggressive-loop-optimizationsโ warns if you're in a loop with a constant number of iterations and the compiler spots 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, function attributes slapped on variables, etc. ๐ฆ This does NOT stop errors for using supported attributes incorrectly, so don't get it twisted.-Wno-builtin-declaration-mismatchโ warns if a built-in function gets declared with an incompatible signature or as a non-function, or when a built-in function declared with a type that has no prototype gets called with args whose promoted types don't match what the function expects ๐ธ With-Wextra, it also warns when a built-in function that takes arguments is declared without a prototype. The-Wbuiltin-declaration-mismatchwarning is on by default. To dodge it, include the right header so the prototypes of built-in functions are in scope ๐ซถ
Here's the vibe check example. The call to memset gets flagged because the function wants a size_t but 32 is an int. With -Wextra, the declaration gets flagged too ๐ญ
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ don't warn if certain built-in macros get redefined ๐ This quiets warnings for redefining__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__.-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 gets a free pass with no warning if it's preceded by a declaration that does specify the argument types.)-Wold-style-declaration(C and Objective-C only) โ warns about obsolescent usages in a declaration, according to the C Standard ๐ง For example, it warns if storage-class specifiers likestaticaren't the first things in a declaration. This one is also enabled by-Wextra.-Wold-style-definition(C and Objective-C only) โ warns if an old-style function definition is used โญ It warns even if there's a previous prototype. A definition using()isn't considered old-style in C2X mode, since it's equivalent to(void)there, 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, like this:
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 shows up 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 there provide prototypes, and a non-matching declaration declares an overload instead of conflicting with an earlier one. For missing declarations in C++, use-Wmissing-declarationsinstead.-Wmissing-declarationsโ warns if a global function is defined without a previous declaration ๐ฅ It does this 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 get issued for functions with previous non-prototype declarations, so use-Wmissing-prototypesfor those. In C++, no warnings get issued for function templates, inline functions, or functions in anonymous namespaces.-Wmissing-field-initializersโ warns if a structure's initializer has some fields missing ๐ฆ In this example,x.his implicitly zero, so you get the warning:
struct s { int f, g, h; };
struct s x = { 3, 4 };
This option does NOT warn about designated initializers, so this version is totally fine:
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++, it doesn't warn about the empty { } initializer:
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-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 they shouldn't be used in portable code.-Wnormalized=[none|id|nfc|nfkc]โ okay this one is a whole saga ๐ธ In ISO C and ISO C++, two identifiers are different if they're different sequences of characters. BUT sometimes, when characters outside basic ASCII are used, you can have two different character sequences that look exactly the same. To avoid that confusion, the ISO 10646 standard sets normalization rules that turn lookalike sequences into the same sequence. GCC can warn you if your identifiers aren't normalized, and this option controls that warning.
There are four levels of warning. The default is -Wnormalized=nfc, which warns about any identifier that isn't in the ISO 10646 "C" normalized form, NFC. NFC is the recommended form for most uses, and it's equivalent to -Wnormalized.
Here's the tea โ Some characters allowed in identifiers by ISO C and ISO C++ turn into characters that AREN'T allowed in identifiers once they're NFC. So there's no way to use those symbols in portable ISO C or C++ AND have all your identifiers in NFC. -Wnormalized=id suppresses the warning for those characters. The hope is that future versions of the standards will fix this, which is why it isn't the default.
You can switch the warning off for all characters with -Wnormalized=none or -Wno-normalized. Only do this if you're using some other normalization scheme (like "D"), because otherwise you can easily create bugs that are literally impossible to see ๐ญ
Some characters in ISO 10646 have distinct meanings but look identical in some fonts or display methods, especially once formatting has been applied. For instance, "\u207F", "SUPERSCRIPT LATIN SMALL LETTER N", displays just like a regular "n" that's been placed in a superscript. ISO 10646 defines the NFKC normalization scheme to convert all of these into a standard form too, and GCC warns if your code isn't in NFKC when you use -Wnormalized=nfkc. This is comparable to warning about every identifier that contains the letter O, since it might be confused with the digit 0. So it isn't the default, but it can be a useful local coding convention if your programming environment can't be fixed to display these characters distinctly ๐ง
-Wno-attribute-warningโ don't warn about usage of functions declared with the "warning" attribute ๐ This warning is enabled by default. Use-Wno-attribute-warningto disable the warning, or-Wno-error=attribute-warningto disable the error when compiling with the-Werrorflag.-Wno-deprecatedโ don't warn about usage of deprecated features ๐ฆ-Wno-deprecated-declarationsโ don't warn about uses of functions, variables, and types marked as deprecated with the "deprecated" attribute ๐-Wno-overflowโ don't warn about compile-time overflow in constant expressions โจ-Wno-odrโ warns about One Definition Rule violations during link-time optimization ๐ This one is enabled by default.-Wopenmp-simdโ warns if the vectorizer cost model overrides the OpenMP simd directive that the user set ๐ฅ The-fsimd-cost-model=unlimitedoption can be used to relax the cost model.-Woverride-init(C and Objective-C only) โ warns if an initialized field without side effects gets overridden when using designated initializers ๐ซถ This warning is included in-Wextra. To get the other-Wextrawarnings without this one, use-Wextra -Wno-override-init.-Wno-override-init-side-effects(C and Objective-C only) โ don't warn if an initialized field with side effects gets overridden when using designated initializers ๐ This warning is enabled by default.-Wpackedโ warns if a structure is given the packed attribute, but the packed attribute has no effect on the layout or size of the structure ๐ Such structures may end up misaligned for little benefit. For instance, in this code, the variablef.xinstruct baris misaligned even thoughstruct bardoesn't itself have the packed attribute:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wnopacked-bitfield-compatโ okay so the 4.1, 4.2 and 4.3 series of GCC just ignored thepackedattribute oncharbit-fields ๐. That got fixed in GCC 4.4, but the fix can shift your struct layout, so GCC tells you when a field's offset has changed. In this struct, the 4-bit gap betweenaandbis gone now โจ:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default ๐ธ. If you want it gone, use -Wno-packed-bitfield-compat ๐ซถ.
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ bestie, this one catches a field with explicit alignment inside a packed struct or union that's misaligned ๐. The message looks likewarning: alignment 1 of 'struct S' is less than 8, and it pops up in code like this:
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall ๐.
-Wpaddedโ warns if padding sneaks into a struct, whether it's there to line up one element or to line up the whole struct ๐ฆ. Sometimes you can shuffle the fields around to cut the padding down and make the struct smaller, which is very iconic ๐.-Wredundant-declsโ warns if something gets declared more than once in the same scope ๐. This happens even when multiple declarations are valid and change absolutely nothing.-Wrestrictโ warns when an object referenced by arestrict-qualified parameter (or, in C++, a__restrict-qualified one) is aliased by another argument, or when copies between those objects overlap ๐ฅ. Check out thisstrcpycall that tries to chop the string by replacing its front with the last four characters. Because the call writes the terminating NUL intoa[4], the copies overlap, and GCC catches it:
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
-Wrestrict catches some simple overlap even without optimization, but it works best at -O2 and above ๐ง. It's included in -Wall ๐.
-Wnested-externs(C and Objective-C only) โ warns if anexterndeclaration shows up inside a function ๐.-Winlineโ warns if a function declared asinlinecan't actually be inlined ๐ . Even with this on, GCC won't warn about inlining failures for functions declared in system headers ๐.
The compiler uses a bunch of heuristics to decide whether to inline a function. For example, it looks at the size of the function being inlined and how much inlining has already happened in the current function. So seemingly tiny changes to your source can make -Winline warnings show up or disappear ๐.
-Wint-in-bool-contextโ warns about sus uses of integers where booleans are expected ๐ง. That includes conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). It also includes left-shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. The same goes for all kinds of multiplications, no matter the data type โ๏ธ. This warning is enabled by-Wall๐.-Wno-int-to-pointer-castโ suppresses warnings about casts to a pointer type from an integer of a different size ๐ซ . In C++, casting to a pointer type of smaller size is an error, so be careful ๐จ.Wint-to-pointer-castis enabled by default ๐ธ.-Wno-pointer-to-int-cast(C and Objective-C only) โ suppresses warnings about casts from a pointer to an integer type of a different size ๐.-Winvalid-pchโ warns if a precompiled header is found in the search path but can't be used ๐ญ.-Wlong-longโ warns if thelong longtype gets used ๐. It's enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. To shush the warnings, use-Wno-long-long๐คซ.-Wvariadic-macrosโ warns if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode ๐. It's enabled by either-Wpedanticor-Wtraditional. To inhibit the warning messages, use-Wno-variadic-macros๐.-Wno-varargsโ stops GCC from warning about questionable usage of the macros that handle variable arguments, likeva_start๐ฆ. These warnings are on by default, so this one is the opt-out ๐ .-Wvector-operation-performanceโ warns if a vector operation isn't implemented using the SIMD capabilities of the architecture โก. It's mainly useful for performance tuning ๐. A vector operation can be implemented in a few different ways:- "piecewise" โ the scalar operation is performed on every vector element ๐งฉ.
- "in parallel" โ the vector operation is implemented using scalars of a wider type, which is normally more performance-efficient ๐.
- "as a single scalar" โ the vector fits into a scalar type ๐.
-Wvlaโ warns if a variable-length array is used in the code ๐.-Wno-vlasilences the-Wpedanticwarning about variable-length arrays ๐ .-Wvla-larger-than=byte-sizeโ if you use this, GCC warns about declarations of variable-length arrays whose size is either unbounded, or bounded by an argument that lets the array size exceedbyte-sizebytes ๐ฆ. It's basically the vibe of-Walloca-larger-than=byte-size, but for VLAs ๐.
Heads up: GCC may optimize small VLAs with a known value into plain arrays, so this warning might not trigger for those ๐ซถ.
-Wvla-larger-than=PTRDIFF_MAX is enabled by default ๐ธ, but it's typically only effective when -ftree-vrp is active (which is the default for -O2 and above) ๐.
See also -Walloca-larger-than=byte-size.
-Wno-vla-larger-thanโ disables-Wvla-larger-than=warnings ๐. It's equivalent to-Wvla-larger-than=SIZE_MAXor larger.-Wvla-parameterโ warns about redeclarations of functions involving arguments of Variable Length Array types with inconsistent kinds or forms ๐งต. It also enables detecting out-of-bounds accesses to those parameters through warnings like-Warray-bounds๐.
If the first function declaration uses the VLA form, the bound in the array is assumed to be the minimum number of elements expected in calls to the function, and also the maximum number of elements it accesses. Not providing arguments of sufficient size, or accessing more than the maximum number of elements, may get diagnosed ๐ฉ.
Here's the drama: the warning triggers for these redeclarations because the first one lets an array of any size get passed to f, while the second one says the array argument must have at least n elements. Calling f with the associated VLA bound parameter larger 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 ๐. The -Warray-parameter option handles similar problems involving ordinary array arguments ๐.
-Wvolatile-register-varโ warns if a register variable is declaredvolatile๐ โโ๏ธ. Heads up:volatiledoesn't stop every optimization that might eliminate reads and/or writes to register variables ๐คท. This warning is enabled by-Wall๐.-Wdisabled-optimizationโ warns if a requested optimization pass gets disabled ๐. This doesn't usually mean anything's wrong with your code. It just means GCC's optimizers can't handle the code effectively ๐ . Often the problem is that your code is too big or too complex, since GCC refuses to optimize programs when the optimization would take inordinate amounts of time ๐ข.-Wpointer-sign(C and Objective-C only) โ warns for pointer argument passing or assignment with different signedness ๐ง. This option is only supported for C and Objective-C. It's implied by-Walland by-Wpedantic, and you can turn it off with-Wno-pointer-sign๐ .-Wstack-protectorโ this one is only active when-fstack-protectoris active ๐ก๏ธ. It warns about functions that aren't protected against stack smashing ๐ฅ.-Woverlength-stringsโ warns about string constants longer than the "minimum maximum" length the C standard specifies ๐. Modern compilers are usually fine with string constants way longer than that 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 specify a normative minimum maximum, so GCC doesn't diagnose overlength strings in C++ ๐.
-Woverlength-strings is implied by -Wpedantic, and it can be disabled with -Wno-overlength-strings ๐ซถ.
-Wunsuffixed-float-constants(C and Objective-C only) โ issues a warning for any floating constant without a suffix ๐ข. When you combine it with-Wsystem-headers, it also warns about those constants in system header files ๐งพ. This is super handy when you're prepping code to use with theFLOAT_CONST_DECIMAL64pragma from the decimal floating-point extension to C99 ๐.-Wno-lto-type-mismatchโ during link-time optimization, GCC won't warn about type mismatches in global declarations coming from different compilation units ๐ค. It requires-fltoto be enabled, and it's enabled by default ๐ธ.-Wno-designated-init(C and Objective-C only) โ suppresses warnings when a positional initializer is used to initialize a structure marked with thedesignated_initattribute ๐.
โจ Options That Control Static Analysis โจ
-fanalyzerโ turns on a static analysis of program flow ๐. It looks for "interesting" interprocedural paths through the code, and it issues warnings for problems it finds on them ๐ง ๐ฅ.
This analysis is much more expensive than other GCC warnings, bestie ๐ so don't be shocked if it takes its sweet time. It's giving deep-dive energy ๐ซถ
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-array-index
-Wanalyzer-unsafe-call-within-signal-handler
-Wanalyzer-use-after-free
-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. So if your build didn't include it, this one's a no-show ๐
โจ OPTIONS โจ
-Wanalyzer-too-complexโ If-fanalyzeris on, the analyzer uses a bunch of heuristics to poke around the control flow and data flow in your program, but really complicated code can totally defeat them ๐. By default the analysis just quietly stops once the code is too tangled and it hits an internal limit. This option is the one that actually warns you when that happens ๐.-Wno-analyzer-double-fcloseโ This warning needs-fanalyzerto be enabled (which turns it on), and you can turn it off with-Wno-analyzer-double-fclose. It flags paths through the code where aFILE *might getfclosecalled on it more than once ๐ .-Wno-analyzer-double-freeโ Needs-fanalyzer, and you can silence it with-Wno-analyzer-double-free. It catches paths where a pointer gets a deallocator called on it more than once, whether that'sfreeor a deallocator referenced by attribute "malloc" ๐ โโ๏ธ.-Wno-analyzer-exposure-through-output-fileโ Needs-fanalyzer, and disable it with-Wno-analyzer-exposure-through-output-file. This one is the security-sensitive one ๐. It warns on paths where something sensitive gets written to an output file, like dumping a password into a log file ๐ญ.-Wno-analyzer-file-leakโ Needs-fanalyzer, and-Wno-analyzer-file-leakturns it off. It warns on paths where aFILE *stream object from<stdio.h>gets leaked ๐ง.-Wno-analyzer-free-of-non-heapโ Needs-fanalyzer, and-Wno-analyzer-free-of-non-heapshuts it up. It warns on paths wherefreegets called on a pointer that isn't on the heap, like an on-stack buffer or a global ๐.-Wno-analyzer-malloc-leakโ Needs-fanalyzer, and you can disable it with-Wno-analyzer-malloc-leak. It warns on paths where a pointer from an allocator gets leaked, whether that allocator ismallocor a function marked with attribute "malloc" ๐ซง.-Wno-analyzer-mismatching-deallocationโ Needs-fanalyzer, and-Wno-analyzer-mismatching-deallocationis how you mute it. It warns on paths where the wrong deallocation function gets called on a pointer, based on which function originally allocated it. That covers mismatches betweenfree, scalardeleteand vectordelete[], plus anything marked as an allocator/deallocator pair using attribute "malloc" ๐งฉ.-Wno-analyzer-possible-null-argumentโ Needs-fanalyzer, and disable it with-Wno-analyzer-possible-null-argument. It warns on paths where a possibly-NULL value gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULL value ๐ซฃ.-Wno-analyzer-possible-null-dereferenceโ Needs-fanalyzer, and-Wno-analyzer-possible-null-dereferenceturns it off. It warns on paths where a possibly-NULL value gets dereferenced ๐.-Wno-analyzer-null-argumentโ Needs-fanalyzer, and-Wno-analyzer-null-argumentdisables it. It warns on paths where a value known to be NULL gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULL value ๐.-Wno-analyzer-null-dereferenceโ Needs-fanalyzer, and you can mute it with-Wno-analyzer-null-dereference. It warns on paths where a value known to be NULL gets dereferenced ๐จ.-Wno-analyzer-shift-count-negativeโ Needs-fanalyzer, and-Wno-analyzer-shift-count-negativeis the off switch. It warns on paths where a shift is attempted with a negative count ๐. It's the analyzer's cousin of the-Wshift-count-negativewarning from the C/C++ front ends, except it works by analyzing interprocedural paths instead of just parsing the syntax tree. Heads up though: the analyzer doesn't prioritize finding these, so false negatives are more likely compared to other warnings ๐ซ .-Wno-analyzer-shift-count-overflowโ Needs-fanalyzer, and disable it with-Wno-analyzer-shift-count-overflow. It warns on paths where a shift is attempted with a count greater than or equal to the precision of the operand's type ๐. It's analogous to the-Wshift-count-overflowdiagnostic in the C/C++ front ends, but again it's based on interprocedural paths rather than just the syntax tree. The analyzer doesn't prioritize these either, so false negatives are more likely relative to other warnings ๐.-Wno-analyzer-stale-setjmp-bufferโ Needs-fanalyzer, and-Wno-analyzer-stale-setjmp-bufferdisables it. It warns on paths wherelongjmpis called to rewind to ajmp_buftied to asetjmpcall, in a function that has already returned โช. Whensetjmpgets called on ajmp_bufto record a rewind location, it records the stack frame. That frame becomes invalid once the function containing thesetjmpcall returns. Trying to rewind to it withlongjmpwould reference a stack frame that doesn't exist anymore, and that's likely to lead to a crash (or worse) ๐ฅ.-Wno-analyzer-tainted-array-indexโ This one needs both-fanalyzerand-fanalyzer-checker=taintto turn on, and-Wno-analyzer-tainted-array-indexis how you turn it off ๐. It warns on paths where a value an attacker could control gets used as the index of an array access without being sanitized first ๐ โโ๏ธ.-Wno-analyzer-unsafe-call-within-signal-handlerโ Needs-fanalyzer, and disable it with-Wno-analyzer-unsafe-call-within-signal-handler. It warns on paths where a function known to be async-signal-unsafe (likefprintf) gets called from a signal handler ๐ซ.-Wno-analyzer-use-after-freeโ Needs-fanalyzer, and-Wno-analyzer-use-after-freemutes it. It warns on paths where a pointer gets used after a deallocator has been called on it, whether that deallocator isfreeor one referenced by attribute "malloc" ๐ชฆ.-Wno-analyzer-use-of-pointer-in-stale-stack-frameโ Needs-fanalyzer, and-Wno-analyzer-use-of-pointer-in-stale-stack-frameturns it off. It warns on paths where a pointer gets dereferenced while pointing to a variable in a stale stack frame ๐ฅ.-Wno-analyzer-write-to-constโ Needs-fanalyzer, and disable it with-Wno-analyzer-write-to-const. It warns on paths where the analyzer spots an attempt to write through a pointer to aconstobject ๐ โโ๏ธ. The analyzer doesn't prioritize these paths though, so false negatives are more likely relative to other warnings ๐คทโโ๏ธ.-Wno-analyzer-write-to-string-literalโ Needs-fanalyzer, and-Wno-analyzer-write-to-string-literalis the off switch. It warns on paths where the analyzer detects an attempt 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 ๐ซค.
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 ๐ง :
-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โ This restricts the analyzer to run just the named checker, and enables it ๐ฏ. Some checkers are disabled by default (even with-fanalyzer), like the "taint" checker that implements-Wanalyzer-tainted-array-index. You need this option to turn those on ๐.-fno-analyzer-feasibilityโ This one's intended 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-feasibility, which is handy for debugging issues in this code ๐.-fanalyzer-fine-grainedโ Also intended for analyzer developers ๐ฆ.
Okay bestie, so under the hood the analyzer builds this "exploded graph" ๐ธ๏ธโจ that mashes control flow graphs together with data flow info. It's giving main character energy ๐
By default, an edge in this graph can hold the effects of a whole run of statements inside one basic block. With -fanalyzer-fine-grained, each statement gets its own edge ๐ฆ
-fanalyzer-show-duplicate-countโ ๐ ๏ธ this one's for the analyzer devs! If several diagnostics get flagged as duplicates of each other, it drops a note on the best diagnostic telling you how many extra ones the deduplication logic quietly suppressed ๐-fno-analyzer-state-mergeโ ๐ ๏ธ also for the devs! By default the analyzer tries to keep things simple by merging sufficiently similar states at each program point while it builds its "exploded graph" ๐ง With-fno-analyzer-state-mergethat merging gets turned off, which is useful for debugging state-handling issues ๐-fno-analyzer-state-purgeโ ๐ ๏ธ devs, you know the drill ๐ By default the analyzer clears out state at a program point when it seems irrelevant, like the values of locals that never get accessed later in the function and don't matter for leak analysis ๐งน With-fno-analyzer-state-purgethat purging gets suppressed, for debugging state-handling issues ๐-fanalyzer-transitivityโ โจ turns on transitivity of constraints within the analyzer. Very smart, very lowkey ๐ง-fanalyzer-verbose-edgesโ ๐ ๏ธ dev-only! It gives you more verbose, lower-level detail in the descriptions of control flow within diagnostic paths ๐บ๏ธ-fanalyzer-verbose-state-changesโ ๐ ๏ธ also dev-only ๐ญ It gives you more verbose, lower-level detail in the descriptions of state machine events within diagnostic paths ๐-fanalyzer-verbosity=levelโ ๐ this one controls how complex the control flow paths are that get emitted for analyzer diagnostics. The level can be one of these:0โ at this level you see interprocedural call and return events, plus the most pertinent state-change events for a diagnostic. For example, with a double-"free" diagnostic, both calls to "free" get shown ๐ธ1โ same as the previous level, but also shows events for the entry to each function ๐ช2โ same as the previous level, but also shows control flow events that matter for triggering the issue (like "true path taken" at a conditional) โญ This level is the default, so it's the one you get if you don't pick anything ๐3โ same as the previous level, but shows all control flow events, not just the significant ones ๐4โ for the analyzer devs ๐ ๏ธ It adds various other events meant for debugging the analyzer itself ๐ง
-fdump-analyzerโ ๐ dumps internal details about what the analyzer is doing into file.analyzer.txt. This option gets overridden by-fdump-analyzer-stderr๐-fdump-analyzer-stderrโ ๐ dumps those same internal details to stderr. This option overrides-fdump-analyzer๐-fdump-analyzer-callgraphโ ๐บ๏ธ dumps a representation of the call graph that's suitable for viewing with GraphViz, written to file.callgraph.dot ๐ฆ-fdump-analyzer-exploded-graphโ ๐ธ๏ธ dumps a representation of the "exploded graph" that's suitable for viewing with GraphViz, written to file.eg.dot. The nodes are color-coded based on state-machine states so the state changes really pop ๐-fdump-analyzer-exploded-nodesโ ๐ฏ emits diagnostics showing where nodes in the "exploded graph" sit in relation to the program source ๐-fdump-analyzer-exploded-nodes-2โ ๐ dumps a textual representation of the "exploded graph" to file.eg.txt ๐-fdump-analyzer-exploded-nodes-3โ ๐ dumps a textual representation of the "exploded graph" to one dump file per node, named file.eg-id.txt. Heads up, this is typically a large number of dump files ๐ญ๐-fdump-analyzer-feasibilityโ ๐ dumps internal details about the analyzer's search for feasible paths. They're written in a form suitable for viewing with GraphViz, using filenames like file..fg.dot and file..tg.dot ๐งฉ-fdump-analyzer-jsonโ ๐ฆ dumps a compressed JSON representation of analyzer internals to file.analyzer.json.gz. The precise format is subject to change, so don't get too attached to it ๐ซถ-fdump-analyzer-state-purgeโ ๐งน like-fdump-analyzer-supergraph, this dumps a supergraph representation suitable for GraphViz, but it's annotated with info on what state will be purged at each node. The graph gets written to file.state-purge.dot ๐-fdump-analyzer-supergraphโ ๐บ๏ธ dumps representations of the "supergraph" suitable for GraphViz to file.supergraph.dot and to file.supergraph-eg.dot. These show all of the control flow graphs in the program, with interprocedural edges for calls and returns โจ The second dump has annotations showing nodes in the "exploded graph" and the diagnostics attached to them ๐ฅ
๐ Options for Debugging Your Program ๐
Okay so if you want GCC to emit extra info for a debugger, in almost all cases you just need to add -g to your other options ๐
GCC lets you use -g with -O. Fair warning though, the shortcuts optimized code takes can be kinda surprising ๐ญ Some variables you declared may not exist at all, flow of control might briefly jump somewhere you didn't expect, some statements may not run because they compute constant results or their values are already at hand, and some statements may execute in different places because they got moved out of loops ๐ Still, it is possible to debug optimized output, so it's reasonable to use the optimizer for programs that might have bugs ๐ซถ
If you're not using some other optimization option, consider using -Og with -g ๐
With no -O option at all, some compiler passes that collect information useful for debugging don't run at all, so -Og may give you a better debugging experience โจ
-gโ ๐ง produces debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information ๐ฆ
On most systems that use stabs format, -g turns on extra debugging information that only GDB can use. That extra info makes debugging work better in GDB, but it probably makes other debuggers crash or refuse to read the program ๐ญ If you want to control for certain whether the extra info gets generated, use -gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below) ๐ฏ
-ggdbโ ๐ produces debugging information for use by GDB. This means it uses the most expressive format available (DWARF, stabs, or the native format if neither of those is supported), including GDB extensions if at all possible ๐-gdwarf,-gdwarf-versionโ ๐ produces debugging information in DWARF format (if that's supported). The value of version can be 2, 3, 4 or 5. The default version for most targets is 5, with the exception of VxWorks, TPF and Darwin/Mac OS X, which default to version 2, and AIX, which defaults to version 4 ๐
With DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables ๐งฉ
Version 4 may require GDB 7.0 and -fvar-tracking-assignments for maximum benefit. Version 5 requires GDB 8.0 or higher โญ
GCC no longer supports DWARF Version 1, which is substantially different from Version 2 and later. For historical reasons, some other DWARF-related options, such as -fno-dwarf2-cfi-asm), still have a reference to DWARF Version 2 in their names, but they apply to all currently-supported versions of DWARF ๐ฐ๏ธ
-gstabsโ ๐งพ produces debugging information in stabs format (if that's 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 debugging output that DBX doesn't understand ๐ต On System V Release 4 systems this option requires the GNU assembler ๐ ๏ธ-gstabs+โ ๐งพ produces debugging information in stabs format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands. Using these extensions is likely to make other debuggers crash or refuse to read the program ๐-gxcoffโ ๐งพ produces debugging information in XCOFF format (if that's supported). This is the format the DBX debugger uses on IBM RS/6000 systems ๐ฅ๏ธ-gxcoff+โ ๐งพ produces debugging information in XCOFF format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands. Using these extensions is likely to 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 information in Alpha/VMS debug format (if that's supported). This is the format the DEBUG tool uses on Alpha/VMS systems ๐ธ-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ ๐๏ธ requests debugging information and also uses level to decide how much information you get. The default level is 2 ๐
Level 0 produces no debug information at all, so -g0 negates -g ๐ซ
Level 1 produces minimal information, enough for making backtraces in parts of the program you don't plan to debug. That includes descriptions of functions and external variables, and line number tables, but no information about local variables ๐งญ
Level 3 includes extra information, such as all the macro definitions present in the program. Some debuggers support macro expansion when you use -g3 ๐ช
If you use multiple -g options, with or without level numbers, the last such option 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 information is produced for symbols that aren't actually used. Use this option if you want debug information for all symbols ๐-femit-class-debug-alwaysโ ๐ Normally GCC only drops a C++ class's debug info into one object file, but this flag makes it emit that info in every object file that uses the class. Only reach for it if your debugger can't handle GCC's usual class debug output, because it can make the debug info up to a factor of two bigger. ๐ซถ-fno-merge-debug-stringsโ ๐ง This tells the linker to skip merging identical strings in the debug info across different object files. Not every assembler or linker can merge strings anyway. Merging keeps the output file's debug info smaller, but linking takes longer. Good news: merging is on by default. โจ-fdebug-prefix-map=old=newโ ๐บ๏ธ Files living in directoryoldget debug info written as if they lived in directorynewinstead. It's handy for swapping a build-time path for an install-time path, or for turning an absolute path into a relative one by using.asnew. This can make builds more reproducible and location independent, but you might need an extra command to tell GDB where the source files are. See also-ffile-prefix-map. ๐ธ-fvar-trackingโ ๐ This runs the variable tracking pass, which figures out where variables are stored at each spot in the code. The result is better debug info, as long as your debug format supports it. It's switched on automatically when you compile with optimization (-Os,-O,-O2, ...) and debug info (-g), and the format supports it. ๐-fvar-tracking-assignmentsโ ๐ This annotates assignments to user variables early on and tries to carry those annotations all the way to the end of compilation, so debug info stays good while optimizing. Pairing it with-gdwarf-4is recommended. It can be turned on even when var-tracking is off, but then the annotations get thrown away at the end. By default it's enabled together with-fvar-tracking, except when selective scheduling is on. ๐-gsplit-dwarfโ ๐ฆ With DWARF debug info enabled, this shoves as much of it as possible into a separate output file ending in.dwo. That lets your build system skip linking files that carry debug info. It's only useful if your debugger can actually read.dwofiles. ๐-gdwarf32,-gdwarf64โ ๐ With DWARF debug info 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. The 32-bit format is smaller, but it can't hold more than 2GiB of debug info in any DWARF debug section. The 64-bit format handles bigger debug info, but not every consumer supports it well yet. ๐งฎ-gdescribe-diesโ ๐ท This adds description attributes to some DWARF DIEs that don't have a name attribute, like artificial variables, external references, and call site parameter DIEs. โจ-gpubnamesโ ๐ This generates the DWARF.debug_pubnamesand.debug_pubtypessections. ๐-ggnu-pubnamesโ ๐งฉ This generates.debug_pubnamesand.debug_pubtypesin a format that can be converted into a GDB index. It's only useful if your linker can produce GDB index version 7. ๐ฅ-fdebug-types-sectionโ ๐ซง With DWARF Version 4 or higher, type DIEs can get their own.debug_typessection instead of living inside.debug_info. That's more efficient since the linker can drop duplicates when they sit in a separate comdat section. The catch: not all DWARF consumers support.debug_typesyet, and on some objects it makes debug info bigger, not smaller. ๐ญ-grecord-gcc-switches,-gno-record-gcc-switchesโ ๐ This appends the command-line options that might affect code generation to theDW_AT_producerattribute in DWARF debug info. The options are joined with spaces, both from each other and from the compiler version. It's on by default. See also-frecord-gcc-switchesfor another way to store compiler options in the object file. ๐-gstrict-dwarfโ ๐ซ This stops you from using extensions from a later DWARF standard version than the one picked with-gdwarf-version. On most targets, though, extensions from later versions that don't conflict with anything are still allowed. ๐-gno-strict-dwarfโ ๐๏ธ This lets you use extensions from a later DWARF standard version than the one picked with-gdwarf-version. ๐-gas-loc-supportโ ๐ This tells the compiler the assembler understands.locdirectives, so the compiler can hand off line number table generation to the assembler to produce DWARF2+ tables. That's usually what you want, since assembler-generated line number tables are way more compact than the ones GCC can build itself. It's enabled by default if the assembler was found to support those directives when GCC was configured. ๐ฆ-gno-as-loc-supportโ ๐ ๏ธ This forces GCC to generate DWARF2+ line number tables internally, whenever those tables are going to be generated at all. ๐ง-gas-locview-supportโ ๐ This tells the compiler the assembler supports"view"assignment and reset assertion checking in.locdirectives. It's enabled by default if the assembler was found to support them at GCC configure time. ๐-gno-as-locview-supportโ ๐ข This forces GCC to assign view numbers internally, but only if-gvariable-location-viewswas explicitly requested. ๐-gcolumn-info,-gno-column-infoโ ๐ฏ This puts location column information into DWARF debug info, not just file and line. It's enabled by default. โญ-gstatement-frontiers,-gno-statement-frontiersโ ๐ฉ This makes GCC drop markers into the internal representation at the start of each statement, then keeps them roughly where they are 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,-O,-O2, ...) and output DWARF 2 debug info at the normal level. ๐ง-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-viewsโ ๐ญ This adds progressive view numbers, implied by the line number table, onto variable location lists. That lets debug consumers peek at the program state at certain points, even when no instructions tied to those source locations exist there. If the assembler can't handle view numbers in line number tables, GCC emits its own line number table instead, which is usually less compact. The augmented tables and lists are fully backward compatible, so older consumers can still read them, they just won't get any benefit. ๐
It's enabled by default when outputting DWARF 2 debug info at the normal level, as long as the assembler supports it, -fvar-tracking-assignments is on, and -gstrict-dwarf is off. If the assembler doesn't support it, the option can still be enabled, but it forces GCC to output internal line number tables. Unless -ginternal-reset-location-views is also enabled, that will most certainly lead to silently mismatching location views. ๐ฑ
There's also a proposed representation for view numbers that isn't backward compatible with the location list format from DWARF 5, and you can turn it on with -gvariable-location-views=incompat5.
โ ๏ธ Heads up bestie: -gvariable-location-views=incompat5 may be removed in the future. It's only there as a reference implementation of the proposed representation. Debug info consumers aren't expected to support this extended format, and they won't be able to decode location lists that use it. ๐
โโ๏ธ
-ginternal-reset-location-views,-gno-internal-reset-location-viewsโ ๐งน This tries to figure out which location views can be dropped from location view lists. It needs the compiler to have very accurate instruction length estimates, which isn't always the case. It can silently generate incorrect view lists when the assembler doesn't support location view lists. The GNU assembler will flag that kind of error as a"view number mismatch". This is only enabled on ports that define a reliable estimation function. โ ๏ธ-ginline-points,-gno-inline-pointsโ ๐ This generates extended debug info for inlined functions. Location view tracking markers get inserted at inlined entry points, so address and view numbers can be computed and output in debug info. You can turn it on independently of location views, in which case the view numbers won't be output. It can only be enabled along with statement frontiers, and it's only enabled by default if location views are enabled. ๐-gz[=type]โ ๐๏ธ This produces compressed debug sections in DWARF format, if that's supported. If you don't give atype, the default depends on what the assembler and linker can do.typecan benone(don't compress debug sections),zlib(zlib compression in ELF gABI format), orzlib-gnu(zlib compression in the traditional GNU format). If the linker can't write compressed debug sections, the option gets rejected. Otherwise, if the assembler doesn't support them,-gzis quietly ignored when producing object files. ๐ง-femit-struct-debug-baseonlyโ ๐ช This only emits debug info for struct-like types when the base name of the compilation source file matches the base name of the file where the struct is defined. It shrinks debug info a lot, but the debugger can lose a significant amount of type information. See-femit-struct-debug-reducedfor a less aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option only works with DWARF debug output. ๐ฅน
โ ๏ธ Real talk: -femit-struct-debug-baseonly can cost you a big chunk of type information in the debugger, so it's a trade-off, not a free win. ๐
-femit-struct-debug-reducedโ okay bestie, this one is a total space saver ๐ Debug info for struct-like types only gets emitted 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 makes the debug info way smaller ๐ฆ, but you might lose a little type info the debugger would've wanted ๐ญ. For a more aggressive version, check out
-femit-struct-debug-baseonly, and for finer control, look at-femit-struct-debug-detailed. - This only works with DWARF debug output ๐
- It makes the debug info way smaller ๐ฆ, but you might lose a little type info the debugger would've wanted ๐ญ. For a more aggressive version, check out
-femit-struct-debug-detailed[=spec-list]โ this one is the customizable queen ๐ It lets you pick exactly which struct-like types get debug info, mostly so you don't get duplicate struct debug info across different object files in the same program ๐ง It's a detailed version of-femit-struct-debug-reducedand-femit-struct-debug-baseonly, and honestly it covers most needs ๐ซถ- A spec looks like
[dir:|ind:][ord:|gen:](any|sys|base|none). The first two words are optional, and the third word tells the compiler which source files to care about ๐ - First word (
dir:orind:) โ this one is optional and limits the spec to structs that are used directly (dir:) or used indirectly (ind:). A struct is used directly when it's the type of a variable or member. Indirect uses come through pointers to structs. In other words, when using an incomplete struct is valid, that use is indirect. Example:struct one direct; struct two * indirect;๐ - Second word (
ord:orgen:) โ also optional, and it limits the spec to ordinary structs (ord:) or generic structs (gen:). Generic structs are a little complicated, ngl. 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-detaileddoesn't implement them yet ๐ฅน - Third word โ this one picks the source files the compiler should emit debug info for.
noneandanyhave their normal meanings.basemeans the base name of the file where the type declaration appears has to match the base name of the main compilation file. So when you compilefoo.c, debug info gets generated for types declared in that file andfoo.h, but not other header files ๐syscovers types that satisfybaseor are declared in system or compiler headers ๐ - You might need to experiment to find the best settings for your app, no cap ๐ฅ
- The default is
-femit-struct-debug-detailed=all๐ธ - This also only works with DWARF debug output โญ
- A spec looks like
-fno-dwarf2-cfi-asmโ emit DWARF unwind info as a compiler-generated".eh_frame"section, instead of using GAS".cfi_*"directives. Main character energy in the assembler, honestly ๐-fno-eliminate-unused-debug-typesโ okay so 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 debug info for every type declared in a compilation unit, even unused ones. For example, if you want to cast a value to a type in the debugger that's declared but never actually used in your program. Just know that this often wastes a ton of 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. So 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 ๐ฆ
Turning on optimization flags makes the compiler try to improve performance and/or code size, but 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 one ๐ซถ
Not all optimizations are controlled directly by a flag. Only the 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 you specify individual optimization flags. 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. If you want the exact set for 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 โจ -Oturns on the following optimization flags:
- With
-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
-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 increases both compilation time and the performance of the generated code ๐-O2turns on all optimization flags specified by-O. 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-pre
-ftree-switch-conversion -ftree-tail-merge -ftree-vrp
- > ๐จ Please note the warning under
-fgcseabout invoking-O2on programs that use computed gotos. Bestie, read that one before you ship ๐จ - > ๐ก๏ธ NOTE: In Ubuntu 8.10 and later versions,
-D_FORTIFY_SOURCE=2is set by default. In Ubuntu 24.04 and later versions,-D_FORTIFY_SOURCE=3is set by default instead. It's activated when-Ois set to 2 or higher, and it enables additional compile-time and run-time checks for several libc functions ๐ฅน To disable it, specify either-U_FORTIFY_SOURCEor-D_FORTIFY_SOURCE=0.
-O3โ optimize yet more ๐ฅ-O3turns on all optimizations specified by-O2, and it 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-loop-vectorize -ftree-partial-pre -ftree-slp-vectorize
-funswitch-loops -fvect-cost-model -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 ๐-Osenables all-O2optimizations except the ones 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, causes the compiler to tune for code size rather than execution speed, and performs further optimizations designed to reduce code size ๐ฆ
-Ofastโ disregard strict standards compliance ๐-Ofastenables all-O3optimizations. It also enables optimizations that aren't valid for all standard-compliant programs, so proceed with care ๐- > โ ๏ธ Because
-Ofastturns on optimizations that aren't valid for every standard-compliant program, your code might behave differently than you expect. It turns on-ffast-math,-fallow-store-data-races, and the Fortran-specific-fstack-arrays(unless-fmax-stack-var-sizeis specified), and-fno-protect-parens๐ญ
- > โ ๏ธ Because
-Ogโ optimize the debugging experience ๐-Ogshould 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-O0for producing debuggable code, because some compiler passes that collect debug information are disabled at-O0๐ซถ- Like
-O0,-Ogcompletely disables a number of optimization passes, so the individual options controlling them have no effect ๐ Otherwise,-Ogenables all-O1optimization flags except for the ones that may interfere with debugging:
- Like
-fbranch-count-reg -fdelayed-branch -fdse -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fssa-phiopt -ftree-bit-ccp -ftree-dse
-ftree-pta -ftree-sra
If you use multiple -O options, with or without level numbers, the last such option is the one that takes effect ๐
Options of the form -fflag specify machine-independent flags ๐ Most flags have both positive and negative forms, and the negative form of -ffoo is -fno-foo. In the 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 the following flags in the rare cases when "fine-tuning" of optimizations to be performed is desired ๐
-fno-defer-popโ okay so on machines that have to pop the arguments after a function call ๐งน, this makes GCC pop them the second each function returns ๐ . Heads up though: at-O1and higher,-fdefer-popis the default, which lets arguments pile up on the stack across several calls and then get popped all at once โจ.-fforward-propagateโ this one's giving RTL realness ๐ฆ. It runs a forward propagation pass on RTL that tries to combine two instructions, then checks whether the result can be simplified. If loop unrolling is active, the pass runs twice, and the second run gets scheduled after loop unrolling ๐. Enabled by default at optimization levels-O,-O2,-O3,-Os๐.-ffp-contract=styleโ bestie, this one's a whole mood ๐.-ffp-contract=offturns floating-point expression contraction OFF ๐ โโ๏ธ.-ffp-contract=fastturns it on, so things like fused multiply-add operations can get formed if the target has native support for them ๐ฅ.-ffp-contract=ononly enables contraction if the language standard allows it ๐. Ngl, that one isn't implemented yet and gets treated the same as-ffp-contract=off๐. The default is-ffp-contract=fast๐.-fomit-frame-pointerโ omits the frame pointer in functions that don't need one ๐ง. This skips the instructions for saving, setting up and restoring the frame pointer, and on lots of targets it also frees up an extra register ๐. Sometimes it does nothing, because on some targets the standard calling sequence always uses a frame pointer, so it can't be dropped ๐. Also,-fno-omit-frame-pointerdoesn't promise the frame pointer gets used in every function, since several targets always omit it in leaf functions ๐. Enabled by default at-Oand higher โญ.-foptimize-sibling-callsโ optimizes sibling and tail recursive calls ๐ช. Enabled at levels-O2,-O3,-Os๐.-foptimize-strlenโ glow-up time for standard C string functions like"strlen","strchr"or"strcpy", plus their"_FORTIFY_SOURCE"counterparts, which get turned into faster alternatives ๐๏ธ. Enabled at levels-O2,-O3โจ.-fno-inlineโ no function gets expanded inline except the ones marked with the"always_inline"attribute ๐ . This is the default when you're not optimizing ๐ค. Single functions can be exempted from inlining by marking them with the"noinline"attribute ๐ซ.-finline-small-functionsโ integrates functions into their callers when their body is smaller than the code for the function call itself, so the overall program gets smaller ๐. The compiler heuristically decides which functions are simple enough to be worth it ๐ง . This applies to all functions, even the ones not declared inline ๐. Enabled at levels-O2,-O3,-Os๐ .-findirect-inliningโ also inlines indirect calls that are discovered to be known at compile time, thanks to earlier inlining ๐ฏ. This only has an effect 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 declared inline ๐ธ. The compiler heuristically decides which ones are worth it. If every call to a given function gets integrated and that function is declared"static", it's normally not spit out as its own assembler code ๐ซฅ. Enabled at levels-O2,-O3,-Os. Also enabled by-fprofile-useand-fauto-profile๐.-finline-functions-called-onceโ considers all"static"functions called once for inlining into their caller, even if they aren't marked"inline"๐ฅก. If a call gets integrated, the function isn't output as assembler code in its own right ๐. Enabled at levels-O1,-O2,-O3and-Os, but not-Og๐ซ.-fearly-inliningโ inlines functions marked"always_inline", plus functions whose body seems smaller than the function call overhead, early on. This happens before the-fprofile-generateinstrumentation and the real inlining pass โฉ. Doing it this way makes profiling significantly cheaper and usually makes inlining faster in programs with large chains of nested wrapper functions ๐ช. Enabled by default ๐ฏ.-fipa-sraโ performs interprocedural scalar replacement of aggregates ๐งฉ, removes unused parameters, and swaps parameters passed by reference for parameters passed by value ๐. Enabled at levels-O2,-O3and-Os๐.-finline-limit=nโ by default GCC caps the size of functions that can be inlined, and this flag gives you coarse control over that cap ๐๏ธ.nis the size of functions that can be inlined, measured in pseudo instructions ๐.max-inline-insns-singleis set ton/2.max-inline-insns-autois set ton/2.- Inlining is actually controlled by a bunch of parameters, which you can set individually with
--param name=value๐ง. The-finline-limit=noption sets some of them like this, as shown above. See below for documentation of the individual inlining parameters and their defaults ๐. - Note: there may be no value of
-finline-limitthat results in default behavior ๐. - Note: a "pseudo instruction" here is just an abstract measurement of a function's size โจ. It is in no way a count of assembly instructions, so its exact meaning might change from one release to another ๐ซ .
-fno-keep-inline-dllexportโ a more fine-grained version of-fkeep-inline-functions, which only applies to functions declared with the"dllexport"attribute or declspec ๐ฏ.-fkeep-inline-functionsโ in C, emits"static"functions declared"inline"into the object file, even if they've been inlined into all of their callers ๐ฆ. This switch doesn't affect functions using the"extern inline"extension in GNU C90 ๐ . In C++, emits any and all inline functions into the object file ๐.-fkeep-static-functionsโ emits"static"functions into the object file, even if they're never used ๐๏ธ.-fkeep-static-constsโ emits variables declared"static const"when optimization isn't turned on, even if they're never referenced ๐. GCC enables this by default ๐ . If you want the compiler to check whether a variable is referenced regardless of optimization, use-fno-keep-static-consts๐.-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 inhibit this behavior ๐. Enabled at levels-O,-O2,-O3,-Osโจ.-fmerge-all-constantsโ attempts to merge identical constants and identical variables ๐งฌ. This implies-fmerge-constants๐. On top of that, it also considers things like constant initialized arrays or initialized constant variables with integral or floating-point types ๐.
๐จ Warning: C and C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations, so using this option results in non-conforming behavior. Yikes, bestie ๐ญ.
-fmodulo-schedโ performs swing modulo scheduling immediately before the first scheduling pass ๐. It looks at the innermost loops and reorders their instructions by overlapping different iterations ๐.-fmodulo-sched-allow-regmovesโ performs more aggressive SMS-based modulo scheduling with register moves allowed ๐ช. Setting this flag deletes certain anti-dependence edges, which triggers the generation of reg-moves based on life-range analysis ๐งช. This is only effective with-fmodulo-schedenabled ๐ซถ.-fno-branch-count-regโ disables the optimization pass that hunts for chances to use "decrement and branch" instructions on a count register, instead of decrementing a register, comparing it against zero, and then branching based on the result ๐ข. This is only meaningful on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390 ๐ฅ๏ธ. Note that-fno-branch-count-regdoesn't remove the decrement and branch instructions introduced by other optimization passes ๐. The default is-fbranch-count-regat-O1and higher, except for-Ogโจ.-fno-function-cseโ doesn't put function addresses in registers; instead, each instruction that calls a constant function contains the function's address explicitly ๐. This gives less efficient code, but some strange hacks that alter the assembler output may get confused by the optimizations performed when this option isn't used ๐ง. The default is-ffunction-cse๐.-fno-zero-initialized-in-bssโ if the target supports a BSS section, GCC by default puts variables initialized to zero into BSS, which can save space in the resulting code ๐พ. This option turns that behavior off, because some programs explicitly rely on variables going into the data section ๐บ๏ธ. For example, the executable can find the beginning of that section and/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, is found ๐. If so, the first branch is redirected to either the destination of the second branch or a point immediately following it, depending on whether the condition is known to be true or false ๐ช. Enabled at levels-O2,-O3,-Os๐ธ.-fsplit-wide-typesโ when using a type that occupies multiple registers, like"long long"on a 32-bit system, splits the registers apart and allocates them independently โ๏ธ. This normally generates better code for those types, but it may make debugging more difficult ๐. Enabled at levels-O,-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 ====================
Okay so, this one lives in common subexpression elimination (CSE) ๐
It scans through jump instructions when the jump's target isn't reached by any other path. Like, when CSE hits an if with an else clause, it follows the jump when the condition tested is false. Iconic. ๐ฆ
Enabled at levels -O2, -O3, -Os.
-fcse-skip-blocksโ bestie, this is basically the sibling of-fcse-follow-jumpsโจ It makes CSE follow jumps that conditionally skip over blocks. So when CSE sees a simpleifwith noelseclause, this flag has it follow the jump around the body of theif. Main character energy ๐
Enabled at levels -O2, -O3, -Os.
-frerun-cse-after-loopโ re-runs common subexpression elimination after the loop optimizations are done. It's giving second chances ๐๐ธ
Enabled at levels -O2, -O3, -Os.
-fgcseโ performs a global common subexpression elimination pass. This one also does global constant and copy propagation, so it's doing a lot of work for you ๐ซถ
โ ๏ธ 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 CSE pass by adding -fno-gcse to the command line. Just something to keep in mind, bestie ๐ญ
Enabled at levels -O2, -O3, -Os.
-fgcse-lmโ when this is on, global CSE tries to move loads that are only killed by stores into themselves. Translation: a loop with a load/store sequence can become a load outside the loop and a copy/store inside it. Lowkey genius ๐ง
Enabled by default when -fgcse is enabled.
-fgcse-smโ when this is on, a store motion pass runs after global CSE. It tries to move stores out of loops. Used together with-fgcse-lm, a loop with a load/store sequence can become a load before the loop and a store after the loop. Slay ๐
Not enabled at any optimization level.
-fgcse-lasโ makes the global CSE pass eliminate redundant loads that come after stores to the same memory location. That covers both partial and full redundancies. Very thorough, very serious ๐งโจ
Not enabled at any optimization level.
-fgcse-after-reloadโ runs a redundant load elimination pass after reload. Its whole job is to clean up redundant spilling ๐งน๐
Enabled by -fprofile-use and -fauto-profile.
-faggressive-loop-optimizationsโ tells the loop optimizer to use language constraints to work out bounds for the number of loop iterations. This assumes the loop code doesn't invoke undefined behavior, like causing signed integer overflows or out-of-bound array accesses. Those bounds then guide loop unrolling, loop peeling, and loop exit test optimizations. This option is enabled by default. ๐ฅ
โ ๏ธ Heads up, bestie: this one relies on your code not hitting undefined behavior. Signed integer overflow or out-of-bounds array access breaks that assumption, so keep your code clean ๐
-funconstrained-commonsโ tells the compiler that variables declared in common blocks (for example, in Fortran) may later be overridden with longer trailing arrays. This stops certain optimizations that depend on knowing the array bounds from happening ๐-fcrossjumpingโ performs the cross-jumping transformation. It unifies equivalent code and saves code size. The result may or may not perform better than code without cross-jumping, so it's a bit of a vibe check ๐ฆ
Enabled at levels -O2, -O3, -Os.
-fauto-inc-decโ combines increments or decrements of addresses with memory accesses. This pass is always skipped on architectures that don't have instructions to support it. It's enabled by default at-Oand higher on architectures that do support it โจ-fdceโ performs dead code elimination (DCE) on RTL. Enabled by default at-Oand higher. Bye bye, unused code ๐๐-fdseโ performs dead store elimination (DSE) on RTL. Enabled by default at-Oand higher. Stores nobody reads get yeeted ๐๏ธ๐ธ-fif-conversionโ attempts to transform conditional jumps into branch-less equivalents. This includes conditional moves, min, max, set flags, and abs instructions, plus some tricks you can do with standard arithmetic. Whether conditional execution gets used on chips that have it is controlled by-fif-conversion2.
Enabled at levels -O, -O2, -O3, -Os, but not with -Og.
-fif-conversion2โ uses conditional execution (where available) to transform conditional jumps into branch-less equivalents ๐ง
Enabled at levels -O, -O2, -O3, -Os, but not with -Og.
-fdeclone-ctor-dtorโ okay, C++ ABI moment ๐ค The ABI requires multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that callsoperator deleteafterwards. For a hierarchy with virtual bases, the base and complete variants are clones, meaning two copies of the function. With this option, those variants become thunks that call one common implementation. Less duplicated code, more slay ๐
Enabled by -Os.
-fdelete-null-pointer-checksโ assumes that programs can't safely dereference null pointers, and that no code or data lives at address zero. This enables simple constant folding optimizations at all optimization levels. Other passes in GCC also use this flag to control global dataflow analyses that eliminate useless null pointer checks. Those assume that a memory access to address zero always traps, so if a pointer gets checked after it's already been dereferenced, it can't be null. Big brain logic ๐ง
โ ๏ธ Not every environment agrees with that assumption! If your program depends on dereferencing address zero, 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, this option is completely disabled ๐ โโ๏ธ
Passes that use the dataflow information are enabled independently at different optimization levels.
-fdevirtualizeโ attempts to convert calls to virtual functions into direct calls. This happens both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp). Enabled at levels-O2,-O3,-Os. ๐ฆ-fdevirtualize-speculativelyโ attempts to convert calls to virtual functions into speculative direct calls. Based on analysis of the type inheritance graph, it figures out the set of likely targets for a given call. If that set is small (preferably size 1), the call becomes a conditional that picks between a direct call and an indirect call. The speculative calls enable more optimizations, like inlining. If they seem useless after further optimization, they get converted back to their original form ๐-fdevirtualize-at-ltransโ streams extra information needed for aggressive devirtualization when running the link-time optimizer in local transformation mode. It enables more devirtualization, but it significantly increases the size of the streamed data. For this reason it's disabled by default ๐ฆ-fexpensive-optimizationsโ performs a bunch of minor optimizations that are relatively expensive. Enabled at levels-O2,-O3,-Os. ๐ธ-freeโ attempts to remove redundant extension instructions. This is especially helpful for the x86-64 architecture, which implicitly zero-extends 64-bit registers after writing to their lower 32-bit half ๐ธ
Enabled for Alpha, AArch64, and x86 at levels -O2, -O3, -Os.
-fno-lifetime-dseโ in C++, an object's value is only affected by changes within its lifetime. When the constructor begins, the object has an indeterminate value, and any changes during its lifetime are dead once the object is destroyed. Normally dead store elimination takes advantage of this. If your code relies on the object storage's value persisting past the object's lifetime, use this flag to disable the optimization. To keep stores made before the constructor starts (for example, because youroperator newclears the object storage) but still treat the object as dead after the destructor, use-flifetime-dse=1. The default behavior can be explicitly selected with-flifetime-dse=2. And-flifetime-dse=0is the same as-fno-lifetime-dse๐งโโ๏ธ-flive-range-shrinkageโ attempts to decrease register pressure through register live range shrinkage. Helpful for fast processors with small or moderate-size register sets ๐โโ๏ธ๐จ-fira-algorithm=algorithm โ picks the coloring algorithm for the integrated register allocator. The algorithm argument can bepriority, which 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 โ picks the regions the integrated register allocator uses. The region argument should be one of the following:allโ uses all loops as register allocation regions. This can give the best results on machines with a small and/or irregular register set ๐ฏmixedโ uses all loops except loops with small register pressure as the regions. This usually gives the best results in most cases and for most architectures, and it's enabled by default when compiling with optimization for speed (-O,-O2, ...) ๐oneโ uses all functions as a single region. This typically results in the smallest code size, and it's enabled by default for-Osor-O0๐ค
-fira-hoist-pressureโ uses IRA to evaluate register pressure in the code hoisting pass when deciding whether to hoist expressions. This usually results in smaller code, but it can slow the compiler down ๐ข
This option is enabled at level -Os for all targets.
-fira-loop-pressureโ uses IRA to evaluate register pressure in loops when deciding whether to move loop invariants. This usually results in faster and smaller code on machines with large register files (32 or more registers), but it can slow the compiler down ๐โจ
This option is enabled at level -O3 for some targets.
-fno-ira-share-save-slotsโ ๐งธ Okay so this one turns OFF sharing of stack slots used for saving call-used hard registers that stay alive through a call. Every hard register gets its own separate stack slot, which means function stack frames end up larger ๐ฆ-fno-ira-share-spill-slotsโ ๐ธ This one switches off sharing of stack slots for pseudo-registers. Each pseudo-register that doesn't get a hard register gets its own slot, so, again, function stack frames are larger ๐ฅฒ-flra-rematโ ๐ฆ Turns on CFG-sensitive rematerialization in LRA. Instead of loading values of spilled pseudos from memory, LRA tries to rematerialize (recalculate) them when that's actually profitable ๐งฎ Switched on at-O2,-O3,-Osโจ-fdelayed-branchโ ๐ง If the target machine supports it, GCC tries to reorder instructions so it can use the instruction slots that come after delayed branch instructions ๐ Switched on at-O,-O2,-O3,-Os, but not at-Og๐-fschedule-insnsโ โญ If supported for the target machine, GCC tries to reorder instructions to get rid of execution stalls caused by data that isn't ready yet โณ This is a lifesaver for machines with slow floating point or memory load instructions, because other instructions can get issued while the load or float op is still cooking, until the result is actually needed ๐ Switched on at-O2,-O3๐ฅ-fschedule-insns2โ ๐ Basically the same vibe as-fschedule-insns, but it asks for an extra scheduling pass after register allocation is done ๐ซถ This is especially iconic on machines with a relatively small number of registers, where memory load instructions take more than one cycle ๐ Switched on at-O2,-O3,-Os๐-fno-sched-interblockโ ๐ โโ๏ธ Disables instruction scheduling across basic blocks. This is normally on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐-fno-sched-specโ ๐ซ Disables speculative motion of non-load instructions. Normally this is on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐-fsched-pressureโ ๐ Enables register pressure sensitive instruction scheduling before register allocation. This only makes sense when scheduling before register allocation is enabled, i.e. with-fschedule-insnsor at-O2or higher ๐ง It can improve the generated code and shrink its size by stopping register pressure from climbing above the number of available hard registers, which would otherwise lead to spills during register allocation ๐ช-fsched-spec-loadโ ๐ Allows speculative motion of some load instructions. Only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐ท-fsched-spec-load-dangerousโ ๐ Allows speculative motion of more load instructions. Same deal: it only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher. It's called "dangerous" for a reason, bestie ๐-fsched-stalled-insns,-fsched-stalled-insns=nโ ๐ข This decides how many insns (if any) can be 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 ahead, and plain-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 early removal from the stalled queue ๐ต๏ธโโ๏ธ It only does anything during the second scheduling pass, and only if-fsched-stalled-insnsis used.-fno-sched-stalled-insns-depis the same as-fsched-stalled-insns-dep=0, and plain-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 faster schedules ๐๏ธ
โ ๏ธ Heads up, bestie: this one is experimental! Not all machine descriptions used by GCC model the CPU closely enough, so the algorithm can give unreliable results ๐ญ This only makes sense when scheduling after register allocation, i.e. with-fschedule-insns2or at-O2or higher.
-fsched-group-heuristicโ ๐ฏ Enables the group heuristic in the scheduler, which favors the instruction that belongs to a schedule group ๐ This is enabled by default whenever scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐ธ-fsched-critical-path-heuristicโ ๐ฃ๏ธ Enables the critical-path heuristic in the scheduler, which favors instructions sitting on the critical path ๐โโ๏ธ Also on by default whenever scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-spec-insn-heuristicโ ๐ฏ Enables the speculative instruction heuristic in the scheduler, which favors speculative instructions with greater dependency weakness ๐ฅฐ Enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher โจ-fsched-rank-heuristicโ ๐ Enables the rank heuristic in the scheduler, which favors the instruction belonging to a basic block with greater size or frequency ๐ Enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-last-insn-heuristicโ ๐ Enables the last-instruction heuristic in the scheduler, which favors the instruction that is less dependent on the last instruction scheduled ๐ Enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐ฆ-fsched-dep-count-heuristicโ ๐งต Enables the dependent-count heuristic in the scheduler, which favors the instruction that has more instructions depending on it ๐ธ๏ธ Enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-freschedule-modulo-scheduled-loopsโ ๐ Modulo scheduling happens before the traditional scheduling. If a loop gets modulo scheduled, later scheduling passes may change its schedule, and this option is how you control that behavior ๐๏ธ-fselective-schedulingโ ๐ Schedules instructions using the selective scheduling algorithm. Selective scheduling runs instead of the first scheduler pass ๐ช-fselective-scheduling2โ ๐ 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 has no effect unless-fselective-schedulingor-fselective-scheduling2is turned on ๐-fsel-sched-pipelining-outer-loopsโ ๐ช When pipelining loops during selective scheduling, this also pipelines the outer loops ๐ It has no effect unless-fsel-sched-pipeliningis turned on ๐-fsemantic-interpositionโ ๐ญ Some object formats, like ELF, let the dynamic linker interpose symbols. That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, and other optimizations, since the function or variable might get swapped out for something else ๐ This is super useful for things like rewriting memory allocation functions with a debugging implementation, but it's expensive in terms of code quality ๐ธ With-fno-semantic-interposition, the compiler assumes that if interposition happens for functions, the overwriting function will have precisely the same semantics (and side effects). Similarly, if interposition happens for variables, the constructor of the variable will be the same ๐ค The flag has no effect for functions explicitly declaredinline, where interposition is never allowed to change semantics, and for symbols explicitly declaredweak๐ง-fshrink-wrapโ ๐ Emits function prologues only before the parts of the function that actually need them, instead of at the very top ๐งฃ Enabled by default at-Oand higher ๐-fshrink-wrap-separateโ โ๏ธ Shrink-wraps the separate parts of the prologue and epilogue separately, so those parts only run when they're needed ๐ This option is on by default, but it has no effect unless-fshrink-wrapis also turned on and the target supports this ๐ซถ-fcaller-savesโ ๐ Enables allocation of values to registers that get clobbered by function calls, by emitting extra instructions to save and restore those registers around such calls ๐ This allocation only happens when it seems to result in better code ๐ฅ This option is always enabled by default on certain machines, usually the ones that have no call-preserved registers to use instead ๐ Switched on at-O2,-O3,-Os๐ซ-fcombine-stack-adjustmentsโ ๐งฉ Tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐ฅ Enabled by default at-O1and higher ๐-fipa-raโ ๐ง Uses caller save registers for allocation if those registers aren't used by any called function. In that case, there's no need to save and restore them around calls ๐ช This is only possible if the called functions are part of the same compilation unit as the current function and they're compiled before it ๐ Switched on at-O2,-O3,-Os, however 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, which happens on targets that don't expose prologues and epilogues in RTL ๐-fconserve-stackโ ๐ชถ Attempts to minimize stack usage, using less stack space even if that makes the program slower ๐ This option implies setting thelarge-stack-frameparameter to100and thelarge-stack-frame-growthparameter to400๐งฎ-ftree-reassocโ ๐ณ Performs reassociation on trees ๐ Enabled by default at-Oand higher โจ-fcode-hoistingโ ๐๏ธ Performs code hoisting. Code hoisting tries to move the evaluation of expressions that get executed on all paths to the function exit as early as possible ๐ซ This is especially useful as a code size optimization, but it often helps code speed too ๐ Enabled by default at-O2and higher ๐-ftree-preโ okay bestie, this one runs partial redundancy elimination (PRE) on trees ๐ณโจ It's on by default at-O2and-O3๐-ftree-partial-preโ makes PRE extra aggressive ๐ค๐ฅ It's on by default at-O3only ๐-ftree-forwpropโ forward propagation on trees, lowkey essential ๐ฆ On by default at-Oand higher.-ftree-freโ full redundancy elimination (FRE) on trees ๐ The tea is that FRE only looks at expressions computed on all paths leading to the redundant computation. It's faster than PRE but catches fewer redundancies, so it's giving speed ๐โโ๏ธ๐จ On by default at-Oand higher.-ftree-phipropโ hoists loads from conditional pointers on trees ๐ง This pass is on by default at-Oand higher.-fhoist-adjacent-loadsโ speculatively hoists loads from both branches of an if-then-else when the loads come from adjacent spots in the same structure and the target architecture has a conditional move instruction ๐ซถ On by default at-O2and higher.-ftree-copy-propโ copy propagation on trees, which clears out unnecessary copy operations ๐งน On by default at-Oand higher.-fipa-pure-constโ discovers which functions are pure or constant ๐ On by default at-Oand higher.-fipa-referenceโ discovers which static variables don't escape the compilation unit ๐ On by default at-Oand higher.-fipa-reference-addressableโ discovers read-only, write-only, and non-addressable static variables ๐ธ On by default at-Oand higher.-fipa-stack-alignmentโ reduces stack alignment on call sites when it's possible ๐ Enabled by default.-fipa-ptaโ interprocedural pointer analysis plus interprocedural modification and reference analysis ๐ง
โ ๏ธ bestie, this one can cause excessive memory and compile-time usage on large compilation units ๐ It is not enabled by default at any optimization level, so you have to ask for it on purpose.
-fipa-profileโ interprocedural profile propagation ๐ Functions called only from cold functions get marked as cold, and functions executed once (such as"cold","noreturn", static constructors or destructors) get identified. Cold functions and loop-less parts of functions executed once then get optimized for size ๐ฅก Enabled by default at-Oand higher.-fipa-modrefโ interprocedural mod/ref analysis ๐ It analyzes the side effects of functions (the memory locations they modify or reference) and unlocks better optimization across the function call boundary ๐ง On by default at-Oand higher.-fipa-cpโ interprocedural constant propagation ๐ It figures out when values passed to functions are constants and optimizes accordingly. If your app passes constants to functions a lot, this can substantially increase performance ๐ On by default at-O2,-Os, and-O3. It's also enabled by-fprofile-useand-fauto-profile.-fipa-cp-cloneโ function cloning to make IPA constant propagation stronger ๐ฏ When enabled, it clones a function 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) ๐ฆ On by default at-O3. It's also enabled by-fprofile-useand-fauto-profile.-fipa-bit-cpโ interprocedural bitwise constant propagation ๐ข On by default at-O2, and by-fprofile-useand-fauto-profile. It requires that-fipa-cpis enabled.-fipa-vrpโ interprocedural propagation of value ranges ๐ On by default at-O2. It requires that-fipa-cpis enabled.-fipa-icfโ Identical Code Folding for functions and read-only variables ๐ช It reduces code size, but it may disturb unwind stacks by swapping a function out for an equivalent one with a different name. It works way better with link-time optimization turned on ๐
Although it behaves similarly to the Gold Linker's ICF optimization, GCC ICF works on different levels, so the optimizations aren't the same. There are equivalences only GCC finds and equivalences only Gold finds ๐ค
On by default at -O2 and -Os.
-flive-patching=levelโ controls GCC's optimizations so the output is suitable for live-patching ๐ฉน
Okay so, if the compiler's optimization uses a function's body (or info pulled from its body) to optimize or change another function, that other function is called an impacted function of the first one. If a function gets patched, its impacted functions should get patched too ๐
The impacted functions are determined by the compiler's interprocedural optimizations. For example, a caller is impacted when a function gets inlined into it, when a function gets cloned and its caller is changed to call the new clone, or when a function's pureness/constness info is extracted to optimize its direct or indirect callers, etc. ๐
Usually, the more IPA optimizations are enabled, the more impacted functions each function has. To keep that number under control and make the list easier to compute, IPA optimizations can be partially enabled at two different levels โจ
The level argument should be one of the following:
inline-cloneโ only enables inlining and cloning optimizations, which includes inlining, cloning, interprocedural scalar replacement of aggregates, and partial inlining. As a result, when patching a function, all its callers and its clones' callers are impacted, so they need to be patched too ๐
-flive-patching=inline-clone disables these optimization flags: -fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment -fipa-modref
inline-only-staticโ only enables inlining of static functions ๐ง As a result, when patching a static function, all its callers are impacted and need to be patched as well.
On top of everything -flive-patching=inline-clone disables, -flive-patching=inline-only-static also disables these flags: -fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp
When -flive-patching is specified without any value, the default value is inline-clone ๐ซถ
This flag is disabled by default ๐ โโ๏ธ
๐ซ Note that-flive-patchingis not supported with link-time optimization (-flto). Don't mix them, bestie.
-fisolate-erroneous-paths-dereferenceโ detects paths that trigger erroneous or undefined behavior from dereferencing a null pointer ๐ณ๏ธ It isolates those paths from the main control flow and turns the statement with the erroneous or undefined behavior into a trap ๐ชค On by default at-O2and higher, and it depends on-fdelete-null-pointer-checksalso being enabled.-fisolate-erroneous-paths-attributeโ detects paths that trigger erroneous or undefined behavior because a null value 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-O2in the future ๐-ftree-sinkโ forward store motion on trees ๐ On by default at-Oand higher.-ftree-bit-ccpโ sparse conditional bit constant propagation on trees, plus pointer alignment info propagation ๐งฉ This pass only operates on local scalar variables. It's enabled by default at-O1and higher, except for-Og๐ It requires that-ftree-ccpis enabled.-ftree-ccpโ sparse conditional constant propagation (CCP) on trees ๐ฏ This pass only operates on local scalar variables and is enabled by default at-Oand higher.-fssa-backpropโ propagates info about uses of a value up the definition chain so the definitions can get simplified ๐ For example, this pass strips sign operations if the sign of a value never matters ๐งผ The flag is enabled by default at-Oand higher.-fssa-phioptโ pattern matching on SSA PHI nodes to optimize conditional code ๐ง This pass is enabled by default at-O1and higher, except for-Og.-ftree-switch-conversionโ converts simple initializations in aswitchinto initializations from a scalar array ๐ On by default at-O2and higher.-ftree-tail-mergeโ looks for identical code sequences, and when it finds them, replaces one with a jump to the other ๐ช This optimization is known as tail merging or cross jumping. It's on by default at-O2and higher. The compilation time in this pass can be limited with themax-tail-merge-comparisonsparameter and themax-tail-merge-iterationsparameter โฑ๏ธ-ftree-dceโ dead code elimination (DCE) on trees ๐๏ธ On by default at-Oand higher.-ftree-builtin-call-dceโ conditional dead code elimination (DCE) for calls to built-in functions that may seterrnobut are otherwise free of side effects ๐งน On by default at-O2and higher, if-Osis not also specified.-ffinite-loopsโ assumes that a loop with an exit will eventually take the exit and won't loop forever ๐ That lets the compiler remove loops that otherwise have no side effects, without treating eventual endless looping as a thing to worry about ๐ค
This option is enabled by default at -O2 for C++ with -std=c++11 or higher.
-ftree-dominator-optsโ a bunch of simple scalar cleanups (constant/copy propagation, redundancy elimination, range propagation, and expression simplification) based on a dominator tree traversal ๐ณ๐ It also performs jump threading, which reduces jumps to jumps ๐งต This flag is enabled by default at-Oand higher.-ftree-dseโ okay so this one does dead store elimination (DSE) on trees ๐ A dead store is a store into a memory location that gets overwritten by a later store with no loads sneaking in between. That first store is literally dead weight, so it can be deleted โจ Enabled by default at-Oand higher ๐ฅ-ftree-chโ loop header copying on trees ๐ฆ It's lowkey iconic because it makes code motion optimizations way more effective, and it saves one jump too ๐ธ Enabled by default at-Oand higher. It is not enabled for-Os, since it usually bloats code size ๐-ftree-loop-optimizeโ loop optimizations on trees ๐ Enabled by default at-Oand higher ๐-ftree-loop-linear,-floop-strip-mine,-floop-blockโ loop nest optimizations, same as-floop-nest-optimize๐ง To actually use this transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure is turned on ๐ ๏ธ-fgraphite-identityโ the identity transformation for graphite ๐ช For every SCoP, GCC builds the polyhedral representation and transforms it back to gimple. With-fgraphite-identityyou can check the costs or benefits of the GIMPLE -> GRAPHITE -> GIMPLE round trip ๐ Some minimal optimizations also happen in the code generator isl, like index splitting and dead code elimination in loops.-floop-nest-optimizeโ the isl based loop nest optimizer ๐ง It's a generic one built on the Pluto optimization algorithms, and it calculates a loop structure tuned for data-locality and parallelism โจ
โ ๏ธ Heads up, bestie: this option is experimental.
-floop-parallelize-allโ uses Graphite data dependence analysis to find loops that can be parallelized ๐งต It parallelizes all the loops that can be analyzed as not containing loop carried dependences, without checking whether parallelizing them is actually profitable ๐ซถ-ftree-coalesce-varsโ when the program leaves SSA form, this tries to cut down on copying by coalescing versions of different user-defined variables, not just compiler temporaries ๐งน In the negated form, this flag prevents SSA coalescing of user variables. Enabled by default if optimization is enabled, and it does very little otherwise ๐
โ ๏ธ This may severely limit your ability to debug an optimized program compiled with -fno-var-tracking-assignments.
-ftree-loop-if-convertโ tries to transform conditional jumps in the innermost loops into branch-less equivalents ๐ The goal is to remove control flow from the innermost loops so the vectorization pass can handle them better. Enabled by default if vectorization is enabled.-ftree-loop-distributionโ loop distribution ๐ฐ This can improve cache performance on big loop bodies and let further loop optimizations, like parallelization or vectorization, take place. For example, this loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
is transformed to:
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
Enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile.
-ftree-loop-distribute-patternsโ distributes loops of patterns that can be code generated as calls to a library ๐ Enabled by default at-O2and higher, and by-fprofile-useand-fauto-profile.
This pass distributes the initialization loops and generates a call to memset zero. For example, this loop:
DO I = 1, N
A(I) = 0
B(I) = A(I) + I
ENDDO
is transformed to:
DO I = 1, N
A(I) = 0
ENDDO
DO I = 1, N
B(I) = A(I) + I
ENDDO
and the initialization loop is turned into a call to memset zero. This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile.
-floop-interchangeโ loop interchange outside of graphite ๐ This can improve cache performance on loop nests and let further loop optimizations, like vectorization, take place. For example, this loop nest:
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
is transformed to:
for (int i = 0; i < N; i++)
for (int k = 0; k < N; k++)
for (int j = 0; j < N; j++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
Enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile.
-floop-unroll-and-jamโ applies unroll and jam transformations on feasible loops ๐ซ In a loop nest, this unrolls the outer loop by some factor and fuses the resulting multiple inner loops. Enabled by default at-O3. It is also enabled by-fprofile-useand-fauto-profile.-ftree-loop-imโ loop invariant motion on trees ๐ This pass only moves the invariants that are hard to handle at RTL level, like function calls and operations that expand to nontrivial sequences of insns. With-funswitch-loopsit also moves the operands of invariant conditions out of the loop, so loop unswitching can use just trivial invariantness analysis. The pass also includes store motion.-ftree-loop-ivcanonโ creates a canonical counter for the number of iterations in loops where figuring that out takes complicated analysis ๐ข Later optimizations can then determine the number easily. It's especially useful alongside unrolling.-ftree-scev-cpropโ performs final value replacement ๐ซ If a variable is modified in a loop so that its value on exit can be figured out from only its initial value and the number of loop iterations, uses of the final value get swapped out for that computation, as long as it's cheap enough. This reduces data dependencies and may allow further simplifications. Enabled by default at-Oand higher.-fivoptsโ induction variable optimizations (strength reduction, induction variable merging and induction variable elimination) on trees ๐งฎ-ftree-parallelize-loops=nโ parallelizes loops by splitting their iteration space to run in n threads ๐งต This is only possible for loops whose iterations are independent and can be arbitrarily reordered. The optimization is only profitable on multiprocessor machines, and only for CPU-intensive loops rather than ones constrained by things like memory bandwidth. This option implies-pthread, so it's only supported on targets that have support for-pthread.-ftree-ptaโ function-local points-to analysis on trees ๐ฏ Enabled by default at-O1and higher, except for-Og.-ftree-sraโ scalar replacement of aggregates ๐ฌ This pass swaps structure references for scalars so structures don't get committed to memory too early. Enabled by default at-O1and higher, except for-Og.-fstore-mergingโ merges narrow stores to consecutive memory addresses ๐งฉ It combines contiguous stores of immediate values that are narrower than a word into fewer, wider stores, cutting down on the number of instructions. Enabled by default at-O2and higher as well as-Os.-ftree-terโ temporary expression replacement during theSSA->normalphase ๐ช Single use/single def temporaries get replaced at their use location with their defining expression. This results in non-GIMPLE code, but it gives the expanders much more complex trees to work on, which leads to better RTL generation. Enabled by default at-Oand higher.-ftree-slsrโ straight-line strength reduction on trees ๐ It recognizes related expressions involving multiplications and replaces them with less expensive calculations when possible. Enabled by default at-Oand higher.-ftree-vectorizeโ vectorization on trees ๐ This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified.-ftree-loop-vectorizeโ loop vectorization on trees ๐ Enabled by default at-O3and by-ftree-vectorize,-fprofile-use, and-fauto-profile.-ftree-slp-vectorizeโ basic block vectorization on trees ๐ Enabled by default at-O3and by-ftree-vectorize,-fprofile-use, and-fauto-profile.-fvect-cost-model=modelโ alters the cost model used for vectorization ๐ฐ The model argument should be one ofunlimited,dynamic,cheaporvery-cheap.unlimitedโ the vectorized code path is assumed to be profitable ๐dynamicโ a runtime check guards the vectorized code path, so it only runs for iteration counts that will likely execute faster than the original scalar loop ๐โโ๏ธcheapโ disables vectorization of loops where doing so would be cost prohibitive, for example because of required runtime checks for data dependence or alignment, but otherwise it's the same asdynamic๐ซงvery-cheapโ only allows vectorization if the vector code would entirely replace the scalar code being vectorized. For example, if each iteration of a vectorized loop could only handle exactly four iterations of the scalar loop, thevery-cheapmodel would only allow vectorization 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โ alters the cost model used for vectorization of loops marked with the OpenMPsimddirective ๐ซง The model argument should be one ofunlimited,dynamic,cheap. All values of model have the same meaning as described in-fvect-cost-model, and by default a cost model defined with-fvect-cost-modelis used.-ftree-vrpโ okay so this one is a whole vibe ๐ It performs Value Range Propagation on trees. It's like constant propagation's cooler cousin, because instead of tracking single values, it tracks ranges of values โจ That lets the optimizers yeet unnecessary range checks like array bound checks and null pointer checks. It's enabled by default at-O2and higher.
Null pointer check elimination is only done if -fdelete-null-pointer-checks is enabled, so don't forget that one, bestie ๐
-fsplit-pathsโ this splits paths leading to loop backedges, and it's giving main character energy for two reasons ๐ It can improve dead code elimination and common subexpression elimination. It's enabled by default at-O3and above. ๐ฅ-fsplit-ivs-in-unrollerโ enables expressing the values of induction variables in later iterations of the unrolled loop using the value from the first iteration. This breaks long dependency chains, which means better efficiency for the scheduling passes ๐ฆ
Ngl, a combination of -fweb and CSE is often enough to get the same effect ๐ซถ However, that's not reliable when the loop body is more complicated than a single basic block. It also doesn't work at all on some architectures 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 result in superior code ๐
This one is enabled by default for PowerPC targets, but disabled by default otherwise.
-fpartial-inliningโ inlines parts of functions ๐ง This option only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functions.
Enabled at levels -O2, -O3, -Os. ๐ธ
-fpredictive-commoningโ performs predictive commoning, which is basically reusing computations (especially memory loads and stores) from previous iterations of loops. It's giving efficiency ๐
This option is enabled at level -O3. It's also enabled by -fprofile-use and -fauto-profile. ๐
-fprefetch-loop-arraysโ if the target machine supports it, the compiler generates instructions to prefetch memory, which can boost loops that access large arrays ๐
Honestly this one is a gamble ๐ฒ It may generate better or worse code, and the results are highly dependent on the structure of loops in your source code.
Disabled at level -Os. ๐
-fno-printf-return-valueโ do not substitute constants for the known return value of formatted output functions like "sprintf", "snprintf", "vsprintf", and "vsnprintf" (but not "printf" or "fprintf"). This is iconic because GCC can optimize or even eliminate branches based on the known return value of these functions, as long as the arguments are constant or known to be in a range that makes the exact return value possible ๐ง
Here's the example, and it's so good ๐ค When -fprintf-return-value is in effect, both the branch and the body of the "if" statement (but not the call to "snprint") can be optimized away when "i" is a 32-bit or smaller integer, because the return value is guaranteed to be at most 8.
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations and yields the best results with -O2 and above. It works in tandem with the -Wformat-overflow and -Wformat-truncation options. โจ The -fprintf-return-value option is enabled by default. ๐ซถ
-fno-peephole,-fno-peephole2โ these disable any machine-specific peephole optimizations. The difference between them is in how they're implemented in the compiler, so some targets use one, some use the other, and a few use both ๐ฆ
-fpeephole is enabled by default. -fpeephole2 is enabled at levels -O2, -O3, -Os. ๐
-fno-guess-branch-probabilityโ do not guess branch probabilities using heuristics. Lowkey a niche one, but iykyk ๐
GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (-fprofile-arcs). These heuristics are based on the control flow graph. If some branch probabilities are specified by __builtin_expect, then the heuristics guess the probabilities for the rest of the control flow graph, taking the __builtin_expect info into account. The interactions between the heuristics and __builtin_expect can get complex, so sometimes it's useful to disable the heuristics so the effects of __builtin_expect are easier to understand ๐ง
You can also specify the expected probability of an expression with the __builtin_expect_with_probability built-in function. ๐ฎ
The default is -fguess-branch-probability at levels -O, -O2, -O3, -Os. ๐
-freorder-blocksโ reorders basic blocks in the compiled function to reduce the number of taken branches and improve code locality ๐ธ
Enabled at levels -O, -O2, -O3, -Os.
-freorder-blocks-algorithm=algorithmโ uses the specified algorithm for basic block reordering. Thealgorithmargument can besimple, which doesn't increase code size (except sometimes because of secondary effects like alignment), orstc, the "software trace cache" algorithm.stctries to put all the often executed code together, minimizing the number of branches executed by making extra copies of code ๐
The default is simple at levels -O, -Os, and stc at levels -O2, -O3. ๐
-freorder-blocks-and-partitionโ in addition to reordering basic blocks to reduce taken branches, this one partitions hot and cold basic blocks into separate sections of the assembly and.ofiles, to improve paging and cache locality performance ๐ง
This optimization is automatically turned off in the presence of exception handling or unwind tables (on targets using setjump/longjump or a target specific scheme), for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections. ๐
When -fsplit-stack is used, this option isn't enabled by default (to avoid linker errors), but it may be enabled 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 is done with special subsections,.text.hotfor the most frequently executed functions and.text.unlikelyfor unlikely executed functions. The reordering is done by the linker, so the object file format must support named sections and the linker must place them in a reasonable way ๐ซถ
This option isn't effective unless you either provide profile feedback (see -fprofile-arcs for details) or manually annotate functions with hot or cold attributes. ๐
Enabled at levels -O2, -O3, -Os. โจ
-fstrict-aliasingโ this lets the compiler assume the strictest aliasing rules that apply to the language being compiled. For C (and C++), it activates optimizations based on the type of expressions ๐ง An object of one type is assumed to never reside at the same address as an object of a different type, unless the types are almost the same. For example, anunsigned intcan alias anint, but not avoid*or adouble. 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;
}
Type-punning, which is reading from a different union member than the one most recently written to, is super common ๐ Even with -fstrict-aliasing, type-punning is allowed, provided 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 memory by taking the address, casting the resulting pointer, and dereferencing the result has undefined behavior, even if the cast uses a union type. Undefined behavior is not the vibe ๐ 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. ๐
-falign-functions,-falign-functions=n,-falign-functions=n:m,-falign-functions=n:m:n2,-falign-functions=n:m:n2:m2โ this aligns the start of functions to the next power-of-two greater than or equal ton, skipping up tom-1bytes ๐ฆ That way, at least the firstmbytes of the function can be fetched by the CPU without crossing ann-byte alignment boundary. Ifmisn't specified, it defaults ton. ๐ง
Here are some examples that are literally so satisfying โจ -falign-functions=32 aligns functions to the next 32-byte boundary. -falign-functions=24 aligns to the next 32-byte boundary only if this can be done by skipping 23 bytes or less. -falign-functions=32:7 aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less.
The second pair of n2:m2 values lets you specify a secondary alignment. -falign-functions=64:7:32:3 aligns to the next 64-byte boundary if this can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if this can be done by skipping 2 bytes or less. If m2 isn't specified, it defaults to n2. ๐
Some assemblers only support this flag when n is a power of two. In that case, it gets rounded up. ๐
-fno-align-functions and -falign-functions=1 are equivalent and mean that functions are not aligned. ๐ธ
If n isn't specified or is zero, the compiler uses a machine-dependent default. The maximum allowed n option value is 65536. ๐ฅ
Enabled at levels -O2, -O3. โจ
-flimit-function-alignmentโ if this option is enabled, the compiler tries to avoid unnecessarily overaligning functions ๐ซถ It attempts to instruct the assembler to align by the amount specified by-falign-functions, but not to skip more bytes than the size of the function. ๐-falign-labels,-falign-labels=n,-falign-labels=n:m,-falign-labels=n:m:n2,-falign-labels=n:m:n2:m2โ aligns all branch targets to a power-of-two boundary ๐ง
Okay so the parameters for this one are basically the same vibe as -falign-functions ๐
. -fno-align-labels and -falign-labels=1 are equivalent, bestie, and both mean labels just don't get aligned ๐
If -falign-loops or -falign-jumps apply and are bigger than this value, their values win instead โจ
If n isn't specified or is zero, GCC uses a machine-dependent default, which is very likely 1, aka no alignment at all ๐ซถ The maximum allowed n value is 65536.
Enabled at levels -O2, -O3.
๐ฆ -falign-loops
-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 bunch of times, the extra cost of the dummy padding instructions is totally worth it ๐
If -falign-labels is bigger than this value, its value gets used instead.
The parameters work the same way as -falign-functions. -fno-align-loops and -falign-loops=1 are equivalent and mean loops are not aligned. The maximum allowed n value is 65536.
If n isn't specified or is zero, GCC uses a machine-dependent default.
Enabled at levels -O2, -O3.
๐ธ -falign-jumps
-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 have to be executed, so it's giving efficiency ๐ง
If -falign-labels is bigger than this value, its value gets used instead.
The parameters are analogous to -falign-functions. -fno-align-jumps and -falign-jumps=1 are equivalent and mean that loops are not aligned.
If n isn't specified or is zero, GCC uses a machine-dependent default. The maximum allowed n value is 65536.
Enabled at levels -O2, -O3.
๐
-fno-allocation-dce
Do not remove unused C++ allocations during dead code elimination. Keep those allocations, babe ๐ โโ๏ธ
โก -fallow-store-data-races
This 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 does not affect optimization of local data. It's only safe to use this if you know global data won't be touched by multiple threads ๐ญ
Examples of what this unlocks include hoisting or if-conversions that might cause a value already in memory to be rewritten with that same value. That rewrite is totally fine in a single-threaded context, but can be unsafe with multiple threads. Also, on some processors, if-conversions might be required to enable vectorization.
Enabled at level -Ofast.
โ ๏ธ Only use this if global data is never accessed by multiple threads. Otherwise you can get data races, and that's a real mess, not a cute one ๐
๐ -funit-at-a-time
This option is only here for compatibility reasons. -funit-at-a-time does absolutely nothing, while -fno-unit-at-a-time implies -fno-toplevel-reorder and -fno-section-anchors.
Enabled by default.
๐ -fno-toplevel-reorder
Does not reorder top-level functions, variables, and asm statements. They get output in the same order they appear in the input file. When this is 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 whenever possible ๐
-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested. Also, -fno-toplevel-reorder implies -fno-section-anchors.
๐ธ๏ธ -fweb
Constructs webs, as commonly used for register allocation purposes, and assigns 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. Heads up though: it can make debugging impossible, since variables no longer stay in a "home register" ๐
Enabled by default with -funroll-loops.
๐ -fwhole-program
Assumes the current compilation unit is the whole program being compiled. All public functions and variables, except main and those merged by the attribute externally_visible, become static functions. That means interprocedural optimizers can go way harder on them โจ
โ ๏ธ Don't use this together with -flto. Relying on a linker plugin gives safer and more precise information instead.
๐ -flto[=n]
This runs the standard link-time optimizer. When it's invoked with source code, it generates GIMPLE (one of GCC's internal representations) and writes it into special ELF sections in the object file. When the object files get linked together, all the function bodies are read back from those ELF sections and instantiated as if they were part of the same translation unit. Iconic behavior honestly ๐ฅ
To use the link-time optimizer, you need -flto and your optimization options at compile time and during the final link. It's recommended that you compile every file in the same link with the same options, and 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 the GIMPLE bytecode from foo.o and bar.o, merges the two files into one internal image, and compiles the result as usual. Since both are merged into a single image, all the interprocedural analyses and optimizations in GCC work across the two files as if they were one. So, for example, the inliner can inline functions in bar.o into functions in foo.o and vice-versa ๐ฆ
Another (simpler) way to enable link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
That generates bytecode for foo.c and bar.c, merges them into a single GIMPLE representation, and optimizes them as usual to produce myprog.
The important thing to remember: to enable link-time optimizations, you need to use the GCC driver to perform the link step. GCC automatically performs link-time optimization if any of the objects involved were compiled with the -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 need to make certain whole program assumptions. The compiler needs to know which functions and variables can be accessed by libraries and runtime outside the link-time optimized unit. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes information to the compiler about used and externally visible symbols. When the linker plugin isn't available, -fwhole-program should be used so the compiler can make these assumptions, which leads to more aggressive optimization decisions.
When a file is compiled with -flto without -fuse-linker-plugin, the generated object file is larger than a regular one, because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). This means object files with LTO information can be linked as normal object files. If -fno-lto is passed to the linker, no interprocedural optimizations are applied. Note that when -fno-fat-lto-objects is enabled, the compile stage is faster, but you cannot perform a regular, non-LTO link on them ๐ญ
When producing the final binary, GCC only applies link-time optimizations to files that contain bytecode. So you can mix and match object files and libraries with GIMPLE bytecodes and final object code. GCC automatically selects which files to optimize in LTO mode and which files to link without further processing ๐ซถ
Generally, options specified at link time override those specified at compile time, although in some cases GCC tries to infer link-time options from the settings used to compile the input files.
If you don't specify an optimization level option -O at link time, GCC uses the highest optimization level used when compiling the object files. It's generally ineffective to specify an optimization level only at link time and not at compile time, for two reasons. First, compiling without optimization suppresses compiler passes that gather information needed for effective optimization at link time. Second, some early optimization passes can only be performed at compile time, not at link time.
There are some code generation flags that GCC preserves when generating bytecodes, since they need to be used during the final link. Right now, the following options and their settings are taken from the first object file that explicitly specifies them: -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm and all the -m target flags.
The following options -fPIC, -fpic, -fpie and -fPIE are combined based on this scheme:
B<-fPIC> + B<-fpic> = B<-fpic>
B<-fPIC> + B<-fno-pic> = B<-fno-pic>
B<-fpic/-fPIC> + (no option) = (no option)
B<-fPIC> + B<-fPIE> = B<-fPIE>
B<-fpic> + B<-fPIE> = B<-fpie>
B<-fPIC/-fpic> + B<-fpie> = B<-fpie>
Certain ABI-changing flags have to match across all compilation units. Trying to override them at link time with a conflicting value gets ignored. This includes options like -freg-struct-return and -fpcc-struct-return ๐
โโ๏ธ
Other options, like -ffp-contract, -fno-strict-overflow, -fwrapv, -fno-trapv or -fno-strict-aliasing, get passed through to the link stage and merged conservatively for conflicting translation units. Specifically, -fno-strict-overflow, -fwrapv and -fno-trapv take precedence, and for example -ffp-contract=off takes precedence over -ffp-contract=fast. You can override them at link time ๐
Okay so the diagnostic flags like -Wstringop-overflow get passed through to the link stage ๐, and their setting matches the compile step at function granularity โจ. This only really matters for diagnostics emitted during optimization, ngl. Bestie, watch out: code transforms like inlining can cause warnings to get enabled or disabled for regions of code that aren't consistent with the setting at compile time ๐.
If you need to pass options to the assembler with -Wa or -Xassembler ๐ง, you either compile those translation units with -fno-lto, or you consistently use the same assembler options on every translation unit ๐ซถ. You can also specify assembler options at LTO link time instead, periodt.
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 generation enabled, the link turns debug info generation on too ๐. Fancy debug settings like the dwarf level -gdwarf-5 need to be explicitly repeated on the linker command line, and mixing different settings across translation units is discouraged, not gonna lie ๐.
If LTO runs into objects with C linkage declared with incompatible types in separate translation units being linked together (undefined behavior according to ISO C99 6.2.7) ๐ญ, a non-fatal diagnostic may be issued. The behavior is still undefined at run time, so no vibes-based fixes allowed ๐. Similar diagnostics may be raised for other languages too.
Another LTO flex is that you can apply interprocedural optimizations to files written in different languages ๐:
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice the final link is done with g++ to get the C++ runtime libraries, and -lgfortran is added to get the Fortran runtime libraries ๐. In general, when mixing 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, say libfoo.a, you can extract and use them in an LTO link as long as you're using a linker with plugin support ๐ฆ. To make static libraries that are LTO-ready, use gcc-ar and gcc-ranlib instead of ar and ranlib, and use gcc-nm to show the symbols of object files with GIMPLE bytecode ๐ง. Those commands require that ar, ranlib and nm have been compiled with plugin support, so double-check that first ๐. At link time, use -fuse-linker-plugin so the library joins the LTO optimization party:
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin enabled, the linker extracts the needed GIMPLE files from libfoo.a and passes them on to the running GCC, where they become part of the aggregated GIMPLE image to be optimized โจ.
If you're not using a linker with plugin support and/or you don't enable the linker plugin, the objects inside libfoo.a still get extracted and linked as usual, but they just don't participate in the LTO optimization process ๐. To make a static library suitable for both LTO optimization and usual linkage, compile its object files with -flto -ffat-lto-objects ๐ซถ.
Link-time optimizations don't need the whole program present to operate ๐ธ. If the program doesn't require any symbols to be exported, you can combine -flto and -fwhole-program so the interprocedural optimizers can use more aggressive assumptions, which may lead to improved optimization opportunities ๐ฅ. Use of -fwhole-program isn't needed 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 in one version of GCC won't work with an older or newer version of GCC ๐ .
Link-time optimization doesn't work well with debugging information generation on systems other than those using a combination 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 utilizing an installed make program ๐โโ๏ธ. The environment variable MAKE may be used to override the program used.
You can also use -flto=jobserver to let GNU make's job server mode decide the number of parallel jobs ๐งต. This is super useful when the Makefile calling GCC is already executing in parallel. You must prepend a + to the command recipe in the parent Makefile for this to work. This option likely only works if MAKE is GNU make. Even without the option value, GCC tries to automatically detect a running GNU make job server ๐ต๏ธโโ๏ธ.
Use -flto=auto to use GNU make's job server if it's available, or otherwise fall back to autodetecting the number of CPU threads in your system โก.
-flto-partition=algโ picks the partitioning algorithm the link-time optimizer uses ๐งฉ. Your options are1to1(mirrors the original source files),balanced(equally sized chunks whenever possible), ormax(a brand new partition for every symbol where possible). Specifyingnoneturns partitioning and streaming off completely ๐ซ. The default isbalanced.1to1can be used as a workaround for various code ordering issues, butmaxpartitioning is intended for internal testing only ๐งช. The valueonespecifies that exactly one partition should be used, whilenonebypasses partitioning and runs the link-time optimization step directly from the WPA phase ๐ฌ.-flto-compression-level=nโ sets how squished the intermediate language gets when it's written into LTO object files ๐๏ธ. It's only meaningful with LTO mode (-flto). GCC supports two LTO compression algorithms: forzstd, valid values run from0(no compression) to19(maximum compression), whilezlibsupports values from0to9๐. Values outside this range get clamped to either the minimum or maximum of the supported values. If the option isn't given, a default balanced compression setting is used ๐.-fuse-linker-pluginโ enables the use of a linker plugin during link-time optimization ๐. This relies on plugin support in the linker, which is available ingoldor in GNU ld 2.21 or newer. It enables extraction of object files with GIMPLE bytecode out of library archives, which improves optimization quality by exposing more code to the link-time optimizer ๐. That information specifies which symbols can be accessed externally (by non-LTO objects or during dynamic linking) ๐. Code quality improvements on binaries (and shared libraries that use hidden visibility) are similar to-fwhole-program. See-fltofor a description of this flag's effect and how to use it ๐ฆ. This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker that supports plugins (GNU ld 2.21 or newer, or gold) ๐.-ffat-lto-objectsโ fat LTO objects are object files that contain both the intermediate language and the object code ๐ฑ, which makes them usable for both LTO linking and normal linking ๐. This option is only effective when compiling with-flto, and it's ignored at link time.-fno-fat-lto-objectsimproves compilation time over plain LTO, but requires the complete toolchain to be aware of LTO ๐ ๏ธ. It requires a linker with plugin support for basic functionality. Additionally,nm,arandranlibneed to support linker plugins to allow a full-featured build environment (one capable of building static libraries and so on). GCC provides thegcc-ar,gcc-nmandgcc-ranlibwrappers to pass the right options to these tools, and with non-fat LTO, makefiles need to be modified to use them ๐ง. Modern binutils provide a plugin auto-load mechanism, and installing the linker plugin into$libdir/bfd-pluginshas the same effect as using the command wrappers (gcc-ar,gcc-nmandgcc-ranlib) โจ. The default is-fno-fat-lto-objectson targets with linker plugin support ๐.-fcompare-elimโ after register allocation and post-register-allocation instruction splitting, GCC hunts down arithmetic instructions that compute processor flags similar to a comparison based on that arithmetic ๐. If possible, it wipes out 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-O,-O2,-O3,-Os.-fcprop-registersโ after register allocation and post-register-allocation instruction splitting, runs a copy-propagation pass to try to reduce scheduling dependencies and occasionally eliminate the copy ๐ช. Enabled at levels-O,-O2,-O3,-Os.-fprofile-correctionโ profiles collected using an instrumented binary for multi-threaded programs can be inconsistent because of missed counter updates ๐ต. When this option is specified, GCC uses heuristics to correct or smooth out those inconsistencies โจ. By default, GCC emits an error message when an inconsistent profile is detected ๐จ. This option is enabled by-fauto-profile.-fprofile-partial-trainingโ with"-fprofile-use", all portions of programs not executed during the train run are optimized aggressively for size rather than speed ๐ฆ. Sometimes it's not practical to train all possible hot paths in the program (for example, a program may contain functions specific to a given hardware, and training may not cover every hardware configuration the program runs on ๐ฅ๏ธ). With"-fprofile-partial-training", profile feedback is ignored for all functions not executed during the train run, so they're optimized as if they were compiled without profile feedback ๐งธ. This leads to better performance when the train run isn't representative, but it also leads to significantly bigger code ๐.-fprofile-use,-fprofile-use=pathโ enables profile feedback-directed optimizations, and the following optimizations, many of which are generally only profitable when profile feedback is available ๐ฅ:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Okay so that's the rest of the crew that rides along with -fprofile-use ๐
โจ
Before you can use this option, you must first generate profiling information. No skipping this step, bestie ๐ฅบ
By default, GCC emits an error message if the feedback profiles don't match the source code ๐จ You can downgrade that error into a warning with -Wno-error=coverage-mismatch. Lowkey, though, this might leave you with poorly optimized code, so be careful ๐ Also by default, GCC throws a warning if the feedback profiles don't exist at all (see -Wmissing-profile) ๐
If you give it a path, GCC goes looking in that path for the profile feedback data files. See -fprofile-dir ๐๏ธ
-fauto-profile,-fauto-profile=pathโ Turns on sampling-based feedback-directed optimizations, plus a whole squad of optimizations that are mostly worth it when profile feedback is available ๐ฆ Here's the lineup:
-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 holding AutoFDO profile info. If you leave it off, 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/ โจ
Here's the vibe:
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Next up, use the create_gcov tool to turn that raw profile data into something GCC can actually read ๐ฅ You also have to hand this tool the unstripped binary for your program, so don't strip it yet, bestie. See https://github.com/google/autofdo ๐ง
Here's how that looks:
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
The following options control compiler behavior regarding floating-point arithmetic. These options are a total trade-off between speed and correctness ๐ All of them must be specifically enabled. Nothing sneaks on without you asking, periodt ๐
-ffloat-storeโ Don't keep floating-point variables in registers, and block any other options that might change whether a floating-point value is pulled from a register or from memory ๐ This stops the undesirable excess precision you get on machines like the 68000, where the floating registers (of the 68881) keep more precision than a "double" is supposed to have. Similarly for the x86 architecture ๐ซถ For most programs that extra precision is all upside, but a few programs depend on the exact definition of IEEE floating point. For those, use-ffloat-storeafter modifying them to store all the pertinent intermediate computations into variables.-fexcess-precision=styleโ This gives you more control over excess precision on machines where floating-point ops happen in a format with more precision or range than the IEEE standard and interchange floating-point types ๐- By default,
-fexcess-precision=fastis in effect. That means ops might run at a wider precision than the types in your source if it makes the code faster, and it's unpredictable when rounding to your source types actually happens ๐ญ - When compiling C, if
-fexcess-precision=standardis specified, excess precision follows the rules in ISO C99. Casts and assignments both 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=standardis not 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=fastall at once ๐ It also causes the preprocessor macro__FAST_MATH__to be defined โจ
This option is not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of these specifications ๐
-fno-math-errnoโ Don't seterrnoafter calling math functions that are executed with a single instruction, e.g.,sqrt๐ง A program that relies on IEEE exceptions for math error handling might want this for speed while keeping IEEE arithmetic compatibility.
This option is not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of these specifications.
- The default is
-fmath-errno. - On Darwin systems, the math library never sets
errno. So there's no reason for the compiler to consider that it might, and-fno-math-errnois the default there ๐
-funsafe-math-optimizationsโ Allows optimizations for floating-point arithmetic that (a) assume 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 other similar optimizations.
This option is not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of these specifications.
- It enables
-fno-signed-zeros,-fno-trapping-math,-fassociative-mathand-freciprocal-math. - The default is
-fno-unsafe-math-optimizations.
-fassociative-mathโ Allows re-association of operands in series of floating-point operations ๐ This violates the ISO C and C++ language 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. That means 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. - 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.
- This option requires that both
-freciprocal-mathโ Lets the reciprocal of a value be used instead of dividing by the value, if that enables optimizations โ For example,x / ycan be replaced withx * (1/y), which is handy if(1/y)is subject to common subexpression elimination. Heads up: this loses precision and increases the number of flops operating on the value.- The default is
-fno-reciprocal-math.
- The default is
-ffinite-math-onlyโ Allows optimizations for floating-point arithmetic that assume arguments and results are not NaNs or +-Infs ๐ข
This option is not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of these specifications.
- The default is
-fno-finite-math-only.
-fno-signed-zerosโ Allows optimizations for floating-point arithmetic that ignore the signedness of zero 0๏ธโฃ IEEE arithmetic specifies the behavior of distinct+0.0and-0.0values, which then prohibits simplifying expressions likex+0.0or0.0*x(even with-ffinite-math-only). This option implies that the sign of a zero result isn't significant.- The default is
-fsigned-zeros.
- The default is
-fno-trapping-mathโ Compiles code assuming floating-point operations cannot generate user-visible traps ๐ชค These traps include division by zero, overflow, underflow, inexact result and invalid operation. This option requires that-fno-signaling-nansbe in effect. Setting it may allow faster code if you rely on "non-stop" IEEE arithmetic, for example.
This option should never be turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
- The default is
-ftrapping-math.
-frounding-mathโ Disables transformations and optimizations that assume the default floating-point rounding behavior ๐ฒ That default is round-to-zero for all floating-point to integer conversions, and round-to-nearest for all other arithmetic truncations. Specify this for programs that change the FP rounding mode dynamically, or that may be executed with a non-default rounding mode. It also disables constant folding of floating-point expressions at compile time (which may be affected by rounding mode) and arithmetic transformations that are unsafe in the presence of sign-dependent rounding modes.- The default is
-fno-rounding-math.
- The default is
This option is experimental and does not currently guarantee to disable all GCC optimizations that are affected by rounding mode. Future versions of GCC may provide finer control of this setting using C99'sFENV_ACCESSpragma. This command-line option will be used to specify the default state forFENV_ACCESS๐งโโ๏ธ
-fsignaling-nansโ okay so this one is for code that assumes IEEE signaling NaNs can cause user-visible traps during floating-point operations ๐ฅ. Turning it on tells GCC to skip optimizations that might change how many exceptions show up with signaling NaNs ๐. It also implies-ftrapping-mathโจ.- This option defines the preprocessor macro
__SUPPORT_SNAN__๐. - The default is
-fno-signaling-nans๐ซถ. - ngl, this one is still experimental, and it does NOT currently guarantee that every GCC optimization affecting signaling NaN behavior gets switched off ๐ญ.
- This option defines the preprocessor macro
-fno-fp-int-builtin-inexactโ bestie, this stops the built-in functionsceil,floor,roundandtrunc(plus theirfloatandlong doubleversions) from generating code that raises theinexactfloating-point exception for noninteger arguments ๐ฆ. ISO C99 and C11 let these functions raiseinexact, but ISO/IEC TS 18661-1:2014, the C bindings to IEEE 754-2008 as integrated into ISO C2X, does not ๐.- The default is
-ffp-int-builtin-inexact, which allows the exception to be 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 the functions end up calling a library function, theinexactexception may still be raised if that library doesn't follow TS 18661 ๐ค.
- The default is
-fsingle-precision-constantโ main character move: floating-point constants get treated as single precision instead of being quietly converted to double-precision constants ๐.-fcx-limited-rangeโ when this is on, it's basically saying a range reduction step isn't needed for complex division ๐. There's also no checking for whether a complex multiplication or division comes out asNaN + I*NaN, so no rescue attempt in that case ๐.- The default is
-fno-cx-limited-range, but-ffast-mathturns it on โจ. - This option controls the default setting of the ISO C99
CX_LIMITED_RANGEpragma ๐ง. Lowkey the wildest part: it applies to all languages ๐.
- The default is
-fcx-fortran-rulesโ complex multiplication and division follow Fortran rules ๐. Range reduction happens as part of complex division, but again there's no checking for aNaN + I*NaNresult and no rescue attempt ๐.- The default is
-fno-cx-fortran-rules๐ซถ.
- The default is
The following options control optimizations that may improve performance, but are not enabled by any -O options. This section includes experimental options that may produce broken code ๐งชโ ๏ธ. Use these with caution, bestie ๐ซถ.
-fbranch-probabilitiesโ okay this one is so clever ๐ง . After running a program compiled with-fprofile-arcs, you can compile it a second time with-fbranch-probabilitiesto improve optimizations based on how many times each branch was taken ๐.- When a program compiled with
-fprofile-arcsexits, it saves arc execution counts to a file calledsourcename.gcdafor each source file ๐. - That data is super dependent on the structure of the generated code, so you MUST use the same source code and the same optimization options for both compilations ๐ญ.
- With
-fbranch-probabilities, GCC puts aREG_BR_PROBnote on eachJUMP_INSNandCALL_INSN๐. These can be used to improve optimization. Right now they're only used in one place: inreorg.c, instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to exactly determine which path is taken more often ๐ฅ. - Enabled by
-fprofile-useand-fauto-profileโจ.
- When a program compiled with
-fprofile-valuesโ if you combine it with-fprofile-arcs, it adds code that gathers some data about values of expressions in the program ๐ฆ.- With
-fbranch-probabilities, it reads back that data and uses it for optimizations ๐ . - Enabled by
-fprofile-generate,-fprofile-use, and-fauto-profile๐ธ.
- With
-fprofile-reorder-functionsโ function reordering based on profile instrumentation records the first time each function executes, then puts those functions in ascending order ๐ช.- Enabled with
-fprofile-use๐.
- Enabled with
-fvptโ with-fprofile-arcs, this tells the compiler to add code that gathers information about values of expressions ๐.- With
-fbranch-probabilities, it reads that data back and actually performs optimizations based on it ๐ฅ. Right now those optimizations include specializing division operations using what it knows about the value of the denominator โ. - Enabled with
-fprofile-useand-fauto-profileโจ.
- With
-frename-registersโ tries to avoid false dependencies in scheduled code by using registers left over after register allocation ๐. This benefits processors with lots of registers the most ๐ช.- Heads up: depending on the debug information format the target uses, this can make debugging impossible, since variables no longer stay in a "home register" ๐ญ.
- Enabled by default with
-funroll-loops๐.
-fschedule-fusionโ a target-dependent pass over the instruction stream that groups instructions of the same type together ๐งฉ. The target machine can run them more efficiently when they sit next to each other in the instruction flow โก.- Enabled at levels
-O2,-O3,-Os๐ซถ.
- Enabled at levels
-ftracerโ performs tail duplication to enlarge superblock size ๐ฆ. This simplifies the control flow of the function so other optimizations can do a better job ๐ .- Enabled by
-fprofile-useand-fauto-profile๐ธ.
- Enabled by
-funroll-loopsโ unrolls loops whose number of iterations can be figured out at compile time or when the loop is entered ๐. It implies-frerun-cse-after-loop,-fweband-frename-registers๐ง. It also turns on complete loop peeling, meaning loops with a small constant number of iterations get completely removed ๐.- 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 ๐ข. It implies the same options as-funroll-loops๐.-fpeel-loopsโ peels loops that have enough information to show they don't roll much, based on profile feedback or static analysis ๐. It also turns on complete loop peeling, meaning loops with a small constant number of iterations get completely removed ๐ง.- Enabled by
-O3,-fprofile-use, and-fauto-profile๐ฅ.
- Enabled by
-fmove-loop-invariantsโ enables the loop invariant motion pass in the RTL loop optimizer ๐โโ๏ธ.- Enabled at level
-O1and higher, except for-Og๐ .
- Enabled at level
-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๐ธ.
- Enabled by
-funswitch-loopsโ moves branches with loop invariant conditions out of the loop ๐ช. Duplicates of the loop end up on both branches, modified according to the result of the condition ๐ฏโโ๏ธ.- Enabled by
-fprofile-useand-fauto-profile๐ซถ.
- Enabled by
-fversion-loops-for-stridesโ if a loop iterates over an array with a variable stride, GCC creates another version of the loop that assumes the stride is always one ๐ชก. Here's how it looks, bestie:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
This is especially useful for assumed-shape arrays in Fortran, where (for example) it allows better vectorization by assuming contiguous accesses ๐. This flag is enabled by default at -O3 ๐ฅ. It's also enabled by -fprofile-use and -fauto-profile โจ.
-ffunction-sections,-fdata-sectionsโ places each function or data item into its own section in the output file, as long as the target supports arbitrary sections ๐ฆ. The function's name or the data item's name determines the section's name in the output file ๐ท๏ธ.- Use these on systems where the linker can optimize to improve locality of reference in the instruction space. Most systems using the ELF object format have linkers with those optimizations ๐ง . On AIX, the linker rearranges sections (CSECTs) based on the call graph, and the performance impact varies ๐.
- Together with a linker garbage collection (
linker --gc-sectionsoption), these options may lead to smaller statically-linked executables (after stripping) ๐ฅน. - On ELF/DWARF systems, these options do not degrade the quality of the debug information ๐. There could be issues with other object file or debug info formats ๐ค.
- Only use these when there are significant benefits ๐จ. They make the assembler and linker create larger object and executable files, and they're slower too ๐. These options also affect code generation: they prevent the compiler and assembler from using relative locations inside a translation unit, since those locations aren't known until link time ๐งฑ. An example of an optimization this blocks is relaxing calls to short call instructions ๐.
-fstdarg-optโ optimizes the prologue of variadic argument functions based on how those arguments are used ๐ช.- NOTE, bestie: In Ubuntu 14.10 and later versions,
-fstack-protector-strongis enabled by default for C, C++, ObjC, and ObjC++, if none of-fno-stack-protector,-nostdlib, or-ffreestandingare found ๐ก๏ธ๐ .
- NOTE, bestie: In Ubuntu 14.10 and later versions,
-fsection-anchorsโ tries to cut down on symbolic address calculations by using shared "anchor" symbols to address nearby objects ๐ฆ. This can help reduce the number of GOT entries and GOT accesses on some targets ๐ธ.- Say you have the following function
foo:
- Say you have the following function
static int a, b, c;
int foo (void) { return a + b + c; }
It usually calculates the addresses of all three variables. But if you compile it with -fsection-anchors, it accesses the variables from a common anchor point instead ๐งฒ. The effect is similar to this pseudocode (which isn't valid C, so don't copy-paste it ๐):
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
Heads up, bestie: not every target supports this one ๐ญ๐
-fzero-call-used-regs=choiceโ okay, this one is a whole security moment ๐โจ It zeroes the call-used registers when a function returns, which can help mitigate Return-Oriented Programming (ROP) attacks or stop information from leaking out through registers ๐ฆ The possible values ofchoiceare the same as the ones for thezero_call_used_regsattribute, and the default isskip๐ You can also control this for one specific function with the function attributezero_call_used_regs๐--param name=valueโ okay so GCC uses little constants behind the scenes to decide how much optimizing to do ๐ง For example, it won't inline a function that has more than a certain number of instructions. You can tweak some of these on the command line with--param๐ธ Heads up though: the names and what the values mean are tied to the compiler's internals and can change without notice in future releases โ ๏ธ To see the minimal, maximal, and default value of a parameter, use--help=param -Q๐ The value is always an integer, and these names are recognized for all targets:predictable-branch-outcomeโ if a branch is predicted to be taken with a probability lower than this threshold (in percent), it counts as well predictable ๐ฎmax-rtl-if-conversion-insnsโ RTL if-conversion tries to remove conditional branches around a block and swap them for conditionally executed instructions. This sets the max number of instructions in a block that get considered for that. GCC also uses other heuristics to decide whether it's actually worth it ๐คmax-rtl-if-conversion-predictable-costโ the max permissible cost for the sequence if-conversion would generate. It depends on whether the branch is statically determined to be predictable or not. The units match GCC's internalseq_costmetric, and GCC tries to pick a reasonable default using theBRANCH_COSTtarget macro ๐max-crossjump-edgesโ the max number of incoming edges to consider for cross-jumping.-fcrossjumpingruns inO(N^2)in the number of incoming edges to each block, so bigger values mean more aggressive optimization, longer compile times, and probably a small improvement in executable size ๐ขmin-crossjump-insnsโ the min number of instructions that must match at the end of two blocks before cross-jumping happens. This gets ignored when every instruction in the block being cross-jumped from is matched ๐max-grow-copy-bb-insnsโ the max code size expansion factor when copying basic blocks instead of jumping. The expansion is relative to a jump instruction ๐max-goto-duplication-insnsโ the max number of instructions to duplicate into a block that jumps to a computed goto. To avoidO(N^2)behavior in a bunch of passes, GCC factors computed gotos early and unfactors them as late as possible. Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsget unfactored ๐งmax-delay-slot-insn-searchโ the max number of instructions to check when hunting for something to fill a delay slot. Past this arbitrary number the time savings are minimal, so GCC stops searching. Bigger values mean more aggressive optimization and longer compile times, with probably a small win in execution time ๐โโ๏ธmax-delay-slot-live-searchโ when filling delay slots, the max number of instructions to check while looking for a block with valid live register information. Raising this arbitrary number means more aggressive optimization and longer compile times. This parameter should get removed once the delay slot code is rewritten to maintain the control-flow graph ๐ ๏ธmax-gcse-memoryโ the approximate max amount of memory inkBthat can be allocated for global common subexpression elimination. If more memory than that is needed, the optimization just doesn't happen ๐งบmax-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is bigger than this for any expression, RTL PRE inserts or removes the expression and leaves partially redundant computations in the instruction stream ๐ซmax-pending-list-lengthโ the max number of pending dependencies the scheduler allows before it flushes its current state and starts over. Big functions with few branches or calls can make these lists huge, which wastes memory and resources ๐max-modulo-backtrack-attemptsโ the max number of backtrack attempts the scheduler makes when modulo scheduling a loop. Larger values can make compile time blow up exponentially ๐max-inline-insns-singleโ several parameters control the tree inliner, and this one sets the max number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will consider for inlining. It only affects functions declaredinlineand methods implemented in a class declaration (C++) ๐max-inline-insns-autoโ when you use-finline-functions(which is included in-O3), tons of functions that would normally not be considered for inlining get checked. For those, a different and more restrictive limit applies than for functions declaredinline, and that limit is set with--param max-inline-insns-autoโจmax-inline-insns-smallโ the bound applied to calls considered relevant under-finline-small-functions๐ทmax-inline-insns-sizeโ the bound applied to calls that are optimized for size. A small growth might be desirable to set up optimization opportunities that inlining exposes ๐ฏ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 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-insnsanduninlined-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 goes over this threshold (in percent), the function can be inlined no matter the limits set by--param max-inline-insns-singleand--param max-inline-insns-auto๐large-function-insnsโ the limit that defines really large functions. For functions bigger than this after inlining, inlining is constrained by--param large-function-growth. This one mainly exists to avoid extreme compile times caused by the non-linear algorithms the back end uses ๐large-function-growthโ the max growth of a large function caused by inlining, in percent. For example, a value of100limits large function growth to 2.0 times the original size ๐large-unit-insnsโ the limit that defines a large translation unit. Growth caused by inlining into units bigger than this is limited by--param inline-unit-growth. For small units that might be too tight. Picture a unit with function A (inline) and function B that just calls A three times. If B is small compared to A, the unit growth is 300% and that inlining is still totally sane ๐ฐ For really big units full of small inlinable functions, the overall unit growth limit is needed to prevent exponential code size explosion. So for smaller units, the size gets bumped up to--param large-unit-insnsbefore--param inline-unit-growthis applied ๐ซงlazy-modulesโ the max number of C++ module files that can be open at once when lazy loading ๐inline-unit-growthโ the max overall growth of the compilation unit caused by inlining. For example, a value of20limits unit growth to 1.2 times the original size. Cold functions (marked cold with an attribute or by profile feedback) don't count toward the unit size ๐ฅถipa-cp-unit-growthโ the max overall growth of the compilation unit caused by interprocedural constant propagation. For example, a value of10limits unit growth to 1.1 times the original size ๐งipa-cp-large-unit-insnsโ the size at which the IPA-CP pass considers a translation unit large ๐large-stack-frameโ the limit that defines large stack frames. While inlining, the algorithm tries not to grow past this limit too much ๐ฅlarge-stack-frame-growthโ the max growth of large stack frames caused by inlining, in percent. For example, a value of1000limits large stack frame growth to 11 times the original size ๐ชmax-inline-insns-recursiveandmax-inline-insns-recursive-autoโ the max number of instructions an out-of-line copy of a self-recursive inline function can grow into by doing recursive inlining ๐
Okay so the --param max-inline-insns-recursive thing applies to functions declared inline ๐
. For functions that aren't declared inline, recursive inlining only kicks in when -finline-functions (which is included in -O3) is enabled, and then --param max-inline-insns-recursive-auto takes over ๐ฆ.
max-inline-recursive-depth,max-inline-recursive-depth-autoโ This sets the max recursion depth for recursive inlining ๐ธ.--param max-inline-recursive-depthis for functions declared inline, and for functions that aren't,--param max-inline-recursive-depth-autois the one (same-finline-functionsdeal as above) ๐ซถ.min-inline-recursive-probabilityโ Recursive inlining is only worth it for functions that recurse deeply on average ๐. For functions with shallow recursion it can backfire, bloating the prologue or making the function body more complicated for the other optimizers ๐ญ. When profile feedback is around (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 only lets inlining happen for call expressions whose probability is higher than the threshold, given in percent โจ.early-inlining-insnsโ How much growth the early inliner is allowed to make ๐ฑ. Basically it means more inlining for code that has a big abstraction penalty ๐.max-early-inliner-iterationsโ The cap on how many iterations the early inliner runs โญ. This pretty much bounds how many nested indirect calls it can resolve ๐ง. Deeper chains still get handled later, by late inlining ๐.comdat-sharing-probabilityโ The percent chance that C++ inline functions with comdat visibility get shared across multiple compilation units ๐.modref-max-bases,modref-max-refs,modref-max-accessesโ How many base pointers, references, and accesses mod/ref analysis will store for a single function ๐ฅ.modref-max-testsโ The max number of tests the alias oracle can run to tell memory locations apart using mod/ref info ๐ต๏ธโโ๏ธ. This should be bigger than--param modref-max-basesand--param modref-max-refs๐.modref-max-depthโ The max depth of the DFS walk used by modref escape analysis ๐. Setting it to0turns the analysis off completely ๐.modref-max-escape-pointsโ The max number of escape points modref tracks per SSA-name ๐ .profile-func-internal-idโ Controls whether the function's internal id gets 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 forgiving of source changes, like functions getting reordered ๐ฅน.min-vect-loop-boundโ Loops with fewer iterations than this won't get vectorized when-ftree-vectorizeis on ๐ท. The number of iterations after vectorization also has to be greater than this value for vectorization to happen ๐.gcse-cost-distance-ratioโ A scaling factor for figuring out how far GCSE is allowed to move an expression โจ. It's only supported in the code hoisting pass ๐ฆ. The bigger the ratio, the more aggressively simple expressions (ones costing less thangcse-unrestricted-cost) get hoisted ๐. Setting it to0turns off hoisting of simple expressions ๐ โโ๏ธ.gcse-unrestricted-costโ The cost, roughly the cost of one typical machine instruction, at which GCSE stops limiting how far an expression can travel ๐ซ. This is only supported in the code hoisting pass too ๐ซถ. The lower the cost, the more aggressive the hoisting gets ๐. Setting it to0lets every expression travel unrestricted distances ๐.max-hoist-depthโ How deep the search goes in the dominator tree looking for expressions to hoist ๐ณ. It's there to stop the hoisting algorithm from going quadratic ๐. A value of0means no limit on the search, but that can slow down compilation of huge functions ๐ข.max-tail-merge-comparisonsโ The max number of similar basic blocks one block gets compared against during tree tail merging ๐. It exists to avoid quadratic behavior there ๐ .max-tail-merge-iterationsโ The max number of iterations of the pass over the function ๐. It's a limit on compilation time in tree tail merging โฑ๏ธ.store-merging-allow-unalignedโ Lets the store merging pass introduce unaligned stores, but only if that's legal ๐งฉ.max-stores-to-mergeโ The max number of stores the store merging pass will try to combine into wider stores ๐ง.max-store-chains-to-trackโ The max number of store chains tracked at once while trying to merge them into wider stores ๐ชก.max-stores-to-trackโ The max number of stores tracked at once while trying to merge them into wider stores in the store merging pass ๐ฏ.max-unrolled-insnsโ The max number of instructions a loop can have and still get unrolled ๐. If the loop does get unrolled, this value also decides how many times the loop code is unrolled ๐.max-average-unrolled-insnsโ The max number of instructions, weighted by how likely they are to run, that a loop can have and still get unrolled ๐. If it gets unrolled, this parameter also decides how many times the loop code is unrolled ๐ก.max-unroll-timesโ The max number of unrollings for a single loop ๐ญ.max-peeled-insnsโ The max number of instructions a loop can have and still get peeled ๐. If it gets peeled, this parameter also decides how many times the loop code is peeled ๐ซ .max-peel-timesโ The max number of peelings for a single loop ๐ง.max-peel-branchesโ The max number of branches on the hot path through the peeled sequence ๐ถ๏ธ.max-completely-peeled-insnsโ The max number of insns in a completely peeled loop ๐ช.max-completely-peel-timesโ The max number of iterations a loop can have and still be suitable for complete peeling ๐๏ธ.max-completely-peel-loop-nest-depthโ The max depth of a loop nest that's suitable for complete peeling ๐ช.max-unswitch-insnsโ The max number of insns in an unswitched loop ๐ชฉ.max-unswitch-levelโ The max number of branches unswitched in a single loop ๐ข.lim-expensiveโ The minimum cost for an expression to count as expensive in loop invariant motion ๐ธ.min-loop-cond-split-probโ When FDO profile info is available, this is the minimum probability a semi-invariant condition statement needs before it triggers a loop split ๐.iv-consider-all-candidates-boundโ Below this number of induction variable candidates, every candidate gets considered for each use ๐งฎ. Above it, only the most relevant ones get considered, so the time complexity doesn't go quadratic ๐.iv-max-considered-usesโ The induction variable optimizations give up on any loop with more induction variable uses than this ๐.iv-always-prune-cand-set-boundโ If the candidate set is smaller than this, the compiler always tries to strip out unnecessary ivs whenever it adds a new one ๐งน.avg-loop-niterโ The average number of iterations of a loop ๐.dse-max-object-sizeโ The max size, in bytes, of objects tracked bytewise by dead store elimination ๐ฆ. Bigger values can mean bigger compilation times โณ.dse-max-alias-queries-per-storeโ The max number of queries into the alias oracle per store ๐. Bigger values mean bigger compilation times, but they can also remove more dead stores ๐๏ธ.scev-max-expr-sizeโ The bound on how big expressions can be in the scalar evolutions analyzer ๐. Big expressions slow the analyzer down ๐.scev-max-expr-complexityโ The bound on how complex expressions can be in the scalar evolutions analyzer ๐งถ. Complex expressions slow the analyzer down too ๐ฉ.max-tree-if-conversion-phi-argsโ The max number of arguments in a PHI that tree if conversion supports, unless the loop is marked with a simd pragma ๐งฌ.vect-max-version-for-alignment-checksโ The max number of run-time checks allowed when the vectorizer does loop versioning for alignment ๐ก๏ธ.vect-max-version-for-alias-checksโ The max number of run-time checks allowed when the vectorizer does loop versioning for alias ๐ช.vect-max-peeling-for-alignmentโ The max number of loop peels the vectorizer can do to improve access alignment ๐งโโ๏ธ. A value of-1means there's no limit ๐.max-iterations-to-trackโ The max number of loop iterations the brute-force algorithm will try to evaluate when it's figuring out how many iterations a loop runs ๐ฐ๏ธ.hot-bb-count-fractionโ The denominator n of the fraction 1/n of the maximal execution count of a basic block in the whole program. A basic block has to hit at least that much to count as hot ๐ฅ. The default is10000, which means a basic block is hot if its execution count is greater than 1/10000 of the maximal execution count ๐ฅ. A value of0means a basic block is never considered hot ๐ง. This is used in non-LTO mode ๐ .hot-bb-count-ws-permilleโ bestie, this is the "how much of the action counts as popular" dial ๐ It's a number from 0 to 1000 (permilles!) for the most-executed slice of the whole profiled program. A basic block only counts as hot if its execution count lands in that slice. The default is990, so a block is hot if it contributes to the upper990permilles, or99.0%, of the profiled execution of the entire program. Setting it to0means nothing is ever hot ๐ฅ Only used in LTO mode.hot-bb-frequency-fractionโ this one is a fraction,1/n, of the entry block's execution frequency for a function. A basic block in that function has to hit at least that much to be considered hot โจ The default is1000, so a block is hot in a function if it runs more often than1/1000of the entry block's frequency.0means it's never hot, no exceptions ๐unlikely-bb-count-fractionโ the "sus, barely showing up" threshold ๐ซ It's a fraction1/nof the number of profiled runs of the whole program. If a basic block's execution count is below that, it's considered unlikely to run. The default is20, so a block counts as unlikely if it runs in fewer than1/20, or5%, of the program's runs.0means it's always considered unlikely executed ๐max-predicted-iterationsโ the cap on how many loop iterations GCC will guess statically ๐ฎ This matters when one function has a loop with a known bound and another loop with an unknown bound. The known count gets predicted correctly, but the unknown ones average out to roughly10. So the unbounded loop looks artificially cold next to the other one, which is kinda unfair ngl ๐ญbuiltin-expect-probabilityโ controls how likely it is that an expression has the specified value ๐ฏ It takes a percentage, meaning0 ... 100, as input.builtin-string-cmp-inline-lengthโ the max length of a constant string for a builtin string compare call that's allowed to get inlined ๐ง Anything longer stays as a regular call.align-thresholdโ pick a fraction of the maximal execution frequency of a basic block in a function to decide whether that block gets aligned ๐ธalign-loop-iterationsโ a loop that's expected to iterate at least this many times gets aligned ๐ฆtracer-dynamic-coverage,tracer-dynamic-coverage-feedbackโ these two are the bouncers for superblock formation ๐ช Once the given percentage of executed instructions is covered, the tracer stops forming superblocks. This keeps code size from getting totally out of hand ๐
The tracer-dynamic-coverage-feedback parameter only gets used when profile feedback is available. Real profiles are way less balanced than the statically estimated ones, so the threshold can be set to a bigger value ๐
tracer-max-code-growthโ tail duplication stops once code growth hits this percentage ๐ It's kind of an artificial limit, since most of the duplicates get cleaned up later during cross jumping. So you can set it way higher than the code growth you actually want ๐tracer-min-branch-ratioโ reverse growth stops when the reverse probability of the best edge drops below this threshold, given in percent ๐ชtracer-min-branch-probability,tracer-min-branch-probability-feedbackโ forward growth stops if the best edge's probability is lower than this threshold โก๏ธ
Same energy as tracer-dynamic-coverage, there are two versions of this one too. tracer-min-branch-probability-feedback is for compilation with profile feedback, and tracer-min-branch-probability is for compilation without it. The feedback version needs to be more conservative, which means a higher value, so the tracer actually works โญ
stack-clash-protection-guard-sizeโ sets the size of the operating system's stack guard as2raised to num bytes ๐ก๏ธ Higher values can cut down on the number of explicit probes. But if the value is larger than the OS guard, your code is left vulnerable to stack clash style attacks, and that's a big nope ๐จstack-clash-protection-probe-intervalโ stack clash protection probes the stack space as it gets allocated ๐ This param sets the max distance between those probes as2raised to num bytes. Higher values might mean fewer explicit probes, but if the value is bigger than the OS guard, your code becomes vulnerable to stack clash style attacks again ๐ฌmax-cse-path-lengthโ the max number of basic blocks on a path that CSE (common subexpression elimination) considers ๐งญmax-cse-insnsโ the max number of instructions CSE processes before it flushes ๐ฟggc-min-expandโ okay, so GCC has its own garbage collector to manage its memory ๐๏ธโจ This sets the minimum percentage the GC's heap is allowed to grow between collections. Tuning it might speed up compilation, but it has zero effect on code generation, so don't stress ๐ซถ
The default is 30% + 70% * (RAM/1GB), capped at a 100% upper bound when RAM >= 1GB. If getrlimit is available, "RAM" means the smallest of actual RAM and RLIMIT_DATA or RLIMIT_AS. If GCC can't calculate RAM on a platform, it falls back to the 30% lower bound. Setting this and ggc-min-heapsize to zero forces a full collection 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 hit before it even starts bothering to collect garbage ๐งน The first collection happens after the heap grows byggc-min-expand%beyondggc-min-heapsize. Again, tuning this might help compile speed, with no effect on code generation ๐ท
The default is the smaller of RAM/8, RLIMIT_RSS, or a limit that tries to make sure RLIMIT_DATA or RLIMIT_AS don't get exceeded. It has a lower bound of 4096 (four megabytes) and an upper bound of 131072 (128 megabytes). If GCC can't calculate RAM on a platform, the lower bound gets used. Setting this parameter very large effectively disables garbage collection, and setting this and ggc-min-expand to zero causes a full collection at every opportunity ๐
max-reload-search-insnsโ the max number of instructions reload looks backward through for an equivalent register ๐ Higher values mean more aggressive optimization, with compile time going up and 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, with compile time going up and probably slightly better performance.max-sched-ready-insnsโ the max number of ready-to-issue instructions the scheduler considers 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 considered for interblock scheduling ๐งฉmax-pipeline-region-blocksโ the max number of blocks in a region considered for pipelining in the selective scheduler ๐ชmax-sched-region-insnsโ the max number of insns in a region considered for interblock scheduling ๐max-pipeline-region-insnsโ the max number of insns in a region considered for pipelining in the selective scheduler ๐min-spec-probโ the minimum probability, in percents, of reaching a source block for interblock speculative scheduling ๐ฒmax-sched-extend-regions-itersโ the max number of iterations through the CFG to extend regions ๐บ๏ธ A value of0disables region extensions, so that's the off switch ๐max-sched-insn-conflict-delayโ the max conflict delay an insn can have and still be considered for speculative motion ๐sched-spec-prob-cutoffโ the minimal probability of speculation success, in percents, that has to be hit before speculative insns get scheduled โsched-state-edge-prob-cutoffโ the minimum probability an edge needs before the scheduler saves its state across it ๐พsched-mem-true-dep-costโ the minimal distance, in CPU cycles, between a store and a load that target the same memory locations โฑ๏ธselsched-max-lookaheadโ the max size of the lookahead window for selective scheduling ๐ It's basically the depth of search for available instructions ๐selsched-max-sched-timesโ the max number of times an instruction gets scheduled during selective scheduling ๐ This is the limit on how many iterations the instruction can get pipelined through ๐ซselsched-insns-to-renameโ the max number of best instructions in the ready list that the selective scheduler considers for renaming ๐ท๏ธsms-min-scโ the minimum stage count value that the swing modulo scheduler generates ๐ขmax-last-value-rtlโ the max size, measured as the number of RTLs, that the combiner can record in an expression as the last known value of a pseudo register ๐max-combine-insnsโ the max number of instructions the RTL combiner tries to combine at once ๐งinteger-share-limitโ small integer constants can use a shared data structure, which saves the compiler memory and makes it faster ๐ This sets the max value of a shared integer constant ๐ขssp-buffer-sizeโ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectionis used ๐ก๏ธ๐
This default before Ubuntu 10.10 was "8" ๐
Right now it's "4", so the stack protector covers way more functions ๐ก๏ธ
min-size-for-stack-sharingโ the smallest a variable can be to join stack slot sharing when you're not optimizing ๐งmax-jump-thread-duplication-stmtsโ the max number of statements a block can have before it has to be duplicated while threading jumps ๐max-fields-for-field-sensitiveโ the max number of fields in a structure that get the field-sensitive treatment during pointer analysis ๐ฆprefetch-latencyโ an estimate of how many instructions run on average before a prefetch finishes โฑ๏ธ The prefetch distance scales with this number, and bumping it up may mean fewer streams get prefetched (seesimultaneous-prefetches) ๐simultaneous-prefetchesโ the max number of prefetches that can run at the same time ๐โโ๏ธl1-cache-line-sizeโ the size of a cache line in the L1 data cache, in bytes ๐l1-cache-sizeโ the size of the L1 data cache, in kilobytes ๐พl2-cache-sizeโ the size of the L2 data cache, in kilobytes ๐พโจprefetch-dynamic-stridesโ whether the loop array prefetch pass should issue software prefetch hints for non-constant strides ๐ค This can be super helpful sometimes, but a non-constant stride makes it hard to predict when the hints are actually worth it.- Set to
1if prefetch hints should be issued for non-constant strides. - Set to
0if prefetch hints should only be issued for strides that are known to be constant and belowprefetch-minimum-stride.
- Set to
prefetch-minimum-strideโ the minimum constant stride, in bytes, before prefetch hints kick in ๐ฆ If the stride is under this threshold, no prefetch hints get issued.- This one is giving hardware realness ๐ฅ๏ธ Processors with hardware prefetchers can clash with software prefetchers. If the hardware prefetchers have a max stride they can handle, put that number here so the software prefetchers play nice.
- A value of
-1means there's no threshold, so prefetch hints can be issued for any constant stride. - This setting only matters for strides that are known and constant.
loop-interchange-max-num-stmtsโ the max number of statements in a loop that can be interchanged ๐loop-interchange-stride-ratioโ the min ratio between the strides of two loops for an interchange to actually be profitable ๐ธmin-insn-to-prefetch-ratioโ the min ratio of instructions to prefetches needed before prefetching gets enabled in a loop ๐งฎprefetch-min-insn-to-mem-ratioโ the min ratio of instructions to memory references needed before prefetching gets enabled in a loop ๐งuse-canonical-typesโ whether the compiler uses the "canonical" type system ๐ This should always be1, since it's a more efficient internal way of comparing types in C++ and Objective-C++. But if bugs in the canonical type system are causing compile failures, set it to0to turn canonical types off ๐ซswitch-conversion-max-branch-ratioโ switch initialization conversion won't create arrays bigger thanswitch-conversion-max-branch-ratiotimes the number of branches in the switch ๐ขmax-partial-antic-lengthโ 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 source code, the enhanced PRE can run away and eat all the memory on the host machine ๐ This caps the length of those sets so that doesn'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 hits, the innermostrpo-vn-max-loop-depthloops and the outermost loop in the loop nest are value-numbered optimistically, and the remaining ones are not.sccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries we run while hunting for redundancies in loads and stores ๐ If this limit gets 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 this number, only the given number of the most frequently-executed loops form regions for regional register allocation.ira-max-conflict-table-sizeโ IRA has a sophisticated way of compressing the conflict table, but huge functions can still need excessive memory ๐ฉ If a function's conflict table could be bigger than the size in MB given by this parameter, the register allocator switches to a faster, simpler, lower-quality algorithm that doesn't build a pseudo-register conflict table.ira-loop-reserved-regsโ IRA can evaluate more accurate register pressure in loops for decisions about moving loop invariants (see-O3) ๐ฏ This sets how many available registers get reserved for other purposes. The default is the best value found from numerous experiments ๐งชlra-inheritance-ebb-probability-cutoffโ LRA tries to reuse values reloaded into registers in subsequent insns, which is called inheritance ๐ EBB is used as the region for this optimization. The parameter is a minimal fall-through edge probability, in percent, used to add a BB to the inheritance EBB in LRA. The default was chosen from numerous runs of SPEC2000 on x86-64 ๐loop-invariant-max-bbs-in-loopโ loop invariant motion can be super expensive for very large loops, both in compilation time and in compile-time memory ๐ธ Loops with more basic blocks than this parameter won't get loop invariant motion performed on them.loop-max-datarefs-for-datadepsโ building data dependencies is expensive for very large loops ๐ฎโ๐จ This limits the number of data references in loops considered for data dependence analysis. These large loops are no handled by the optimizations that use loop data dependencies.max-vartrack-sizeโ the max number of hash table slots to use during variable tracking dataflow analysis of any function ๐งฉ If this limit is exceeded with variable tracking at assignments enabled, analysis for that function is retried without it, after removing all debug insns from the function. If the limit is still exceeded without debug insns, var tracking analysis is completely disabled for the function. Setting this to zero makes it unlimited.max-vartrack-expr-depthโ the max number of recursion levels when mapping variable names or debug temporaries to value expressions ๐ฌ This trades compilation time for more complete debug information. If it's set too low, value expressions that could be represented in debug information may end up not being used. Setting it higher may let the compiler find more complex debug expressions, but compile time and memory use may grow.max-debug-marker-countโ a threshold on the number of debug markers (like begin stmt markers) to avoid a complexity explosion at inlining or when 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 starting at this parameter are used for nondebug insns ๐ The range below it is reserved exclusively for debug insns created by-fvar-tracking-assignments, but debug insns may get (non-overlapping) uids above it if the reserved range runs out.ipa-sra-ptr-growth-factorโ IPA-SRA only replaces a pointer to an aggregate with one or more new parameters when their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter ๐ipa-sra-max-replacementsโ the max number of pieces of an aggregate that IPA-SRA tracks ๐งท As a consequence, it's also the max number of replacements of a formal parameter.sra-max-scalarization-size-Ospeed,sra-max-scalarization-size-Osizeโ the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) aim to swap scalar parts of aggregates for uses of independent scalar variables ๐ These parameters control the max size, in storage units, of an aggregate considered for replacement when compiling for speed (sra-max-scalarization-size-Ospeed) or for size (sra-max-scalarization-size-Osize), respectively.sra-max-propagationsโ the max number of artificial accesses that Scalar Replacement of Aggregates (SRA) will track per local variable, to help with copy propagation ๐ชtm-max-aggregate-sizeโ when making copies of thread-local variables in 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 option only applies when using-fgnu-tm.graphite-max-nb-scop-paramsโ ๐ okay so Graphite loop transforms can go fully exponential if nobody stops them, so the number of parameters in a Static Control Part (SCoP) gets capped. Set it to0to lift the cap. And any variable whose value isn't known at compile time and is defined outside a SCoP counts as one of its parameters. ๐งloop-block-tile-sizeโ ๐ฆ when loop blocking or strip mining is on (via-floop-blockor-floop-strip-mine), each loop in the nest gets strip mined by a set number of iterations. Want a different strip length? This param is how you change it.ipa-jump-function-lookupsโ ๐ how many statements get visited during jump function offset discovery.ipa-cp-value-list-sizeโ ๐ IPA-CP tries to track every value and type passed into 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. โจipa-cp-eval-thresholdโ ๐ฅ IPA-CP scores cloning profitability on its own, and it only goes through with cloning opportunities whose scores exceedipa-cp-eval-threshold.ipa-cp-max-recursive-depthโ ๐ how deep recursive cloning can go for a self-recursive function.ipa-cp-min-recursive-probabilityโ ๐ฏ recursive cloning only happens when the probability of the call actually being executed is higher than this parameter.ipa-cp-recursion-penaltyโ ๐ the percentage penalty recursive functions take when they're evaluated for cloning.ipa-cp-single-call-penaltyโ ๐ the percentage penalty functions take when they contain a single call to another function and get evaluated for cloning.ipa-max-agg-itemsโ ๐ธ IPA-CP can also propagate scalar values passed inside an aggregate. This caps how many of those values it handles per parameter.ipa-cp-loop-hint-bonusโ ๐ if IPA-CP figures out that a cloning candidate would make a loop's iteration count known, it adds a bonus ofipa-cp-loop-hint-bonusto that candidate's profitability score. Very main character.ipa-max-loop-predicatesโ ๐งฉ the max number of different predicates IPA uses to describe when loops in a function have known properties.ipa-max-aa-stepsโ ๐ซถ IPA-CP uses alias analysis to track the values that function parameters point to. So it doesn't spend forever on huge functions, it gives up after examiningipa-max-aa-stepsstatements that modify memory and treats all memory as clobbered.ipa-max-switch-predicate-boundsโ ๐ the max number of boundary endpoints of case ranges in a switch statement. Any switch over this limit won't get a cloning cost predicate for its default case. That predicate is what IPA-CP uses to estimate cloning benefit.ipa-max-param-expr-opsโ ๐ง IPA-CP checks conditionals 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 IPA analysis skips it. ๐lto-partitionsโ ๐ the desired number of partitions produced during WHOPR compilation. It should be more than the number of CPUs used for compilation.lto-min-partitionโ ๐ฑ the minimal partition size for WHOPR, measured in estimated instructions. This keeps tiny programs from getting chopped into way too many partitions.lto-max-partitionโ ๐ฐ the max partition size for WHOPR, measured in estimated instructions. It sets an upper bound on how big any single partition can get. It's only meant to be used with balanced partitioning.lto-max-streaming-parallelismโ ๐ the max number of parallel processes used for LTO streaming.cxx-max-namespaces-for-diagnostic-helpโ ๐ the max number of namespaces GCC will 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 the statement's original block, which decides whether a statement can be sunk. Bigger numbers mean more aggressive sinking. Statements with memory operands get a small positive adjustment, since sinking them is even more profitable. ๐max-stores-to-sinkโ ๐๏ธ the max number of conditional store pairs that can be sunk. Set it to0if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is disabled. ๐case-values-thresholdโ ๐ช the smallest number of distinct values where a jump table is better than a tree of conditional branches. If it's0, 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โ ๐ณ the max number of instructions executed in parallel in a reassociated tree. If it's set to a non-zero value, it overrides the target-dependent heuristics that would be used by default.sched-pressure-algorithmโ ๐๏ธ pick between the two implementations of-fsched-pressure. Algorithm 1 is the original and is the more likely of the two to stop instructions from being reordered. Algorithm 2 was designed as a compromise between algorithm 1's pretty conservative approach and the rather aggressive approach of the default scheduler. It leans more heavily on having a regular register file and accurate register pressure classes. For more details, check outhaifa-sched.cin the GCC sources. ๐
The default choice depends on the target. ๐ฏ
max-slsr-cand-scanโ ๐ญ the max number of existing candidates considered when hunting for a basis for a new straight-line strength reduction candidate.asan-globalsโ ๐ก๏ธ enables buffer overflow detection for global objects. This protection is on by default when you use-fsanitize=address. To turn off global objects protection, use--param asan-globals=0.asan-stackโ ๐ก๏ธ enables buffer overflow detection for stack objects. This is on by default when using-fsanitize=address. To turn off stack protection, use--param asan-stack=0.asan-instrument-readsโ ๐ enables buffer overflow detection for memory reads. This is on by default when using-fsanitize=address. To turn off memory reads protection, use--param asan-instrument-reads=0.asan-instrument-writesโ โ๏ธ enables buffer overflow detection for memory writes. This is on by default when using-fsanitize=address. To turn off memory writes protection, use--param asan-instrument-writes=0.asan-memintrinโ ๐งฐ enables detection for built-in functions. This is on by default when using-fsanitize=address. To turn off built-in functions protection, use--param asan-memintrin=0.asan-use-after-returnโ โฐ enables detection of use-after-return. This is on by default when you use the-fsanitize=addressoption. To turn it off, use--param asan-use-after-return=0.
โ ๏ธ Heads up: by default the check is disabled at run time. To turn it on, add "detect_stack_use_after_return=1" to theASAN_OPTIONSenvironment variable.
asan-instrumentation-with-call-thresholdโ ๐ if the number of memory accesses in the function being instrumented is greater than or equal to this number, GCC uses callbacks instead of inline checks. For example, to disable inline code, 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 when using-fsanitize=hwaddressand off by default when using-fsanitize=kernel-hwaddress. To turn stack instrumentation off, use--param hwasan-instrument-stack=0. To turn it on, use--param hwasan-instrument-stack=1.hwasan-random-frame-tagโ ๐ฒ when stack instrumentation is in use, tags for stack variables come from a deterministic sequence that starts at a random tag for each frame. If this param isn't set, the tags use the same sequence but start from1. This is 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. This is on by default when using-fsanitize=hwaddressand off by default when using-fsanitize=kernel-hwaddress. To turn off instrumentation for these variables, use--param hwasan-instrument-allocas=0. 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โ ๐ Turns on hwasan checks for memory writes. It's already on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress, but if you want to switch it off, use--param hwasan-instrument-writes=0.hwasan-instrument-mem-intrinsicsโ โจ Turns on hwasan instrumentation for builtin functions. This is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To turn it off, use--param hwasan-instrument-mem-intrinsics=0.use-after-scope-direct-emission-thresholdโ ๐ฆ If a local variable is at most this many bytes, the shadow memory gets poisoned (or unpoisoned) directly, instead of calling run-time callbacks.tsan-distinguish-volatileโ ๐ธ Adds special instrumentation for accesses to volatiles.tsan-instrument-func-entry-exitโ ๐ง Emits instrumentation calls to__tsan_func_entry()and__tsan_func_exit().max-fsm-thread-path-insnsโ ๐ The most instructions that get copied when duplicating blocks along a finite state automaton jump thread path.max-fsm-thread-lengthโ ๐ซถ The most basic blocks allowed on a finite state automaton jump thread path.max-fsm-thread-pathsโ ๐ The most new jump thread paths GCC will create for a finite state automaton.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 in an innermost parallelized loop. Once a loop hits this number, the parallel version is preferred over the single-threaded one. Heads up: for a parallelized loop nest, the minimum number of iterations of the outermost loop per thread is two.max-ssa-name-query-depthโ ๐ The deepest recursion allowed when querying properties of SSA names, like in fold routines. Each level of recursion means following one use-def chain.max-speculative-devirt-maydefsโ ๐ The maximum number of may-defs analyzed while hunting for a must-def that reveals the dynamic type of an object making a virtual call. If we find it, we may be able to devirtualize speculatively.max-vrp-switch-assertionsโ ๐ The maximum number of assertions added along the default edge of a switch statement during VRP.evrp-modeโ ๐ฆ Sets the mode that Early VRP operates in.unroll-jam-min-percentโ ๐ธ The minimum percentage of memory references that must be optimized away for the unroll-and-jam transformation to count as profitable.unroll-jam-max-unrollโ โจ The maximum number of times the outer loop can be unrolled by the unroll-and-jam transformation.max-rtl-if-conversion-unpredictable-costโ ๐ The maximum allowed cost for the sequence the RTL if-conversion pass would generate for a branch considered unpredictable.max-variable-expansions-in-unrollerโ ๐ง If-fvariable-expansion-in-unrolleris used, this is the maximum number of times one individual variable gets expanded during loop unrolling.tracer-min-branch-probability-feedbackโ ๐ Stops forward growth once the probability of the best edge drops below this threshold (in percent). Only used when profile feedback is available.partial-inlining-entry-probabilityโ ๐ซถ The maximum probability (in percent, relative to the entry BB of the function) of the entry BB of a split region that still lets partial inlining happen.max-tracked-strlensโ ๐ The maximum number of strings whose lengths the strlen optimization pass will track.gcse-after-reload-partial-fractionโ ๐ฅ The threshold ratio for doing partial redundancy elimination after reload.gcse-after-reload-critical-fractionโ ๐ The threshold ratio of critical edge execution count that still allows redundancy elimination after reload.max-loop-header-insnsโ ๐ The maximum number of insns in a loop header that the copy loop headers pass is allowed to duplicate.vect-epilogues-nomaskโ ๐ Turns on loop epilogue vectorization using a smaller vector size.vect-partial-vector-usageโ ๐ Controls when the loop vectorizer considers partial vector loads and stores, as an alternative to falling back to scalar code. It takes one of three values:0โ the vectorizer never uses partial vector loads and stores. ๐1โ partial vector loads and stores are allowed if vectorization gets rid of the need for the code to iterate. ๐2โ partial vector loads and stores are allowed in all loops. ๐
This parameter only does something on targets that support partial vector loads and stores.
avoid-fma-max-bitsโ โญ The maximum number of bits for which GCC avoids creating FMAs.sms-loop-average-count-thresholdโ ๐ A threshold on the average loop count that the swing modulo scheduler takes into account.sms-dfa-historyโ ๐ฆ The number of cycles the swing modulo scheduler looks at when checking for conflicts using DFA.max-inline-insns-recursive-autoโ ๐ง The maximum number of instructions a non-inline function can grow to through recursive inlining.graphite-allow-codegen-errorsโ ๐ Decides whether codegen errors should be ICEs when-fcheckingis on.sms-max-ii-factorโ ๐ซถ A tuning factor for the upper bound the swing modulo scheduler uses when scheduling a loop.lra-max-considered-reload-pseudosโ ๐ฅ The maximum number of reload pseudos considered while spilling a non-reload pseudo.max-pow-sqrt-depthโ ๐ The maximum depth of sqrt chains used when synthesizing exponentiation by a real constant.max-dse-active-local-storesโ ๐ธ The maximum 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โ ๐ The bound on the cost of an expression used to compute the number of iterations.max-isl-operationsโ ๐ The maximum number of isl operations. Setting it to0means unlimited.graphite-max-arrays-per-scopโ ๐ The maximum number of arrays per scop.max-vartrack-reverse-op-sizeโ ๐ The maximum size of a loc list for which reverse ops should be added.tracer-dynamic-coverage-feedbackโ โญ The percentage of a function, weighted by execution frequency, that trace formation must cover. Only used when profile feedback is available.max-inline-recursive-depth-autoโ ๐ The maximum depth of recursive inlining for non-inline functions.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.fsm-maximum-phi-argumentsโ ๐ง The maximum number of arguments a PHI can have before the FSM threader stops trying to thread through its block.uninit-control-dep-attemptsโ ๐ The maximum number of nested calls used to search for control dependencies during uninitialized variable analysis.sra-max-scalarization-size-Osizeโ ๐ The maximum size, in storage units, of an aggregate that should be considered for scalarization when compiling for size.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's the number of lookahead cycles the model looks into. Set it to' 'to only enable the instruction sorting heuristic. ๐คloop-versioning-max-inner-insnsโ ๐ธ The maximum 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 maximum number of instructions an outer loop can have before the loop versioning pass decides it's too big to copy. Any instructions in inner loops that directly benefit from versioning don't count toward this.ssa-name-def-chain-limitโ ๐ The maximum number of SSA_NAME assignments to follow when figuring out a property of a variable, like its value. This caps the number of iterations or recursive calls GCC makes while optimizing certain statements or checking whether they're valid before issuing diagnostics.store-merging-max-sizeโ ๐ The maximum size of a single store merging region, in bytes.hash-table-verification-limitโ ๐ The number of elements that get hash table verification done on them for each searched element.max-find-base-term-valuesโ โญ The maximum number of VALUEs handled during a singlefind_base_termcall.analyzer-max-enodes-per-program-pointโ ๐ฆ The maximum number of exploded nodes per program point within the analyzer. Once a point hits this, analysis of that point stops.analyzer-max-constraintsโ ๐ The maximum number of constraints per state.analyzer-min-snodes-for-call-summaryโ ๐ง The minimum number of supernodes within a function before the analyzer considers summarizing its effects at call sites.analyzer-max-enodes-for-full-dumpโ ๐ The maximum depth of exploded nodes that can show up in a dot dump. Past this, the dump switches to a less verbose format.analyzer-max-recursion-depthโ ๐ The maximum number of times a callsite can appear in a call stack within the analyzer. Once it's hit, analysis of a call that would recurse deeper stops.analyzer-max-svalue-depthโ ๐ซถ The maximum depth of a symbolic value. Anything deeper gets approximated as unknown.analyzer-max-infeasible-edgesโ ๐ The maximum number of infeasible edges to reject before a diagnostic is declared infeasible.gimple-fe-computed-hot-bb-thresholdโ ๐ฅ The number of executions a basic block needs before it counts as hot. This parameter is only used in the GIMPLE FE. โจanalyzer-bb-explosion-factorโ this is the cap on how many "after supernode" exploded nodes the analyzer can make per supernode ๐ Once it hits that number, the analysis gets terminated ๐ranger-logical-depthโ the max depth of logical expression evaluation that ranger will dig through when it's checking outgoing edge ranges ๐openacc-kernelsโ picks how OpenACCkernelsconstructs get handled ๐ธ There are two modes:--param=openacc-kernels=decomposeโ eachkernelsconstruct gets split into parts, a sequence of compute constructs, and each part is handled individually. Heads up, this one is still work in progress ๐ง--param=openacc-kernels=parloopsโkernelsconstructs get handled by the parloops pass, en bloc. This is the current default, so you're already getting it ๐
These next ones are the AArch64-only vibes ๐ They're available on AArch64 targets:
aarch64-sve-compare-costsโ when vectorizing for SVE, GCC considers using "unpacked" vectors for smaller elements, and lets the cost model pick the cheapest approach ๐ The cost model also decides between SVE and Advanced SIMD vectorization. Going unpacked 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 forfloattype โจ When division approximation is enabled, the precision of division scales with this param. The default value is1๐ฆaarch64-double-recp-precisionโ same energy, but fordoubletype ๐ It's the number of Newton iterations for the reciprocal, and when division approximation is enabled, the precision of division is proportional to this param. The default value is2๐ธaarch64-autovec-preferenceโ forces an ISA selection strategy for auto-vectorization ๐ฅ It accepts values from0to4, inclusive:0โ use the default heuristics ๐คท1โ use only Advanced SIMD for auto-vectorization2โ use only SVE for auto-vectorization3โ use both Advanced SIMD and SVE, and prefer Advanced SIMD when the costs are deemed equal4โ use both Advanced SIMD and SVE, and prefer SVE when the costs are deemed equal
The default value is 0.
aarch64-loop-vect-issue-rate-nitersโ some AArch64 CPUs tune by weighing both latencies and issue rates when deciding whether a loop gets vectorized with SVE, with Advanced SIMD, or not at all ๐ง If this parameter is set ton, GCC won't use this heuristic for loops that are known to execute in fewer thannAdvanced SIMD iterations ๐
๐ Program Instrumentation Options ๐
GCC supports a bunch of command-line options that control adding run-time instrumentation to the code it normally generates ๐ For example, one purpose of instrumentation is collecting profiling stats for finding program hot spots, code coverage analysis, or profile-guided optimizations ๐ Another class adds run-time checking to catch programming errors like invalid pointer dereferences or out-of-bounds array accesses, plus deliberately hostile attacks such as stack smashing or C++ vtable hijacking ๐ญ There's also a general hook that can be used to implement other forms of tracing or function-level instrumentation for debug or program analysis purposes ๐ง
-p,-pgโ generates extra code to write profile information suitable for the analysis programprof(for-p) orgprof(for-pg) ๐ You must use this option when compiling the source files you want data about, and you must also use it when linking.
You can use the function attribute no_instrument_function to suppress profiling of individual functions when compiling with these options ๐
-fprofile-arcsโ adds code so that program flow arcs get instrumented ๐ During execution, the program records how many times each branch and call is executed, and how many times it's taken or returns. On targets that support constructors with priority support, profiling properly handles constructors, destructors, and C++ constructors (and destructors) of classes that are used as a type of a global variable. When the compiled program exits, it saves this data to a file calledauxname.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'sauxnameis generated from the name of the output file, if explicitly specified and it is not the final executable. Otherwise, it's the basename of the source file. In both cases any suffix is removed (e.g.foo.gcdafor input filedir/foo.c, ordir/foo.gcdafor output file specified as-o dir/foo.o).
With -fprofile-arcs, for each function of your program GCC creates a program flow graph, then finds a spanning tree for the graph. Only arcs that are not on the spanning tree have to be instrumented: the compiler adds code to count the number of times those arcs are executed. When an arc is the only exit or only entrance to a block, the instrumentation code can be added to the block. Otherwise, a new basic block must be created to hold the instrumentation code ๐งฎ
--coverageโ this is used to compile and link code instrumented for coverage analysis ๐งช It's a synonym for-fprofile-arcs-ftest-coverage(when compiling) and-lgcov(when linking). See the documentation for those options for more details. Here's the full workflow:
- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, use the additional-ftest-coverageoption. You do not need to profile every source file in a program. - Compile the source files additionally with
-fprofile-abs-pathto create absolute path names in the.gcnofiles. This allowsgcovto find the correct sources in projects where compilations occur with different working directories. - Link your object files with
-lgcovor-fprofile-arcs(the latter implies the former). - Run the program on a representative workload to generate the arc profile information. This may be repeated any number of times. You can run concurrent instances of your program, and provided that the file system supports locking, the data files will be correctly updated. Unless a strict ISO C dialect option is in effect,
forkcalls are detected and correctly handled without double counting. - For profile-directed optimizations, compile the source files again with the same optimization and code generation options plus
-fbranch-probabilities. - For test coverage analysis, use
gcovto produce human readable information from the.gcnoand.gcdafiles. Refer to the gcov documentation for further information.
-ftest-coverageโ produces a notes file that thegcovcode-coverage utility can use to show program coverage ๐ Each source file's note file is calledauxname.gcno. Refer to the-fprofile-arcsoption above for a description ofauxnameand instructions on how to generate test coverage data. Coverage data matches the source files more closely if you do not optimize ๐ฏ-fprofile-abs-pathโ automatically converts relative source file names to absolute path names in the.gcnofiles ๐บ๏ธ This allowsgcovto find the correct sources in projects where compilations occur with different working directories.-fprofile-dir=pathโ sets the directory to search for the profile data files in topath๐ This option only affects the profile data generated by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-useand-fbranch-probabilitiesand its related options. Both absolute and relative paths can be used. By default, GCC uses the current directory aspath, so the profile data file appears in the same directory as the object file. To prevent file name clashing, if the object file name is not an absolute path, GCC mangles the absolute path of thesourcename.gcdafile and uses it as the file name of a.gcdafile. See similar option-fprofile-note.
When an executable is run in a massive parallel environment, it's recommended to save profiles to different folders ๐ง You can do that with variables in path that get exported during run-time:
%pโ process ID.%q{VAR}โ value of environment variableVAR
-fprofile-generate,-fprofile-generate=pathโ enables options usually used for instrumenting an application to produce a profile that's useful for later recompilation with profile feedback based optimization ๐ฅ You must use-fprofile-generateboth when compiling and when linking your program. The following options get enabled:-fprofile-arcs,-fprofile-values,-finline-functions, and-fipa-bit-cp.
If path is specified, GCC looks at that path to find the profile feedback data files. See -fprofile-dir. To optimize the program based on the collected profile information, use -fprofile-use ๐
-fprofile-info-section,-fprofile-info-section=nameโ registers the profile information in the specified section instead of using a constructor/destructor ๐งฉ The section name isnameif it's specified, otherwise it defaults to.gcov_info. A pointer to the profile information generated by-fprofile-arcsor-ftest-coverageis placed in the specified section for each translation unit. This option disables the profile information registration through a constructor, and it disables the profile information processing through a destructor. It is not intended to be used in hosted environments such as GNU/Linux. It targets systems with limited resources that don't support constructors and destructors. The linker could collect the input sections in a continuous memory block and define start and end symbols. The runtime support could dump the profiling information registered in this linker set during program termination to a serial line, for example. โจ
Now for the spicy part, bestie: a GNU linker script example that defines a linker output section comes right up next:
Picking up right where that linker script leaves off ๐
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
-fprofile-note=pathโ okay so, if you give it apath, GCC drops the.gcnofile right there ๐ bestie, heads up: if you combine it with multiple source files, that.gcnogets overwritten ๐ญ-fprofile-prefix-path=pathโ this one is a total lifesaver โจ It's meant to be used withprofile-generate=profile_dirandprofile-use=profile_dir, and it tells GCC where the base directory of your built source tree lives ๐ธ- By default,
profile_dirgets filled with files that have mangled absolute paths for every object file in the build. Lowkey messy ๐ - It becomes a real problem when the directory you built the instrumented binary in is different from the one you used for the optimized build. The profile data just won't be found ๐
- So you point
-fprofile-prefix-path=pathat the base directory of the build. It strips the irrelevant part and keeps every file name relative to the main build directory ๐ฆ
- By default,
-fprofile-update=methodโ this changes how the update works for an app that's been instrumented for profile feedback based optimization ๐ Themethodargument should besingle,atomic, orprefer-atomic.singleis the move for single-threaded apps ๐งatomicis the thread-safe queen, because it prevents profile corruption by emitting thread-safe code ๐
Warning: if an application doesn't properly join all its threads (or it creates a detached thread), a profile file can still get corrupted. Not ideal, bestie ๐ญ
prefer-atomicis transformed intoatomicwhen the target supports it, and intosingleotherwise ๐- The GCC driver automatically picks
prefer-atomicwhenever-pthreadis in the command line โจ
-fprofile-filter-files=regexโ only instrument functions from files whose name matches any of the regular expressions, separated by semi-colons ๐ฏ- Example:
-fprofile-filter-files=main\.c;module.*\.cwill instrument onlymain.cand all C files starting with'module'๐
- Example:
-fprofile-exclude-files=regexโ this one's the mirror vibe ๐ช It says to instrument only functions from files whose name does not match any of the regular expressions, separated by semi-colons.- Example:
-fprofile-exclude-files=/usr/.*will prevent instrumentation of all files located in the/usr/folder ๐
- Example:
-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ this controls how reproducible the profile gathered by"-fprofile-generate"is ๐ It's giving rebuild-the-same-outcome energy, which is super useful for things like distribution packages ๐ฆserialโ the profile is reproducible provided the trained program behaves the same at each invocation of the train run, it's not multi-threaded, and profile data streaming is always done in the same order ๐ซถ Also, streaming happens at the end of the program run, but also before the"fork"function is invoked. Wild, right? ๐ญ- Heads up: execution counts for some parts of a program can depend on things like the length of temporary file names or memory space randomization (which might mess with hash-table collision rate) ๐ That non-reproducible part can be annotated with the
no_instrument_functionfunction attribute. You can usegcov-dumpwith-lto dump the gathered data and check that it's actually reproducible ๐ parallel-runsโ the collected profile stays reproducible no matter what order the data gets streamed intogcdafiles ๐ This lets you run multiple instances of the instrumented program in parallel (like withmake -j) ๐โโ๏ธ
Heads up: running in parallel reduces the quality of the gathered data, especially for indirect call profiling ๐
-fsanitize=addressโ enables AddressSanitizer, a fast memory error detector ๐ฅ It instruments memory access instructions to catch out-of-bounds and use-after-free bugs. This option also enables-fsanitize-address-use-after-scope.- More details live at
https://github.com/google/sanitizers/wiki/AddressSanitizer๐ - You can tweak run-time behavior with the
ASAN_OPTIONSenvironment variable. Set it to"help=1"and the available options get shown when the instrumented program starts up ๐ง - A list of supported options is at
https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags๐ - This can't be combined with
-fsanitize=threador-fsanitize=hwaddress. Also, the only target-fsanitize=hwaddressis currently supported on is AArch64 โจ
- More details live at
-fsanitize=kernel-addressโ AddressSanitizer for the Linux kernel ๐ง More info athttps://github.com/google/kasan๐ธ-fsanitize=hwaddressโ hardware-assisted AddressSanitizer ๐ฆ It uses a hardware ability to ignore the top byte of a pointer, which lets it detect memory errors with a low memory overhead. Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs, and this option enables-fsanitize-address-use-after-scope.- See
https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.htmlfor more details ๐ - Run-time behavior can be influenced with the
HWASAN_OPTIONSenvironment variable. When set to"help=1", the available options show up at startup of the instrumented program ๐ - This can't be combined with
-fsanitize=threador-fsanitize=address, and it's currently only available on AArch64 ๐ซถ
- See
-fsanitize=kernel-hwaddressโ hardware-assisted AddressSanitizer for compiling the Linux kernel ๐ It's similar to-fsanitize=kernel-addressbut uses an alternate instrumentation method. It's also similar to-fsanitize=hwaddress, just with instrumentation differences needed for the kernel ๐ Those differences exist to avoid hwasan library initialization calls and to account for the stack pointer having a different value in its top byte.
Note: this option has different defaults to-fsanitize=hwaddress. Instrumenting the stack and alloca calls isn't 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 isn't implemented for kernel instrumentation ๐
-fsanitize=pointer-compareโ instruments comparison operations (<,<=,>,>=) with pointer operands ๐ It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it can't be combined with-fsanitize=thread.- Heads up: the check is disabled at run time by default ๐ To turn it on, add
"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. "detect_invalid_pointer_pairs=1"only detects invalid operation when both pointers are non-null ๐
- Heads up: the check is disabled at run time by default ๐ To turn it on, add
-fsanitize=pointer-subtractโ same energy, but for subtraction with pointer operands โจ It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it can't be combined with-fsanitize=thread.- Again, the check is disabled at run time by default. Add
"detect_invalid_pointer_pairs=2"toASAN_OPTIONSto enable it ๐ "detect_invalid_pointer_pairs=1"only detects invalid operation when both pointers are non-null ๐ธ
- Again, the check is disabled at run time by default. Add
-fsanitize=threadโ enables ThreadSanitizer, a fast data race detector ๐งต It instruments memory access instructions to catch data race bugs. More details athttps://github.com/google/sanitizers/wiki#threadsanitizer๐- Run-time behavior can be influenced with the
TSAN_OPTIONSenvironment variable. For a list of supported options, checkhttps://github.com/google/sanitizers/wiki/ThreadSanitizerFlags๐ - This can't be combined with
-fsanitize=addressor-fsanitize=leak๐ โโ๏ธ - Note that sanitized atomic builtins cannot throw exceptions when operating on invalid memory addresses with non-call exceptions (
-fnon-call-exceptions) ๐
- Run-time behavior can be influenced with the
-fsanitize=leakโ enables LeakSanitizer, a memory leak detector ๐ฉธ This option only matters when linking executables, and when the executable is linked against a library that overridesmallocand other allocator functions.- More details at
https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer๐ - Run-time behavior can be influenced with the
LSAN_OPTIONSenvironment variable ๐ง - It can't be combined with
-fsanitize=thread๐ โโ๏ธ
- More details at
-fsanitize=undefinedโ enables UndefinedBehaviorSanitizer, a fast undefined behavior detector ๐ Various computations get instrumented to catch undefined behavior at runtime.- See
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.htmlfor more details ๐ - Run-time behavior can be influenced with the
UBSAN_OPTIONSenvironment variable. Current suboptions are:-fsanitize=shiftโ checks that the result of a shift operation isn't undefined ๐ซง What counts as undefined differs slightly between C and C++, and also between ISO C90 and C99, etc. This option has two suboptions:-fsanitize=shift-baseand-fsanitize=shift-exponent.-fsanitize=shift-exponentโ checks that the second argument of a shift operation isn't negative and is smaller than the precision of the promoted first argument ๐ข-fsanitize=shift-baseโ if the second argument of a shift operation is within range, it checks that the result of the shift isn't undefined ๐งฎ Same deal as above: the exact rules differ between C and C++, and between ISO C90 and C99, etc.-fsanitize=integer-divide-by-zeroโ detects integer division by zero, as well as"INT_MIN / -1"division ๐-fsanitize=unreachableโ the compiler turns the"__builtin_unreachable"call into a diagnostics message call instead ๐จ When you reach the"__builtin_unreachable"call, the behavior is undefined, so this is a whole vibe check ๐ญ-fsanitize=vla-boundโ checks that the size of a variable length array is positive ๐
- See
-fsanitize=nullโ okay, pointer checking is the vibe here ๐ With this on, your program throws an error when it tries to dereference aNULLpointer ๐ญ. It also flags a reference (possibly an rvalue reference) bound to aNULLpointer, or a method invoked on an object pointed to by aNULLpointer.-fsanitize=returnโ return statement checking, and it's giving main character energy ๐ Programs built with this will issue an error when the end of a non-void function is reached without actually returning a value. This one is C++ only ๐ธ.-fsanitize=signed-integer-overflowโ signed integer overflow checking ๐ฅ It checks that the result of+,*, and both unary and binary-doesn't overflow in signed arithmetic. Integer promotion rules still apply, so this is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ array bounds instrumentation ๐ฆ Lots of out-of-bounds accesses get caught. Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented ๐-fsanitize=bounds-strictโ the stricter array bounds check ๐ Most out-of-bounds accesses are detected, including flexible array members and flexible array member-like arrays. Initializers of variables with static storage still aren't instrumented.-fsanitize=alignmentโ pointer alignment checking โจ It kicks in when a pointer gets 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โ memory references get instrumented using the__builtin_object_sizefunction ๐ Various out-of-bounds pointer accesses are detected.-fsanitize=float-divide-by-zeroโ floating-point division by zero detection โ Unlike other similar options, this one is not turned on by-fsanitize=undefined. That's because dividing a float by zero can be a legit way to get infinities and NaNs, so it's not automatically treated as a bug ๐-fsanitize=float-cast-overflowโ floating-point to integer conversion checking ๐ง It makes sure the result of the conversion doesn't overflow. Also not turned on by-fsanitize=undefined.
โ ๏ธ Heads up bestie ๐ This option does not work well with FE_INVALID exceptions enabled.
-fsanitize=nonnull-attributeโ checks calls to make sure null values aren't passed to arguments marked as needing a non-null value by thenonnullfunction attribute ๐ซถ-fsanitize=returns-nonnull-attributeโ instruments return statements in functions marked with thereturns_nonnullfunction attribute, so it can catch null values being returned from them ๐-fsanitize=boolโ instruments loads frombool๐ If a value other than0/1gets loaded, you'll get a run-time error.-fsanitize=enumโ instruments loads from an enum type ๐ If a value outside the range of values for that enum type gets loaded, a run-time error is issued.-fsanitize=vptrโ C++ member function calls, member accesses, and some conversions between pointers to base and derived classes get instrumented ๐ฆ This verifies the referenced object has the correct dynamic type.-fsanitize=pointer-overflowโ pointer arithmetic gets instrumented ๐ธ If the pointer arithmetic overflows, a run-time error is issued.-fsanitize=builtinโ instruments arguments to selected builtin functions ๐ฎ If an invalid value gets passed to one of those arguments, a run-time error is issued. For example, passing0as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior, and this option diagnoses it.
While -ftrapv causes traps for signed overflows to be emitted, -fsanitize=undefined gives a diagnostic message instead. This currently works only for the C family of languages ๐
-fno-sanitize=allโ disables all previously enabled sanitizers ๐งน
โ ๏ธ -fsanitize=all is not allowed, as some sanitizers cannot be used together.
-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks ๐งช It's useful for experimenting with different shadow memory layouts in Kernel AddressSanitizer.-fsanitize-sections=s1,s2,...โ sanitizes global variables in selected user-defined sections ๐๏ธsimay contain wildcards.-fsanitize-recover[=opts]โ controls the error recovery mode for the sanitizers in the comma-separated listopts๐ When recovery is enabled for a sanitizer, it tries to keep running the program as if no error happened. That means multiple runtime errors can be reported in a single run, and the exit code may indicate success even when errors were reported. The-fno-sanitize-recover=option changes this: only the first detected error gets reported, and then the program exits with a non-zero exit code ๐
Right now this only works for -fsanitize=undefined (and its suboptions except for -fsanitize=unreachable and -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address and -fsanitize=address. For these sanitizers, error recovery is turned on by default, except for -fsanitize=address, where this feature is experimental ๐งช -fsanitize-recover=all and -fno-sanitize-recover=all are also accepted. The former enables recovery for all sanitizers that support it, and the latter disables recovery for all sanitizers that support it.
Even if recovery mode is turned on compiler-side, it also needs to be enabled on the runtime library side. Otherwise the failures are still fatal ๐ The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while the default value for AddressSanitizer is halt_on_error=1. You can override this by setting the halt_on_error flag in the corresponding environment variable ๐
Syntax without an explicit opts parameter is deprecated ๐ฌ It's equivalent to specifying an opts list of:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ enables sanitization of local variables to detect use-after-scope bugs ๐ This option sets-fstack-reusetonone.-fsanitize-undefined-trap-on-errorโ reports undefined behavior using__builtin_trapinstead of alibubsanlibrary routine ๐ช The perk is that thelibubsanlibrary isn't needed and doesn't get linked in, so this works even in freestanding environments ๐๏ธ-fsanitize-coverage=trace-pcโ enables coverage-guided fuzzing code instrumentation ๐ It inserts a call to__sanitizer_cov_trace_pcinto every basic block.-fsanitize-coverage=trace-cmpโ enables dataflow guided fuzzing code instrumentation ๐ง It inserts calls to the following:__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4, or__sanitizer_cov_trace_cmp8for integral comparisons where both operands are variables__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4, or__sanitizer_cov_trace_const_cmp8for integral comparisons where one operand is a constant__sanitizer_cov_trace_cmpfor__sanitizer_cov_trace_cmpdfor float or double comparisons__sanitizer_cov_trace_switchfor switch statements
-fcf-protection=[full|branch|return|none|check]โ control-flow instrumentation for extra security ๐ก๏ธ It checks that the target addresses of control-flow transfer instructions (such as indirect function calls, function returns, and indirect jumps) are valid. This stops the flow of control from being diverted to an unexpected target. It's meant to protect against threats like Return-oriented Programming (ROP), and similar call/jmp-oriented programming (COP/JOP) ๐branchโ checking happens at indirect branch instructions, i.e. call/jmp instructions ๐ฟreturnโ checking happens when returning from a function โฉ๏ธfullโ an alias for specifying bothbranchandreturn๐noneโ turns off instrumentation ๐checkโ used for the final link with link-time optimization (LTO). An error is issued if LTO object files were compiled with different-fcf-protectionvalues. This value is ignored at compile time ๐ซ
The macro __CET__ is defined when -fcf-protection is used โจ The first bit of __CET__ is set to 1 for the value branch, and the second bit of __CET__ is set to 1 for return.
You can also use the nocf_check attribute to mark which functions and calls should be skipped from instrumentation ๐
Right now the x86 GNU/Linux target provides an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processors or newer ๐ป
NOTE: In Ubuntu 19.10 and later versions,-fcf-protectionis enabled by default for C, C++, ObjC, ObjC++, if none of-fno-cf-protectionnor-fcf-protection=*are found ๐
-fstack-protectorโ okay bestie, this one is a stack-smashing bodyguard ๐ก๏ธ๐ It sneaks a guard variable into any function with vulnerable objects. That covers functions that callalloca, plus functions with buffers of at least 8 bytes. The guards get set up when a function is entered and get checked on the way out. If a guard check fails, you get an error message and the program exits. Only variables that actually live on the stack count, so anything optimized away or stuck in a register doesn't get a guard. ๐ธ-fstack-protector-allโ same energy as-fstack-protector, but every single function gets protected. Full bodyguard mode ๐-fstack-protector-strongโ basically-fstack-protectorbut with extra functions in the guest list ๐ These are the ones with local array definitions, or ones that reference local frame addresses. The same rule applies: only variables actually allocated on the stack count, and optimized-away or register variables don't.-fstack-protector-explicitโ the VIP-list version of-fstack-protector. It only protects functions that carry thestack_protectattribute ๐ง-fstack-checkโ this one makes the code check that you don't go past the edge of the stack ๐ฆ You'll want it if you're running in a multithreaded environment. In a single-threaded setup you almost never need it, because stack overflow is usually caught automatically on nearly every system if there's only one stack. ngl that's a relief ๐ญ
This flag doesn't do the checking itself. The operating system or the language runtime has to do that. What it does is generate code so they can see the stack being extended. You can also pass it a string parameter: no means no checking at all, generic forces the old-style checking, and specific uses the best checking method for the target and is equivalent to bare -fstack-check.
Old-style checking is a generic mechanism. It doesn't need any target-specific support from the compiler, but it comes with some drawbacks, and honestly they're a lot:
- Modified allocation strategy for large objects: they're always allocated dynamically if their size goes over a fixed threshold. This may change the semantics of some code, so be careful ๐
- 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, your code performance takes a hit ๐
Also, old-style stack checking is the fallback for specific if the compiler doesn't have target support added. So specific falls back to it when there's no target support.
-fstack-check= was designed for Ada's needs, specifically detecting infinite recursion and stack overflows. specific is an excellent choice when you're compiling Ada code ๐
It's not generally enough to protect you against stack-clash attacks though. For that, you want -fstack-clash-protection.
-fstack-clash-protectionโ this is the anti-stack-clash flag ๐ฅ When it's on, the compiler only allocates one page of stack space at a time, and each page gets accessed right after it's allocated. That means allocations can't jump over a stack guard page the operating system provides.
Most targets don't fully support stack clash protection. On the ones that do, -fstack-clash-protection protects dynamic stack allocations. It can also give limited protection to static stack allocations, but only if the target supports -fstack-check=specific.
NOTE: In Ubuntu 19.10 and later,-fstack-clash-protectionis enabled by default for C, C++, ObjC, and ObjC++, unless-fno-stack-clash-protectionshows up in the command line. So it's already on for you, probably ๐ซถ
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ these generate code so the stack never grows past a certain value. That value is either a register's contents or the address of a symbol ๐ If the program needs a bigger stack than that, a signal gets raised at run time. On most targets the signal goes off before the stack actually overruns the boundary, so you can catch it without doing anything special.
Here's an example. Say 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โ this one automatically splits the stack before it overflows ๐ง The result is a discontiguous stack, which can only overflow if the program can't allocate any more memory at all. It's most useful for threaded programs, because you don't have to work out a good stack size for each thread anymore. Life-changing ๐ญ Right now it's only implemented for x86 targets running GNU/Linux.
If code compiled with -fsplit-stack calls code compiled without it, the latter code might not have much stack space to run in. If compiling everything (library code included) with -fsplit-stack isn't an option, the linker can fix up those calls so the code without -fsplit-stack always gets a large stack. This support is implemented in the gold linker in GNU binutils release 2.21 and later ๐ฆ
-fvtable-verify=[std|preinit|none]โ C++ only! ๐ This turns on the security feature that checks, at run time and 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. Use-fvtable-verify=noneto turn it off. If an invalid vtable pointer gets detected, an error is reported and the program stops right away ๐
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 structures get built. In both cases they're built before execution reaches main. With -fvtable-verify=std, they're built after shared libraries have been loaded and initialized. With -fvtable-verify=preinit, they're built before shared libraries have been loaded and initialized.
If this option shows up multiple times in the command line with different values, none takes the highest priority over both std and preinit, and preinit takes priority over std ๐
-fvtv-debugโ use this with-fvtable-verify=stdor-fvtable-verify=preinitand it calls the debug versions of the runtime functions for vtable verification ๐ It also makes the compiler log which vtable pointers it finds for each class. That info goes into a file calledvtv_set_ptr_data.log, in the directory named by the environment variableVTV_LOGS_DIRif that's defined, or in the current working directory otherwise.
Note: this feature appends to the log file. If you want a fresh log, delete any existing one first ๐งน
-fvtv-countsโ a debugging flag, bestie ๐ 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 the calls it inserts to certain run-time library functions and logs all of this for each compilation unit. The compiler writes that info tovtv_count_data.login the directory named byVTV_LOGS_DIRif it'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 to the log files too. For fresh log files, delete any existing ones first ๐
-finstrument-functionsโ this generates instrumentation calls for function entry and exit ๐ธ Right after a function is entered, and right before it exits, the following profiling functions get called with the address of the current function and its call site. (Heads up: on some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site info might not be available to the profiling functions.)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
The first argument is the address of the start of the current function, which can be looked up exactly in the symbol table ๐ฅ
This instrumentation also happens for functions that get expanded inline into other functions. The profiling calls show where, conceptually, the inline function is entered and exited. That means addressable versions of those functions have to exist. If all your uses of a function get expanded inline, this may mean extra code size. If you use extern inline in your C code, an addressable version of those functions must be provided. (This is usually 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 no_instrument_function attribute, and then this instrumentation won't happen for it. This is handy for things like the profiling functions listed above, high-priority interrupt routines, and any function 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,...โ okay bestie, this one is the VIP exclusion list ๐ซโจ It sets which functions get skipped for instrumentation (peep-finstrument-functionsfor the full tea โ). If the file holding a function's definition matches one of the file entries, that function is NOT instrumented. The match is done on substrings, so if your file bit shows up anywhere inside the file name, it counts ๐ฆ
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
That excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys ๐
If, for some reason, you need a comma inside one of the sym values, you double it up and write ,, ๐ Like this, with single quotes around the whole option: -finstrument-functions-exclude-file-list=',,tmp' ๐งต
-finstrument-functions-exclude-function-list=sym,sym,...โ this is basically the file-list's cousin ๐ฏ, except it lists the function names to skip instead of files. The name that gets matched is the user-visible name, likevector<int> blah(const vector<int> &), NOT the scrambled internal mangled name like_Z4blahRSt6vectorIiSaIiEE๐. Matching is substring-based too: if sym is a substring of the function name, it's a match. For C99 and C++ extended identifiers, the function name has to be written in UTF-8, not with universal character names ๐-fpatchable-function-entry=N[,M]โ okay this one is giving extra space ๐ง. It generates N NOPs right at the start of each function, with the function entry point sitting before the Mth NOP. If M is left off, it defaults to 0, so the entry point is the address right at the first NOP. Those NOPs reserve room you can patch instrumentation into at run time, as long as the code segment is writable โจ. The amount of space is controlled indirectly through how many NOPs you ask for. The NOP instruction used is the one emitted by the internal GCC back-end interfacegen_nop. This is target-specific and may also depend on the architecture variant and/or other compilation options ๐ธ
For run-time identification, the starting addresses of these areas, which correspond to their respective function entries minus M, also get collected in the __patchable_function_entries section of the resulting binary ๐
Note that the value of __attribute__ ((patchable_function_entry (N,M))) takes precedence over the command-line option -fpatchable-function-entry=N,M. This can be used to increase the area size or to remove it completely on a single function. If N=0, no pad location is recorded ๐
The NOP instructions are inserted at---and maybe before, depending on M---the function entry address, even before the prologue. ๐ซฃ
The maximum value of N and M is 65535 ๐
โจ Options Controlling the Preprocessor โจ
These options control the C preprocessor, which runs on each C source file before the actual compilation happens ๐งผ
If you use -E, nothing gets done except preprocessing. Some of these options only make sense together with -E, because they make the preprocessor output unsuitable for actual compilation ๐
In addition to the options listed here, there are a bunch of options that control search paths for include files, documented in Directory Options ๐. Options to control preprocessor diagnostics are listed in Warning Options โ ๏ธ
-D nameโ predefines name as a macro, with the definition1๐-D name=definitionโ the contents of definition get tokenized and processed as if they showed up during translation phase three in a#definedirective ๐งฉ. Heads up: the definition gets truncated by any embedded newline characters โ๏ธ
If you're invoking the preprocessor from a shell (or something shell-like), you might need the shell's quoting syntax to protect characters like spaces that have a meaning in shell syntax ๐
If you want to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses mean stuff to most shells, so you should quote the option ๐ซถ With sh and csh, -D'name(args...)=definition' works ๐
-D and -U options are processed in the order they're given on the command line. All -imacros file and -include file options get processed after all -D and -U options ๐
-U nameโ cancels any previous definition of name, whether it was built in or provided with a-Doption ๐งน-include fileโ processes file as if#include "file"appeared as the very first line of the primary source file ๐. The twist: the first directory searched for file is the preprocessor's working directory, not the directory containing the main source file ๐. If it's not found there, it gets searched for in the rest of the#include "..."search chain as normal.
If you give multiple -include options, the files are included in the order they show up on the command line ๐ข
-imacros fileโ exactly like-include, except any output produced by scanning file gets thrown away ๐๏ธ. The macros it defines stay defined, which lets you grab all the macros from a header without also processing its declarations โจ
All files specified by -imacros are processed before all files specified by -include ๐
-undefโ do not predefine any system-specific or GCC-specific macros ๐ซ. The standard predefined macros stay defined ๐-pthreadโ defines the extra macros required for using the POSIX threads library ๐งต. You should use this option consistently for both compilation and linking ๐. It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets ๐-Mโ instead of outputting the preprocessed result, it outputs a rule suitable formakethat describes the dependencies of the main source file ๐. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from-includeor-imacroscommand-line options ๐ฆ
Unless you specify it explicitly (with -MT or -MQ), the object file name consists of the name of the source file with any suffix replaced by the object file suffix and any leading directory parts removed. If there are lots of included files, the rule gets split into several lines using \-newline. The rule has no commands ๐งพ
This option doesn't suppress the preprocessor's debug output, such as -dM. To avoid mixing that debug output with the dependency rules, you should explicitly specify the dependency output file with -MF, or use an environment variable like DEPENDENCIES_OUTPUT. Debug output is still sent to the regular output stream as normal ๐
Passing -M to the driver implies -E, and suppresses warnings with an implicit -w ๐คซ
-MMโ like-M, but doesn't mention header files found in system header directories, nor header files included directly or indirectly from such a header ๐
This implies that the choice of angle brackets or double quotes in an #include directive doesn't in itself determine whether that header appears in -MM dependency output ๐
-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โ in conjunction with an option such as-Mrequesting 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โ disables dependency generation for compiled module interfaces ๐งฉ-MPโ instructs CPP to add a phony target for each dependency other than the main file, causing each one to depend on nothing ๐ป. These dummy rules work around errorsmakegives if you remove header files without updating the Makefile to match ๐ ๏ธ
This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ changes the target of the rule emitted by dependency generation ๐ฏ. By default, CPP takes the name of the main input file, deletes any directory components and any file suffix such as.c, and appends the platform's usual object suffix. The 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.
For example, -MT '$(objpfx)foo.o' might give
$(objpfx)foo.o: foo.c
-MQ targetโ same as-MT, but it quotes any characters which are special to Make ๐งท.-MQ '$(objpfx)foo.o'gives
$$(objpfx)foo.o: foo.c
The default target is automatically quoted, as if it were given with -MQ ๐
-MDโ-MDis equivalent to-M -MF file, except that-Eis not implied ๐ฅ. The driver determines file based on whether an-ooption is given. If it is, the driver uses its argument but with a suffix of.d. Otherwise, it takes the name of the input file, removes any directory components and suffix, and applies a.dsuffix ๐.
If -MD is used in conjunction with -E, any -o switch is understood to specify the dependency output file, but if used without -E, each -o is understood to specify a target object file ๐ง
Since -E is not implied, -MD can be used to generate a dependency output file as a side effect of the compilation process ๐
-MMDโ like-MDexcept it mentions only user header files, not system header files ๐-fpreprocessedโ ๐ okay so this flag tells the preprocessor "bestie, this file is ALREADY preprocessed, don't touch it" ๐ โโ๏ธ It skips macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives. Comments still get recognized and removed, so you can pass in a file made with-Cwith zero drama โจ In this mode the integrated preprocessor is basically just a tokenizer for the front ends ๐ง Also,-fpreprocessedis implicit if your input file ends in.i,.iior.mi. Those are the extensions GCC uses for preprocessed files made by-save-temps๐-fdirectives-onlyโ ๐ธ When preprocessing, this handles directives but does NOT expand macros. How it acts depends on-Eand-fpreprocessed, so let's break it down:- With
-E, preprocessing is limited to directives like"#define","#ifdef", and"#error". Macro expansion and trigraph conversion are skipped, and-dDgets turned on automatically ๐ฆ - With
-fpreprocessed, predefinition of command line macros and most builtin macros is turned off. Contextual macros like__LINE__still get handled normally. This is what lets you compile files that were previously run through-E -fdirectives-only๐ - With both
-Eand-fpreprocessed, the-fpreprocessedrules win. This gives you full preprocessing of files that were previously run through-E -fdirectives-only๐
- With
-fdollars-in-identifiersโ ๐ Lets$show up inside identifiers. Accepted, no cap.-fextended-identifiersโ ๐ Accepts universal character names and extended characters in identifiers. This one is on by default for C99 (and later C standards) and C++, so it's literally already on for you ๐ซถ-fno-canonical-system-headersโ ๐ When preprocessing, this stops system header paths from getting shortened with canonicalization.-fmax-include-depth=depthโ ๐งถ Sets the max depth of nested#includes. Default is200.-ftabstop=widthโ ๐ Sets the distance between tab stops. This helps the preprocessor report correct column numbers in warnings or errors, even when tabs are on the line. If the value is less than1or greater than100, the option gets ignored. Default is8๐-ftrack-macro-expansion[=level]โ ๐ Tracks token locations across macro expansions, so when an error happens inside a macro, the compiler can show you the current macro expansion stack. Heads up: this makes the preprocessor and compiler eat more memory ๐ฝ๏ธ The level parameter lets you pick how precise the tracking is, so you can drop memory use if you need to:0turns this off1tracks locations in a degraded mode for minimal memory overhead. In this mode, every token coming from expanding an argument of a function-like macro gets the same location2tracks locations completely. This is the most memory hungry option ๐- With no argument at all, the default level is
2
Note that -ftrack-macro-expansion=2 is activated by default โจ
-fmacro-prefix-map=old=newโ ๐บ๏ธ When preprocessing files living in directory old, the__FILE__and__BASE_FILE__macros get expanded as if those files lived in directory new instead. You can use.for new to turn an absolute path into a relative one, which can lead to more reproducible, location-independent builds ๐ง This also affects__builtin_FILE()during compilation. See also-ffile-prefix-map.-fexec-charset=charsetโ ๐ค Sets the execution character set used for string and character constants. Default isUTF-8. charset can be any encoding the system'siconvlibrary routine supports.-fwide-exec-charset=charsetโ ๐ Sets the wide execution character set, used for wide string and character constants. The default is one ofUTF-32BE,UTF-32LE,UTF-16BE, orUTF-16LE, whichever matches the width ofwchar_tand the big-endian or little-endian byte order used for code generation. Just like-fexec-charset, charset can be any encodingiconvsupports. โ ๏ธ Fair warning though: you'll have problems with encodings that don't fit exactly inwchar_t.-finput-charset=charsetโ ๐ฅ Sets the input character set, used for translating from the input file's character set into the source character set GCC uses. If the locale doesn't specify one, or GCC can't get it from the locale, the default isUTF-8. The locale or this command-line option can override it, but if they conflict, the command-line option wins ๐ charset can be any encodingiconvsupports.-fpch-depsโ ๐ When you're using precompiled headers, this makes the dependency-output flags also list the files from the precompiled header's dependencies. Without it, only the precompiled header gets listed, not the files used to create it, because those files aren't consulted when a precompiled header is used ๐-fpch-preprocessโ ๐งฉ This lets you use a precompiled header together with-E. It inserts a special#pragmainto the output,#pragma GCC pch_preprocess "filename", to mark where the precompiled header was found, plus its filename. When-fpreprocessedis in use, GCC recognizes this#pragmaand loads the PCH ๐ซถ- This option is off by default, because the preprocessed output is only really suitable as input to GCC. It gets switched on by
-save-temps. - You shouldn't write this
#pragmain your own code. But it's totally 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.
- This option is off by default, because the preprocessed output is only really suitable as input to GCC. It gets switched on by
-fworking-directoryโ ๐ Turns on linemarkers in the preprocessor output that tell the compiler what the working directory was at preprocessing time. When it's on, the preprocessor emits a second linemarker after the initial one, containing the current working directory followed by two slashes. GCC uses that directory, when it's present in the preprocessed input, as the working directory in some debugging information formats. This is implicitly enabled if debugging information is enabled, but you can block it with the negated form-fno-working-directory. If the-Pflag is in the command line, this option does nothing, since no#linedirectives get emitted whatsoever ๐ซ-A predicate=answerโ ๐ช Makes an assertion with the predicate predicate and the answer answer. This form is the preferred one over the older-A predicate(answer), which is still supported, because it doesn't use shell special characters ๐-A -predicate=answerโ โ Cancels an assertion with the predicate predicate and the answer answer. Bye bye ๐-Cโ ๐ฌ Keeps your comments! Everything gets passed through to the output file, except comments inside processed directives, which get deleted along with the directive.- Be prepared for side effects with
-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#๐ญ
- Be prepared for side effects with
-CCโ ๐ Keeps 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
-Cside effects,-CCconverts 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 ๐ -CCis generally used to support lint comments.
- On top of the
-Pโ ๐ค Stops linemarkers from showing up in the preprocessor output. This could come in handy when you're running the preprocessor on something that isn't C code and will get sent to a program that might get confused by linemarkers.-traditional,-traditional-cppโ ๐ฐ๏ธ These try to imitate the behavior of pre-standard C preprocessors, instead of ISO C preprocessors. Check the GNU CPP manual for details.- GCC doesn't try to emulate a pre-standard C compiler otherwise, and these options only work with the
-Eswitch, or when you invoke CPP explicitly.
- GCC doesn't try to emulate a pre-standard C compiler otherwise, and these options only work with the
-trigraphsโ ๐บ Supports ISO C trigraphs. These are three-character sequences that all start with??, which ISO C defines as stand-ins 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โ ๐๏ธ Turns on special code to work around file systems that only allow very short file names, like MS-DOS ๐พ-Hโ ๐ Prints the name of each header file used, on top of the other normal stuff. Each name is indented to show how deep it is in the#includestack ๐ฟ Precompiled header files get printed too, even if they turn out to be invalid. An invalid precompiled header is printed with...x, and a valid one with...!โ-dlettersโ ๐งช Tells GCC to make debugging dumps during compilation, as specified by letters. The flags documented here are the ones relevant to the preprocessor. Other letters are interpreted by the compiler proper, or reserved for future versions of GCC, so they're silently ignored. If you specify letters whose behavior conflicts, the result is undefined ๐-dMโ ๐ Instead of the normal output, this generates a list of#definedirectives for all the macros defined during the execution of the preprocessor, including predefined macros. It's a super easy way to find out what's predefined in your version of the preprocessor ๐ฎ Assuming you have no filefoo.h, the command
okay so the easiest way to see every predefined macro your compiler has baked in is this ๐
touch foo.h; cpp -dM foo.h
and bestie, it spits out all of them ๐คฏ main character energy.
Heads up ๐: if you use-dMwithout the-Eoption,-dMgets treated as a synonym for-fdump-rtl-mach. Not me getting plot-twisted ๐ญ
-dDโ this one is like-dMbut with two twists ๐ธ It skips 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โ basically-dD, but chill. It only emits the macro names, not their expansions ๐ง-dIโ adds#includedirectives to the output, on top of the preprocessing result ๐-dUโ like-dD, except only macros that get expanded, or whose definedness gets tested in preprocessor directives, make the cut โจ The output is delayed until the use or test of the macro, and#undefdirectives also show up for macros that were tested but undefined at that time ๐-fdebug-cppโ ngl this one is only for debugging GCC itself ๐ค When it's used from CPP or with-E, it dumps debugging info about location maps, and every token in the output gets the dump of the map its location belongs to. When it's used from GCC without-E, it does absolutely nothing ๐-Wp,optionโ lets you skip the compiler driver and sendoptionstraight through to the preprocessor ๐ Ifoptionhas commas, it gets split into multiple options at the commas. BUT ๐จ a lot of options get modified, translated or interpreted by the driver before they reach the preprocessor, and-Wpforcibly bypasses 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โ passesoptionto the preprocessor ๐ง Use it for system-specific preprocessor options that GCC doesn't recognize. If you want to pass an option that takes an argument, you need to use-Xpreprocessortwice: once for the option and once for the argument.-no-integrated-cppโ preprocessing gets its own separate pass before compilation ๐ช By default, GCC preprocesses as an integrated part of input tokenization and parsing. With this flag, the appropriate language front end (cc1,cc1plus, orcc1objfor C, C++, and Objective-C, respectively) gets invoked twice: once for preprocessing only, and once for actual compilation of the preprocessed input. It can be handy alongside the-Bor-wrapperoptions to use an alternate preprocessor, or to do extra processing on your source between normal preprocessing and compilation ๐-flarge-source-filesโ for when your files are HUGE ๐ It makes GCC expect large source files, at the cost of slower compilation and higher memory usage. Normally GCC tracks both column numbers and line numbers, and prints both in diagnostics. But once it has processed a certain number of source lines, it stops tracking column numbers and only tracks line numbers. So diagnostics for later lines don't include column numbers, and options like-Wmisleading-indentationstop working at that point, although the compiler prints a note if this happens ๐ Passing-flarge-source-filessignificantly 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 ๐ซ
-Wa,optionโ passesoptionto the assembler ๐ช Ifoptionhas commas, it gets split into multiple options at the commas.-Xassembler optionโ passesoptionto the assembler too ๐ซง Use it for system-specific assembler options that GCC doesn't recognize. If you want to pass an option that takes an argument, you need to use-Xassemblertwice: once for the option and once for the argument.
๐ Options for Linking ๐
These options come into play when the compiler links object files into an executable output file. They're meaningless if the compiler isn't doing a link step ๐
object-file-nameโ 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 their contents, not us ๐ต๏ธ) If linking is done, these object files get used as input to the linker.-c,-S,-Eโ if any of these is used, the linker doesn't run, so object file names shouldn't be used as arguments ๐ซ-flinker-output=typeโ 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 incremental linking with a non-LTO object file is desired, it may be useful to control the type manually. The options for type are:execโ code generation produces a static binary. In this case-fpicand-fpieare both disabled.dynโ code generation produces a shared library. In this case-fpicor-fPICis preserved, but not enabled automatically. This allows building shared libraries without position-independent code on architectures where that's possible, i.e. on x86.pieโ code generation produces an-fpieexecutable. This gives similar optimizations asexec, except that-fpieis not disabled if it was specified at compilation time.relโ the compiler assumes incremental linking is happening. The sections containing intermediate code for link-time optimization are merged, pre-optimized, and output to the resulting object file. In addition, if-ffat-lto-objectsis specified, binary code is produced for future non-LTO linking. The object file produced by incremental linking is smaller than a static library produced from the same object files. At link time, the result of incremental linking also loads faster than a static library, assuming that the majority of objects in the library are 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 is stripped. When multiple object files are linked together, the resulting code is better optimized than with link-time optimizations disabled (for example, cross-module inlining happens), but most of the benefits of whole program optimizations are lost.
During the incremental link (by -r) the linker plugin defaults to rel. With current interfaces to GNU Binutils, it is however not possible to incrementally link LTO objects and non-LTO objects into a single mixed object file. If any of the object files in an incremental link cannot be used for link-time optimization, the linker plugin issues a warning and uses nolto-rel. To maintain whole program optimization, it is recommended to link such objects into a static library instead. Alternatively, it is possible to use H.J. Lu's binutils with support for 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โ searches the library namedlibrarywhen linking. (The second form, with the library as a separate argument, is only 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. The directories searched include several standard system directories, plus any that you specify with -L.
Static libraries are archives of object files, and have file names like liblibrary.a. Some targets also support shared libraries, which typically have names like liblibrary.so. If both static and shared libraries are found, the linker gives preference to linking with 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 are specified. Thus, 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 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 are passed to the linker, and options specifying linkage of the system libraries, such as-static-libgccor-shared-libgcc, are ignored. The standard startup files are used normally, unless-nostartfilesis used.
The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc.
Heads up ๐จ: these entry points should be supplied through some other mechanism when this option is specified.
-nolibcโ don't use the C library, or the system libraries tightly coupled with it, when linking. It still links with the startup files, libgcc, or toolchain-provided language support libraries such aslibgnat,libgfortranorlibstdc++, unless options preventing their inclusion are used as well. This typically removes-lcfrom the link command line, along with system libraries that normally go with it and become meaningless when a C library is assumed absent, for example-lpthreador-lmin some configurations. This is intended for bare-board targets when there is indeed 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 are passed to the linker. Options specifying 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 bestie, when you use this flag, those entry points have to be supplied some other way ๐ญ.
One of the standard libraries that -nostdlib and -nodefaultlibs bypass is libgcc.a ๐ง. It's a library of internal subroutines that GCC uses to work around shortcomings of certain machines or to meet the special needs of some languages ๐
.
Honestly, you usually still need libgcc.a even when you're trying to skip the other standard libraries โจ. So if you specify -nostdlib or -nodefaultlibs, you should usually add -lgcc too ๐ฅ. That way you have no unresolved references to internal GCC library subroutines. (An example of one of those internal subroutines is __main, which makes sure C++ constructors get called ๐.)
-e entry,--entry=entryโ Sets the program entry point to entry ๐ฆ. The linker is the one who reads this value, and the GNU linker will take either a symbol name or an address.-pieโ Makes a dynamically linked position independent executable on targets that support it ๐. For predictable results, you also need to use the same compilation options you used for the build (-fpie,-fPIE, or model suboptions) when you pass this linker option โจ.-no-pieโ Skips making a dynamically linked position independent executable ๐.-static-pieโ Makes a static position independent executable on targets that support it ๐ธ. It's kind of like a static executable, except it can be loaded at any address without a dynamic linker, which is so iconic ๐. Same deal as before: for predictable results, use the same set of options you compiled with (-fpie,-fPIE, or model suboptions) when you use this linker option ๐ .-pthreadโ Links with the POSIX threads library ๐งต. This one is supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets ๐. On some targets it also sets flags for the preprocessor, so use it consistently for both compilation and linking, periodt ๐.-rโ Produces a relocatable object as the 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 to the dynamic symbol table, not only the ones that are used ๐. It's needed for some uses ofdlopen, or if you want to get backtraces from inside a program ๐ฅ.-sโ Strips all symbol table and relocation information out of the executable ๐.-staticโ On systems that support dynamic linking, this overrides-pieand stops the linking with shared libraries ๐ซถ. On other systems it does absolutely nothing ๐.-sharedโ Makes a shared object that can then be linked with other objects to form an executable ๐. Not every system supports this one. For predictable results, you also need to use the same set of compilation options (-fpic,-fPIC, or model suboptions) when you pass 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 the static version, respectively ๐ธ. If no shared version of libgcc was built when the compiler was configured, these options do nothing ๐.
There are a few situations where an application should use the shared libgcc instead of the static one ๐ฆ. The biggest one is when the app wants to throw and catch exceptions across different shared libraries ๐ญ. In that case, every one of 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 typically use exceptions, so this is the right move, no cap โจ.
Now, if you use the GCC driver to create shared libraries, you might notice they aren't always 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 the option --eh-frame-hdr, it links the shared version of libgcc into shared libraries by default ๐ง. Otherwise, it takes advantage of the linker and optimizes away the linking with the shared version of libgcc, so it links with the static version by default ๐
. This lets exceptions propagate through those shared libraries without adding relocation costs at library load time ๐.
However, if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ driver, or using the option -shared-libgcc, so that it's linked with the shared libgcc ๐จ.
-static-libasanโ When-fsanitize=addressis used to link a program, the GCC driver automatically links against libasan ๐. If libasan is available as a shared library and-staticisn't used, it links against the shared version of libasan ๐ธ. This option tells the GCC driver to link libasan statically, without necessarily linking other libraries statically โจ.-static-libtsanโ When-fsanitize=threadis used to link a program, the GCC driver automatically links against libtsan ๐งต. If libtsan is available as a shared library and-staticisn't used, it links against the shared version of libtsan ๐. This option tells the GCC driver to link libtsan statically, without necessarily linking other libraries statically ๐ฆ.-static-liblsanโ When-fsanitize=leakis used to link a program, the GCC driver automatically links against liblsan ๐ซง. If liblsan is available as a shared library and-staticisn't used, it links against the shared version of liblsan ๐. This option tells the GCC driver to link liblsan statically, without necessarily linking other libraries statically ๐ท.-static-libubsanโ When-fsanitize=undefinedis used to link a program, the GCC driver automatically links against libubsan ๐. If libubsan is available as a shared library and-staticisn't used, it links against the shared version of libubsan ๐. 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-staticisn't used, it links against the shared version of libstdc++, and that's normally fine ๐ . But sometimes it's useful 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 you override that with the link editor option-Xlinker -z -Xlinker defs๐. Only a few systems support this one, so it's a bit of a rare bird ๐ฆ.-T scriptโ Uses script as the linker script ๐. This is supported by most systems that use the GNU linker ๐. On some targets, like bare-board targets without an operating system, you might need-Twhen linking to avoid references to undefined symbols ๐.-Xlinker optionโ Passes option along to the linker as an option ๐ง. Use this for system-specific linker options that GCC doesn't recognize, bestie ๐ .
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 that passes the entire string as one single argument, and the linker is not vibing with that ๐.
With the GNU linker, it's usually way 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 instead of -Xlinker -Map -Xlinker output.map โจ. Other linkers might not support this syntax for command-line options ๐.
-Wl,optionโ Passes option along to the linker as an option ๐ธ. If option contains commas, it gets split into multiple options at those commas ๐ช. You can use this syntax to pass an argument to the option โจ. For example,-Wl,-Map,output.mappasses-Map output.mapto the linker ๐บ๏ธ. When you're using the GNU linker, you can get the same effect with-Wl,-Map=output.map๐.
NOTE: In Ubuntu 8.10 and later versions, for LDFLAGS, the option-Wl,-z,relrois used. To disable it, use-Wl,-z,norelroโ ๏ธ.
-u symbolโ Pretends the symbol is 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โ-zis passed straight on to the linker, along with the keyword ๐งต. Check the section in your linker's documentation for the permitted values and what they mean ๐.
โจ Options for Directory Search โจ
These options specify the directories to search for header files, for libraries, and for parts of the compiler ๐.
-I dir,-iquote dir,-isystem dir,-idirafter dirโ Adds the directory dir to the list of directories searched for header files during preprocessing ๐. If dir begins with=or$SYSROOT, then that=or$SYSROOTgets replaced by the sysroot prefix. See--sysrootand-isysrootfor the details ๐ณ.
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 #include "file" and #include <file> ๐.
You can specify any number or combination of these options on the command line to search for header files in several directories at once ๐. The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first ๐.
- ๐ For the quote form of the include directive, the
-iquotedirectories get searched left-to-right, in the same order they show up on the command line ๐ - ๐ธ
-Idirectories get scanned left-to-right ๐ธ - ๐ฆ
-isystemdirectories get scanned left-to-right ๐ฆ - ๐๏ธ The standard system directories get scanned ๐๏ธ
- ๐ง
-idirafterdirectories get scanned left-to-right ๐ง
ngl, this search order is the whole vibe ๐ญ You can use -I to override a system header file and swap in your own version, because those directories get searched before the standard system header file directories. BUT bestie, don't use -I to add directories that hold 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 โจ
Lowkey the most important part: if a standard system include directory, or a directory given with -isystem, is also given with -I, the -I option gets ignored ๐ The directory still gets searched, but as a system directory at its normal spot in the system include chain. This is so 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-โ Okay, this one is deprecated ๐ so please don't start new stuff with it. Use-iquoteinstead for the-Idirectories that come before the-I-, then remove the-I-option.
Any directories given with -I options before -I- only get searched for headers requested with "#include "file"". They are not searched for "#include <file>". If more directories come with -I options after the -I-, those get searched for all #include directives.
Also, -I- stops the directory of the current file from being used as the first search directory for "#include "file"". There is no way to override this effect of -I- ๐
-iprefix prefixโ Setprefixas the prefix for the later-iwithprefixoptions ๐ If the prefix represents a directory, make sure you include the final/.-iwithprefix dir,-iwithprefixbefore dirโ Tackdironto the prefix you set earlier with-iprefix, and add the resulting directory to the include search path ๐ง-iwithprefixbeforeputs it in the same place-Iwould, and-iwithprefixputs it where-idirafterwould.-isysroot dirโ This is like the--sysrootoption, but it only applies to header files ๐ (Except on Darwin targets, where it applies to both header files and libraries.) Check out the--sysrootoption for more info.-imultilib dirโ Usediras a subdirectory of the directory that holds the target-specific C++ headers ๐-nostdincโ Don't search the standard system directories for header files ๐ Only the directories you explicitly give with-I,-iquote,-isystem, and/or-idirafterget searched, plus the directory of the current file if it applies.-nostdinc++โ Skip the C++-specific standard directories when looking for headers, but still search the other standard directories ๐ฆ (This one is used when building the C++ library.)-iplugindir=dirโ Sets the directory to search for plugins that get passed with-fplugin=name, instead of-fplugin=path/name.so. This isn't meant for you to use directly. It's only passed along by the driver ๐ค-Ldirโ Adddirto the list of directories searched for-lโจ-Bprefixโ This option tells the compiler where to find its own executables, libraries, include files, and data files ๐บ๏ธ
The compiler driver program runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for each program it tries to run, both with and without machine/version/ for the corresponding target machine and compiler version.
For each subprogram to be run, the driver first tries the -B prefix, if there is one. If that name isn't found, or if -B isn't specified, the driver tries two standard prefixes, /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those turns up a file, the unmodified program name is searched for using the directories in your PATH environment variable.
The compiler checks to see if the path given by -B refers to a directory, and if needed it adds a directory separator character at the end of the path.
-B prefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into -L options for the linker. They also apply to include files in the preprocessor, because the compiler translates these options into -isystem options for the preprocessor. In this case, the compiler appends include to the prefix.
The runtime support file libgcc.a can also be searched for using the -B prefix, if needed. If it isn't found there, the two standard prefixes above are tried, and that is all. The file is left out of the link if it isn't found by those means.
Another way to specify a prefix that works much like the -B prefix is to use the environment variable GCC_EXEC_PREFIX.
๐ As a special kludge, if the path given by-Bis[dir/]stageN/, whereNis a number in the range 0 to 9, then it gets replaced by[dir/]include. This is there 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โ Usediras the logical root directory for headers and libraries ๐ฑ For example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it searchesdir/usr/includeanddir/usr/libinstead.
If you use both this option and 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 aspect of --sysroot still works, but the library aspect doesn't.
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory given with--sysroot, depending on the other options used. That means headers might be found indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off the addition of that suffix ๐ซ
๐ Options for Code Generation Conventions ๐
These machine-independent options control the interface conventions used in code generation ๐
Most of them have both positive and negative forms, and the negative form of -ffoo is -fno-foo. In the table below, only one of the forms is listed, the one that is not the default. You can figure out the other form by either removing no- or adding it ๐ง
-fstack-reuse=reuse-levelโ This one 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 the 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 the lifetime of a variable ends, and if the variable lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range doesn't overlap with it. Legacy code that extends local lifetime is likely to break with the stack reuse optimization ๐ญ
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example:
struct A
{
A(int k) : i(k), j(k) { }
int i;
int j;
};
A *ap;
void foo(const A& ar)
{
ap = &ar;
}
void bar()
{
foo(A(10)); // temp object's lifetime ends when foo returns
{
A a(20);
....
}
ap->i+= 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
}
The lifetime of a compiler-generated temporary is well defined by the C++ standard. When the lifetime of a temporary ends, and if the temporary lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range doesn't overlap with it. However, some legacy code relies on the behavior of older compilers, where temporaries' stack space is not reused, so aggressive stack reuse can lead to runtime errors ๐ฅ This option is used to control the temporary stack reuse optimization.
-ftrapvโ This option generates traps for signed overflow on addition, subtraction, and multiplication operations ๐จ The options-ftrapvand-fwrapvoverride each other, so using-ftrapv -fwrapvon the command line results in-fwrapvbeing effective. Note that only active options override, so using-ftrapv -fwrapv -fno-wrapvon the command line results in-ftrapvbeing effective ๐-fwrapvโ bestie, this one tells the compiler to just assume signed addition, subtraction, and multiplication overflow wraps around using twos-complement representation ๐โจ. It turns on some optimizations and turns off others.-ftrapvand-fwrapvare beefing with each other, so-ftrapv -fwrapvmeans-fwrapvwins ๐. Only the active options fight, though, so-ftrapv -fwrapv -fno-wrapvgives you-ftrapv๐ .-fwrapv-pointerโ same energy, but for pointer arithmetic. It assumes pointer overflow on addition and subtraction wraps around using twos-complement representation ๐ฆ. It also disables some optimizations that assume pointer overflow is invalid ๐.-fstrict-overflowโ this one implies-fno-wrapv -fno-wrapv-pointer๐ฅ. Flip it to the negated version and it implies-fwrapv -fwrapv-pointerinstead ๐ซถ.-fexceptionsโ enables exception handling and generates the extra code needed to propagate exceptions ๐. Heads up: on some targets this implies GCC generates frame unwind information for all functions, which can cause significant data size overhead ๐ญ. It doesn't affect execution though โจ. By default, GCC turns this on for languages like C++ that normally need exception handling, and turns it off for languages like C that don't ๐ธ. You might still need it when compiling C code that has to play nicely with exception handlers written in C++ ๐ง. You might also want to disable it if you're compiling older C++ programs that don't use exception handling ๐.-fnon-call-exceptionsโ lets trapping instructions throw exceptions ๐. Real talk, this needs platform-specific runtime support that doesn't exist everywhere ๐. It only lets trapping instructions throw, meaning memory references or floating-point instructions ๐ฆ. It does not let exceptions come out of arbitrary signal handlers like"SIGALRM"๐ โโ๏ธ.-fdelete-dead-exceptionsโ instructions that might throw but don't otherwise contribute to the program's execution can get optimized away ๐๏ธโจ. This is on by default for the Ada compiler, which the Ada language spec allows ๐. Optimization passes that remove dead exceptions are enabled separately at different optimization levels ๐ .-funwind-tablesโ kinda like-fexceptions, except it only generates any needed static data and leaves the generated code alone ๐. You usually don't need to turn this on yourself, because any language processor that needs it will enable it for you ๐ซถ.-fasynchronous-unwind-tablesโ generates an unwind table in DWARF format, as long as the target machine supports it ๐ง. The table is exact at each instruction boundary, so it can be used for stack unwinding from asynchronous events, like a debugger or garbage collector ๐โจ.-fno-gnu-uniqueโ okay so, with a recent GNU assembler and C library, the C++ compiler uses the"STB_GNU_UNIQUE"binding ๐. That keeps template static data members and static local variables in inline functions unique, even with"RTLD_LOCAL"๐. This matters because a library used by two different"RTLD_LOCAL"plugins could otherwise disagree about the binding of a symbol ๐ญ. The catch is that it makesdlcloseget ignored for affected DSOs ๐. If your program relies on reinitializing a DSO throughdlcloseanddlopen, use-fno-gnu-unique๐.-fpcc-struct-returnโ returns"short""struct"and"union"values in memory, just like 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 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โ returns"struct"and"union"values in registers whenever it can ๐. It's more efficient than-fpcc-struct-returnfor small structures ๐ . If you specify neither flag, GCC uses whichever convention is standard for the target ๐ฏ. If there's no standard convention, GCC defaults to-fpcc-struct-return, except on targets where GCC is the principal compiler ๐. In those cases GCC can pick the standard itself, and it chose the more efficient register return option ๐.
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 an"enum"type only as many bytes as it needs for its declared range of values ๐ฑ. The"enum"type ends up equivalent to the smallest integer type that has enough room ๐งฉ.
Warning: -fshort-enums makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface ๐จ.
-fshort-wcharโ overrides the underlying type for"wchar_t"to be"short unsigned int"instead of the target's default ๐. This is handy for building programs that run under WINE ๐ท.
Warning: -fshort-wchar makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface ๐จ.
-fcommonโ in C code, this controls where global variables defined without an initializer get placed ๐ฆ. Those are called tentative definitions in the C standard, and they're different fromexterndeclarations, which don't allocate any storage ๐ซง.
The default is -fno-common, which means the compiler puts uninitialized global variables in the BSS section of the object file ๐๏ธ. This stops the linker from merging tentative definitions, so you 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 behavior is inconsistent with C++, and on many targets it implies a speed and code size penalty on global variable references ๐ข. It's mainly useful for getting legacy code to link without errors ๐ฅน.
-fno-identโ ignores the#identdirective ๐.-finhibit-size-directiveโ doesn't output a.sizeassembler directive, or anything else that would cause trouble if the function gets split in the middle with the two halves placed far apart in memory ๐งฉ. This one is used when compilingcrtstuff.c, and you shouldn't need it for anything else ๐ซ.-fverbose-asmโ adds extra commentary to the generated assembly code so it's easier to read ๐. This is generally only useful for people who actually need to read the generated assembly, like when they're debugging the compiler itself ๐งโ๐ป.
-fno-verbose-asm, which is the default, leaves that extra info out ๐ซฅ. It's 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.
Here's an example. Say you've got this C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
If you compile it to (x86_64) assembly with -S and send the result straight to stdout with -o -, like this:
gcc -S test.c -fverbose-asm -Os -o -
you'll get 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
Heads up: the comments are meant for humans rather than machines, so the precise format of the comments is subject to change ๐ซถ.
-frecord-gcc-switchesโ okay so this one makes GCC stash the exact command line you used to invoke the compiler right inside the object file it's making ๐ผ. It's only implemented on some targets, and the exact format depends on the target and binary file format, but it usually shows up as a section full of ASCII text ๐งพ. Don't mix it up with-fverbose-asm! That one only drops info into the assembler output as comments, so it never reaches the object file ๐ . For another way to store compiler options in the object file, see also-grecord-gcc-switches๐.-fpicโ generate position-independent code (PIC) that's ready for a shared library, if the target machine supports it ๐ฆ. This code reaches all constant addresses through a global offset table (GOT) โจ. The dynamic loader fills in the GOT entries when the program starts (and the dynamic loader is NOT part of GCC, it's part of the operating system, bestie ๐ ). If the GOT size for the linked executable goes over a machine-specific max, the linker throws an error saying-fpicdoesn't work, so just recompile with-fPICinstead ๐ญ. (The maxes are 8k on the SPARC, 28k on AArch64, and 32k on the m68k and RS/6000. The x86 has no such limit ๐.) PIC needs special support, so it only works on certain machines. For the x86, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent ๐. When this flag is set, the macros"__pic__"and"__PIC__"are defined to1โจ.-fPICโ if the target machine supports it, this emits position-independent code that's suitable for dynamic linking and doesn't have any limit on the size of the global offset table ๐. It makes a real difference on AArch64, m68k, PowerPC and SPARC ๐ฅ. Like before, it needs special support, so it only works on certain machines. When this flag is set,"__pic__"and"__PIC__"are defined to2๐.-fpie,-fPIEโ these are giving the same vibe as-fpicand-fPIC, but the position-independent code can only be linked into executables ๐. Usually you'll use these to compile code that gets linked with the-pieGCC option ๐ง. Both of them define"__pie__"and"__PIE__". The macros have the value1for-fpieand2for-fPIE๐ซถ.-fno-pltโ no PLT for external function calls in position-independent code, bestie ๐ . Instead, it loads the callee address at call sites from the GOT and branches to it. This leads to more efficient code by eliminating PLT stubs and exposing 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 requires the PLT, so with-fno-pltall external symbols get resolved at load time โฑ๏ธ. Alternatively, the function attribute"noplt"can be used to avoid calls through the PLT for specific external functions ๐ธ. In position-dependent code, a few targets also convert calls to functions that are marked to not use the PLT so they use the GOT instead ๐ง .-fno-jump-tablesโ do not use jump tables for switch statements, even where they'd be more efficient than other code generation strategies ๐. This is useful alongside-fpicor-fPICwhen 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 need a GOT, so this option isn't needed there ๐.-fno-bit-testsโ do not use bit tests for switch statements, even where it would be more efficient than other code generation strategies ๐.-ffixed-regโ treat the register named reg as a fixed register, so generated code should never refer to it (except maybe as a stack pointer, frame pointer, or in some other fixed role) ๐. reg must be the name of a register. The accepted register names are machine-specific and are defined in the"REGISTER_NAMES"macro in the machine description macro file ๐๏ธ. This flag has no negative form, because it's a three-way choice ๐.-fcall-used-regโ treat the register named reg as an allocable register that gets clobbered by function calls ๐. It may be allocated for temporaries or variables that don't live across a call. Functions compiled this way do not save and restore the register reg ๐ฌ. It is an error to use this flag with the frame pointer or stack pointer. Using it for other registers that have fixed, pervasive roles in the machine's execution model produces disastrous results ๐. No negative form, because it's a three-way choice ๐.-fcall-saved-regโ treat the register named reg as an allocable register that's saved by functions ๐ก๏ธ. It may be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restore the register reg if they use it ๐พ. It is an error to use this flag with the frame pointer or stack pointer. Using it on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results ๐. A different sort of disaster happens if you use this flag on a register where function values may be returned ๐ญ. No negative form, because it's a three-way choice ๐.-fpack-struct[=n]โ without a value, this packs all structure members together with no holes ๐งฑ. When you give it a value (which must be a small power of two), it packs structure members according to that value, which represents the maximum alignment. Objects with default alignment requirements larger than this get output potentially unaligned at the next fitting location ๐.
โ ๏ธ Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. It also makes the code suboptimal ๐. Only use it to conform to a non-default application binary interface ๐ซ .
-fleading-underscoreโ this option and its counterpart,-fno-leading-underscore, forcibly change the way C symbols are represented in the object file ๐. One big use is helping you link with legacy assembly code ๐๏ธ.
โ ๏ธ Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface. Also, not all targets provide complete support for this switch ๐ฅฒ.
-ftls-model=modelโ change the thread-local storage model that gets used ๐งต. The model argument should be one ofglobal-dynamic,local-dynamic,initial-execorlocal-exec๐ฏ. Heads up, the choice is subject to optimization: the compiler might use a more efficient model for symbols that aren't visible outside of the translation unit, or if-fpicisn't given on the command line โจ. The default without-fpicisinitial-exec. With-fpic, the default isglobal-dynamic๐ .-ftrampolinesโ for targets that normally need trampolines for nested functions, this always generates them instead of using descriptors ๐ช. For targets that don't need them, like HP-PA or IA-64, it does nothing ๐คท. A trampoline is a small piece of code that gets created at run time on the stack when the address of a nested function is taken, and it's used to call the nested function indirectly ๐. Because of that, it requires the stack to be made executable for the program to work properly ๐จ.
-fno-trampolines is enabled by default on a language-by-language basis, so the compiler can avoid generating trampolines if it figures that's safe, and swap them out 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-trampolines is enabled by default only for Ada ๐. Also, code compiled with -ftrampolines and code compiled with -fno-trampolines are not binary compatible if nested functions are present ๐ต. This option must be used on a program-wide basis and handled with extreme care ๐ซฃ.
-fvisibility=[default|internal|hidden|protected]โ this sets the default ELF image symbol visibility to the option you pick. All symbols get marked with it unless they're overridden within the code ๐ฎ. Using this can substantially improve linking and load times of shared object libraries, produce more optimized code, give you near-perfect API export, and prevent symbol clashes ๐ค. It's strongly recommended that you use this in any shared objects you distribute ๐.
Despite the nomenclature, default always means public, i.e., available to be linked against from outside the shared object ๐. protected and internal are pretty useless in real-world usage, so the only other commonly used option is hidden ๐. The default if -fvisibility isn't specified is default, i.e., every symbol is made public ๐. For a good explanation of the benefits of making sure ELF symbols have the correct visibility, check out "How To Write Shared Libraries" by Ulrich Drepper (which can be found at <https://www.akkadia.org/drepper/>) ๐. A superior solution this option makes possible, compared to marking things hidden when the default is public, is to make the default hidden and mark things public instead ๐. That's the norm with DLLs on Windows. With -fvisibility=hidden and "__attribute__ ((visibility("default")))" used instead of "__declspec(dllexport)", you get almost identical semantics with identical syntax ๐ซถ. This is a total great boon for anyone working on cross-platform projects ๐ฆโจ
For anyone adding visibility to code that already exists ๐ง, #pragma GCC visibility is your friend โจ. You wrap the declarations you care about in #pragma GCC visibility push(hidden) and close it with #pragma GCC visibility pop ๐
. Real talk: symbol visibility is part of the API interface contract, so all new code should spell out its visibility whenever it isn't the default ๐ซถ. Declarations that only get used inside the local DSO should always be marked explicitly as hidden, which dodges PLT indirection overheads ๐. Writing it out this clearly also makes the code way more readable and self-documenting ๐. Also, thanks to ISO C++ spec requirements, operator new and operator delete must always have default visibility ๐ฅ.
Be careful with headers from outside your project, especially system headers and headers from any other library you use ๐. They may not be expecting to be compiled with visibility other than the default. You might need to say #pragma GCC visibility push(default) before including any of them ๐ธ.
extern declarations aren't affected by -fvisibility, so a lot of code can be recompiled with -fvisibility=hidden with zero modifications ๐ฆ. The catch is that calls to extern functions with no explicit visibility go through the PLT, so it's way more effective to use __attribute ((visibility)) and/or #pragma GCC visibility to tell the compiler which extern declarations should be treated as hidden ๐.
Also, -fvisibility does affect C++ vague linkage entities โญ. So an exception class that gets thrown between DSOs must be explicitly marked with default visibility, so that the type_info nodes are unified between the DSOs ๐ญ.
If you want the full tea on these techniques, their benefits and how to use them, check out <http://gcc.gnu.org/wiki/Visibility> ๐.
โจ -fstrict-volatile-bitfields โจ
Use this one when accesses to volatile bit-fields (or other structure fields, though the compiler usually honors those types anyway) should be a single access at the width of the field's type, aligned to a natural alignment if possible ๐. For example, targets with memory-mapped peripheral registers might require every access to be 16 bits wide. With this flag, you can declare all the peripheral bit-fields as unsigned short (assuming short is 16 bits on those targets) to force GCC to use 16-bit accesses instead of a maybe more efficient 32-bit access ๐ฅ.
If this option is disabled, the compiler goes for the most efficient instruction ๐โโ๏ธ. In the previous example, that might be a 32-bit load instruction, even though it touches bytes that don't contain any part of the bit-field, or memory-mapped registers unrelated to the one being updated ๐.
In some cases, like when the packed attribute is applied to a structure field, it might not be possible to access the field with a single read or write that's correctly aligned for the target machine ๐. In that case GCC falls back to generating multiple accesses, instead of code that would fault or truncate the result at run time. Safe and sound ๐ซถ.
Note: Due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members ๐ญ. It's therefore recommended to define all bits of the field's type as bit-field members.
The default value of this option is determined by the application binary interface for the target processor ๐ง.
โจ -fsync-libcalls โจ
This option controls whether any out-of-line instance of the __sync family of functions may be used to implement the C++11 __atomic family of functions ๐ฆ.
The default is enabled, so the only useful form of this option is -fno-sync-libcalls ๐. This option is used in the implementation of the libatomic runtime library ๐.
๐ ๏ธ GCC Developer Options
This section covers command-line options that are mainly of interest to GCC developers ๐งโ๐ป. That includes options that support compiler testing and investigation of compiler bugs and compile-time performance problems ๐. It also covers options that produce debug dumps at various points in compilation, options that print statistics like memory use and execution time, and options that print info about GCC's configuration, like where it searches for libraries ๐. You should rarely need any of these for ordinary compilation and linking tasks ๐.
Lots of developer options that make GCC dump output to a file take an optional =filename suffix โจ. You can specify stdout or - to dump to standard output, and stderr for standard error ๐
.
If =filename is omitted, a default dump file name gets built by concatenating the base dump file name, a pass number, a phase letter, and the pass name ๐งฉ. The base dump file name is the name of the output file the compiler produces, if you explicitly specified one and it isn't an executable. Otherwise, it's the source file name ๐. The pass number is determined by the order passes are registered with the compiler's pass manager ๐ข. That's usually the same as the execution order, but passes registered by plugins, target-specific passes, or passes that get registered late are numbered higher than the pass named final, even if they run earlier ๐ซ . The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree) ๐ธ. The files get created in the directory of the output file ๐.
โจ -fcallgraph-info โจ
โจ -fcallgraph-info=MARKERS โจ
This makes the compiler output callgraph information for the program, on a per-object-file basis ๐ธ๏ธ. 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 ๐. When the su marker is specified, the callgraph gets decorated with stack usage info, which is equivalent to -fstack-usage ๐ฅ. When the da marker is specified, the callgraph gets decorated with info about dynamically allocated objects ๐ง .
When you compile with -flto, no callgraph info is output along with the object file ๐
โโ๏ธ. At LTO link time, -fcallgraph-info may generate multiple callgraph info files right next to the intermediate LTO output files ๐.
โจ -dletters, -fdump-rtl-pass, -fdump-rtl-pass=filename โจ
Okay, this is the debugging dump zone ๐ฌ. These make debugging dumps during compilation at times specified by letters. They're used for debugging the RTL-based passes of the compiler ๐งช.
Some -dletters switches mean something different when -E is used for preprocessing ๐.
You can enable debug dumps with a -fdump-rtl switch or with some -d option letters ๐. Here are the possible letters you can use in pass and letters, and what they mean ๐:
-fdump-rtl-alignmentsโ 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 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โ okay bestie, this one dumps after sign/zero extension elimination ๐งนโจ-fdump-rtl-seqabstrโ dumps after common sequence discovery ๐๐-fdump-rtl-shortenโ dumps after shortening branches ๐ฆ-fdump-rtl-siblingโ dumps after sibling call optimizations ๐ธ-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ these five are giving "do it five times" energy ๐ each one turns on a dump after one of five rounds of instruction splitting ๐-fdump-rtl-smsโ dumps after modulo scheduling ๐ง this pass is only run on some architectures, so don't be shocked if it's missing on yours-fdump-rtl-stackโ dumps after converting GCC's "flat register file" registers into the x87's stack-like registers ๐ this pass is only run on x86 variants-fdump-rtl-subreg1,-fdump-rtl-subreg2โ these two enable dumping after the two subreg expansion passes ๐ซถ-fdump-rtl-unshareโ dumps after all rtl has been unshared ๐-fdump-rtl-vartrackโ dumps after variable tracking ๐-fdump-rtl-vregsโ dumps after converting virtual registers to hard registers ๐-fdump-rtl-webโ dumps after live range splitting ๐ธ๏ธ-fdump-rtl-regclass,-fdump-rtl-subregs_of_mode_init,-fdump-rtl-subregs_of_mode_finish,-fdump-rtl-dfinit,-fdump-rtl-dfinishโ these are defined but they always produce empty files ๐
Heads up, bestie: those five always produce empty files, so don't panic when you open one and it's giving nothing ๐ญ
-da,-fdump-rtl-allโ produce all the dumps listed above ๐-dAโ annotates the assembler output with miscellaneous debugging information ๐ง-dDโ dumps all macro definitions at the end of preprocessing, in addition to the normal output ๐-dHโ produces a core dump whenever an error occurs ๐ฅ-dpโ annotates the assembler output with a comment indicating which pattern and alternative is used ๐ the length and cost of each instruction get printed too-dPโ dumps the RTL in the assembler output as a comment before each instruction โจ it also turns on-dpannotation-dxโ just generates RTL for a function instead of compiling it ๐ฆ usually used with-fdump-rtl-expand-fdump-debugโ dumps the debugging information generated during the debug generation phase ๐-fdump-earlydebugโ dumps the debugging information generated during the early debug generation phase โฐ-fdump-noaddrโ when doing debugging dumps, suppresses address output ๐ this makes it way more feasible to diff debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations-freport-bugโ collects and dumps debug information into a temporary file if an internal compiler error (ICE) occurs ๐จ-fdump-unnumberedโ when doing debugging dumps, suppresses instruction numbers and address output ๐ข this makes diffing dumps way easier for invocations with different options, especially with and without-g-fdump-unnumbered-linksโ when doing debugging dumps (see-doption above), suppresses instruction numbers for the links to the previous and next instructions in a sequence ๐-fdump-ipa-switch,-fdump-ipa-switch-optionsโ these control the dumping at various stages of inter-procedural analysis language tree to a file ๐๏ธ the file name is generated by appending a switch specific suffix to the source file name, and the file is created in the same directory as the output file. the possible dumps are:allโ enables all inter-procedural analysis dumpscgraphโ dumps information about call-graph optimization, unused function removal, and inlining decisionsinlineโ dumps after function inlining
Additionally, the options -optimized, -missed, -note, and -all can be provided, with the same meaning as for -fopt-info, defaulting to -optimized.
For example, -fdump-ipa-inline-optimized-missed will emit information on callsites that were inlined, along with callsites that were not inlined ๐
By default, the dump will contain messages about successful optimizations (equivalent to -optimized) together with low-level details about the analysis.
-fdump-langโ dumps language-specific information ๐ท the file name is made by appending.langto the source file name-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ these control the dumping of language-specific information ๐ the options and filename parts behave as described in the-fdump-treeoption. the accepted switch values are:allโ enables all language-specific dumpsclassโ dumps class hierarchy information. virtual table information is emitted unless 'slim' is specified. this one is C++ only ๐moduleโ dumps module information. the options lineno (locations), graph (reachability), blocks (clusters), uid (serialization), alias (mergeable), asmname (Elrond), eh (mapper) & vops (macros) may provide additional information. this one is C++ only ๐งrawโ dumps the raw internal tree data. this one is C++ only ๐ชต
-fdump-passesโ prints onstderrthe list of optimization passes that are turned on and off by the current command-line options ๐-fdump-statistics-optionโ enables and controls dumping of pass statistics in a separate file ๐ the file name is generated by appending a suffix ending in.statisticsto the source file name, and the file is created in the same directory as the output file. if the-optionform is used,-statscauses counters to be summed over the whole compilation unit while-detailsdumps every event as the passes generate them. the default with no option is to sum counters for each function compiled.-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filenameโ these control the dumping at various stages of processing the intermediate language tree to a file ๐ณ if the-optionsform is used, options is a list of--separated options that control the details of the dump. not all options are applicable to all dumps, and the ones that aren't meaningful get ignored. the following options are available:addressโ prints the address of each node ๐ usually this isn't meaningful, since it changes according to the environment and source file. its main use is tying up a dump file with a debug environmentasmnameโ if "DECL_ASSEMBLER_NAME" has been set for a given decl, that gets used in the dump instead of "DECL_NAME" ๐ฎ its main use is working backward from mangled names in the assembly fileslimโ when dumping front-end intermediate representations, inhibits dumping of members of a scope or body of a function merely because that scope has been reached. only dumps those items when they're directly reachable by some other path ๐ฅ- when dumping pretty-printed trees, this option inhibits dumping the bodies of control structures
- when dumping RTL, the RTL is printed in slim (condensed) form instead of the default LISP-like representation
rawโ prints a raw representation of the tree ๐งพ by default, trees are pretty-printed into a C-like representationdetailsโ enables more detailed dumps (not honored by every dump option) ๐ also includes information from the optimization passesstatsโ enables dumping various statistics about the pass (not honored by every dump option) ๐blocksโ enables showing basic block boundaries (disabled in raw dumps) ๐งฑgraphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a representation of the control flow graph suitable for viewing with GraphViz to file.passid.pass.dot ๐บ๏ธ each function in the file is pretty-printed as a subgraph, so GraphViz can render them all in a single plot. this option currently only works for RTL dumps, and the RTL is always dumped in slim formvopsโ 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 information (only available in certain passes) โmissedโ enables showing missed optimization information (only available in certain passes) โnoteโ enables other detailed optimization information (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 what tree dumps are available, or to find the dump for a pass you're after, follow the steps below ๐ต๏ธโโ๏ธ
- Invoke GCC with
-fdump-passes, then look in thestderroutput for a code that matches the pass you're interested in. for example, the codes "tree-evrp", "tree-vrp1", and "tree-vrp2" correspond to the three Value Range Propagation passes. the number at the end distinguishes distinct invocations of the same pass ๐ - To enable the creation of the dump file, append the pass code to the
-fdump-option prefix and invoke GCC with it. for example, to enable the dump from the Early Value Range Propagation pass, invoke GCC with-fdump-tree-evrp. optionally, you may specify the name of the dump file. if you don't specify one, GCC creates one as described below ๐ - Hunt down the pass dump in a file named with three bits joined by periods: the source file GCC was invoked to compile, then a numeric suffix for the pass number with a
tfor tree passes (or anrfor RTL passes), then 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, bestie: those numeric codes are not stable and can change from one GCC version to another ๐
โจ OPTIONS โจ
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ optimization dump central ๐ฆ These control dumps from the various optimization passes. If you use the-optionsform, options is a list of--separated keywords that pick the dump details and which optimizations you want.
The options come in three groups, and you can mix and match within each group since they don't overlap. If there's a clash, the later option on the command line wins ๐
- Options that describe what kinds of messages get emitted
- Options that describe how verbose the dump is
- Options that describe which optimizations get included
Message kinds (group 1) ๐
optimizedโ successful glow-ups! Prints info whenever an optimization gets applied. Each pass decides what's relevant. The vectorizer, for example, prints the source location of loops that got successfully vectorized.missedโ Info about optimizations that didn't happen. Each pass picks what goes in here ๐noteโ Verbose stuff about optimizations, like certain transformations and more detailed messages about decisions โจallโ The full tea โ Detailed optimization info, which includesoptimized,missed, andnote.
Verbosity (group 2) ๐ง
internalsโ By default you only get the "high-level" messages. This one unlocks extra, more detailed messages that are mostly for GCC developers. Not for the faint of heart ๐
Optimization groups (group 3) ๐ You can use one or more of these keywords to target a whole group of optimizations:
ipaโ Dumps from all interprocedural optimizations.loopโ Dumps from all loop optimizations.inlineโ Dumps from all inlining optimizations.ompโ Dumps from all OMP (Offloading and Multi Processing) optimizations.vecโ Dumps from all vectorization optimizations.optallโ Dumps from literally every optimization. It's a superset of the groups above, so it's giving everything ๐
If options is left out, it defaults to optimized-optall. That means you get messages about successful optimizations from all the passes, minus anything treated as "internals" ๐
If you pass a filename, the dumps from all the applicable optimizations get concatenated into that file. Otherwise, the dump goes to stderr. You can throw in multiple -fopt-info options, but only one of them can carry a filename. If you give other filenames, all but the first such option get ignored ๐ฅบ
Heads up: the output filename gets overwritten when you have multiple translation units. If you want one combined output from several translation units, use stderr instead!
Here's the vibe check with examples. First, the optimization info goes to stderr:
gcc -O3 -fopt-info
This one dumps the missed optimization report from all the passes into missed.all:
gcc -O3 -fopt-info-missed=missed.all
And this one prints info about missed optimization opportunities from the vectorization passes on stderr. Note that -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec. The order of the optimization group names and message types after -fopt-info does not matter, so slay however you like ๐
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
Another one, which outputs info about missed optimizations and optimized locations from all the inlining passes into inline.txt:
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
Finally, consider this one ๐
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Here, the two output filenames vec.miss and loop.opt are in conflict, since only one output file is allowed. Only the first option takes effect and the rest get ignored. So you only end up with vec.miss, which has the vectorizer's dumps about missed opportunities. Not me being chaotic, the compiler just be like that ๐ญ
-fsave-optimization-recordโ the machine-readable receipts ๐งพ This writes aSRCFILE.opt-record.json.gzfile detailing which optimizations were performed, for the ones that support-fopt-info.
Sis, this option is experimental, and the format of the data inside the compressed JSON file is subject to change. Don't build your whole life on it yet ๐
It's roughly the machine-readable version of -fopt-info-all, as a collection of messages with source file, line number, and column number. Each message also gets this extra data:
- the execution count of the code being optimized, plus metadata about whether it came from actual profile data or was just an estimate, so consumers can prioritize messages by code hotness ๐ฅ
- the function name of the code being optimized, where that applies
- the "inlining chain" for the code being optimized, so when a function gets inlined into several 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 those categories they are, and, when available, their source code location
- the GCC pass that emitted the message
- the location in GCC's own code where the message came from
Also, some messages are logically nested inside other messages, reflecting implementation details of the optimization passes ๐ง
-fsched-verbose=nโ scheduler tea, served hot โ On targets that use instruction scheduling, this controls how much debugging output the scheduler dumps into the dump files.
For n greater than zero, -fsched-verbose outputs the same info as -fdump-rtl-sched1 and -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 the RTL at the abort point, plus control-flow and regions info. And for n over four, -fsched-verbose also includes dependence info. Iconic levels, honestly ๐
-fenable-kind-pass,-fdisable-kind-pass=range-listโ the pass on/off switches ๐ This is a set of options for explicitly disabling and enabling optimization passes. They're meant for debugging GCC itself. If you're just a regular compiler user, stick with the regular options for enabling and disabling passes instead ๐
Here's the full menu:
-fdisable-ipa-passโ Disables the IPA pass pass, where pass is the pass name. If the same pass gets statically invoked in the compiler multiple times, append a sequential number to the pass name, starting from 1.-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ Disables the RTL pass pass, where pass is the pass name. Same deal with the sequential number if the pass runs more than once. 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 a function's call graph node uid falls within one of the specified ranges, the pass gets disabled for that function. The uid shows up in the function header of a dump file, and you can dump the pass names using-fdump-passes.-fdisable-tree-pass,-fdisable-tree-pass=range-listโ Disables the tree pass pass. Check-fdisable-rtl-passfor how the option arguments work.-fenable-ipa-passโ Enables the IPA pass pass, where pass is the pass name. Same sequential numbering rule as above, starting from 1.-fenable-rtl-pass,-fenable-rtl-pass=range-listโ Enables the RTL pass pass. Check-fdisable-rtl-passfor the option argument description and examples.-fenable-tree-pass,-fenable-tree-pass=range-listโ Enables the tree pass pass. Check-fdisable-rtl-passfor how the option arguments work.
Here are some examples of these options in action ๐
# disable ccp1 for all functions
-fdisable-tree-ccp1
# disable complete unroll for function whose cgraph node uid is 1
-fenable-tree-cunroll=1
# disable gcse2 for functions at the following ranges [1,1],
# [300,400], and [400,1000]
# disable gcse2 for functions foo and foo2
-fdisable-rtl-gcse2=foo,foo2
# disable early inlining
-fdisable-tree-einline
# disable ipa inlining
-fdisable-ipa-inline
# enable tree full unroll
-fenable-tree-unroll
-fchecking,-fchecking=nโ internal vibe checks ๐ Enables internal consistency checking. The default depends on how the compiler was configured.-fchecking=2turns on further internal consistency checking that might affect code generation.-frandom-seed=stringโ the reproducibility queen ๐ธ This 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. Use-frandom-seedto produce reproducibly identical object files, which is honestly so main character ๐ซถ
The string can be a number (decimal, octal, or hex) or an arbitrary string. If it's an arbitrary string, it gets converted to a number by computing CRC32 โจ
The string should be totally different for every file you compile, bestie ๐ no copy-pasting the same one everywhere!
-save-tempsโ okay so this one keeps the usual "temporary" intermediate files around permanently ๐พ Instead of tossing them, they get named as auxiliary output files, the same way described under-dumpbaseand-dumpdir.
Pairing -save-temps with the -x command-line option is lowkey genius ๐ง It won't overwrite an input source file that shares an extension with an intermediate file. If you want that intermediate file, just rename the source file before using -save-temps.
-save-temps=cwdโ same energy as-save-temps -dumpdir ./.๐
-save-temps -dumpdir ./.
-save-temps=objโ this one puts everything in the output file's folder ๐ฆ It's equivalent to-save-temps -dumpdir outdir/, whereoutdir/is the directory of the output file given after the-ooption, including any directory separators. No-o? Then it acts exactly like-save-temps=cwd.-time[=file]โ reports the CPU time each subprocess in the compilation sequence takes โฑ๏ธ For C source files, that's the compiler proper and the assembler (plus the linker if you're linking).
Without an output file, you get something like this:
# cc1 0.12 0.01
# as 0.00 0.01
The first number on each line is the "user time", which is the time spent running the program itself. The second is the "system time", the time spent in operating system routines on the program's behalf. Both numbers are in seconds ๐ซถ
With an output file, the report gets appended to that file and looks like this:
0.12 0.01 cc1 <options>
0.00 0.01 as <options>
Now the "user time" and "system time" get moved before the program name, and the options passed to the program are shown too. That way you can totally tell later which file was being compiled and with which options ๐ต๏ธโโ๏ธ
-fdump-final-insns[=file]โ dumps the final internal representation (RTL) to file ๐งฉ If the optional argument is left out (or file is"."), the dump file gets named by slapping".gkd"onto the dump base name. See-dumpbasefor the deets.-fcompare-debug[=opts]โ this one is a whole vibe ๐ If there's no error during compilation, the compiler runs a second time, adding opts and-fcompare-debug-secondto the arguments for that second go. It dumps the final internal representation in both compilations and prints an error if they differ.
If you skip the equal sign, the default -gtoggle is used.
The environment variable GCC_COMPARE_DEBUG, if it's defined, non-empty, and nonzero, implicitly enables -fcompare-debug. If GCC_COMPARE_DEBUG is set to a string starting with a dash, that string is used for opts. Otherwise the default -gtoggle is used ๐
-fcompare-debug=, with the equal sign but no opts, is the same as -fno-compare-debug. That turns off the dumping of the final representation and the second compilation, and it even stops GCC_COMPARE_DEBUG from taking effect ๐
โโ๏ธ
To verify full coverage during-fcompare-debugtesting, setGCC_COMPARE_DEBUGto say-fcompare-debug-not-overridden. GCC rejects that as an invalid option in any actual compilation (rather than preprocessing, assembly or linking), so it's a whole thing. If you only want a warning, settingGCC_COMPARE_DEBUGto-w%n-fcompare-debug not overriddenwill do the trick โ ๏ธ
-fcompare-debug-secondโ this gets passed to the compiler implicitly for the second compilation requested by-fcompare-debug๐ฅ It comes along with options to silence warnings, and it leaves out any other options that would make the compiler produce output to files or to standard output as a side effect. Dump files and preserved temporary files get renamed to include the".gk"additional extension during that second compilation, so they don't overwrite the ones from the first run.
When you pass this option to the compiler driver, it skips the first compilation entirely. Honestly, that makes it pretty much only useful for debugging the compiler proper ๐ค
-gtoggleโ turns off debug info generation if leaving this option out would generate it, or turns it on at level 2 otherwise ๐ Where it sits on the command line doesn't matter. It takes effect after all the other options are processed, and it only does its thing once, no matter how many times you give it. It's mainly meant to be used with-fcompare-debug.-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-assignments, the same way-gtoggletoggles-g๐๏ธ-Qโ makes the compiler print out each function name as it gets compiled, and print some statistics about each pass when it finishes ๐-ftime-reportโ makes the compiler print some statistics about the time consumed by each pass when it's done โณ-ftime-report-detailsโ records the time consumed by infrastructure parts separately for each pass ๐ฌ-fira-verbose=nโ controls how verbose the dump file for the integrated register allocator is ๐๏ธ The default value is5. If the value n is greater than or equal to10, the dump output gets sent to stderr, using the same format as n minus 10.-flto-reportโ prints a report with internal details on how the link-time optimizer is working ๐ง The contents change from version to version. It's meant to be useful to GCC developers when processing object files in LTO mode (via-flto).
It's disabled by default, so you have to ask for it ๐โโ๏ธ
-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 statistics about permanent memory allocation when it finishes ๐ง ๐พ-fmem-report-wpaโ makes the compiler print some statistics about permanent memory allocation for the WPA phase only ๐ฏ-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ makes the compiler print some statistics about permanent memory allocation either before or after interprocedural optimization ๐ง-fprofile-reportโ makes the compiler print some statistics about the consistency of the (estimated) profile and the effect of individual passes ๐-fstack-usageโ makes the compiler output stack usage information for the program, on a per-function basis ๐ฅ The filename for the dump is made by appending.suto the auxname. The auxname comes from the name of the output file, if you explicitly specified one and it's not an executable. Otherwise it's the basename of the source file.
Each entry has three fields:
- The name of the function.
- A number of bytes.
- One or more qualifiers: "static", "dynamic", "bounded".
The "static" qualifier means the function manipulates the stack statically ๐งฑ A fixed number of bytes gets allocated for the frame on function entry and released on function exit, and no other stack adjustments happen in the function. The second field is that fixed number of bytes.
The "dynamic" qualifier means the function manipulates the stack dynamically ๐ On top of the static allocation, stack adjustments happen in the body of the function, for example to push and pop arguments around function calls. If "bounded" is also present, the amount of those adjustments is bounded at compile time, and the second field is an upper bound on the total amount of stack the function uses. If "bounded" isn't there, the amount of adjustments isn't bounded at compile time, and the second field only represents the bounded part.
-fstatsโ emits statistics about front-end processing at the end of the compilation ๐ Only the C++ front end supports this, and the info is generally only really useful to the G++ development team ๐งโ๐ป-fdbg-cnt-listโ prints the name and the counter upper bound for all debug counters ๐-fdbg-cnt=counter-value-listโ sets the internal debug counter lower and upper bounds ๐๏ธ counter-value-list is a comma-separated list ofname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]tuples. Each one sets the counter's name and a list of closed intervals. Thelower_boundis optional and gets zero initialized if it isn't set.
For example, with -fdbg-cnt=dce:2-4:10-11,tail_call:10, dbg_cnt(dce) returns true only for the second, third, fourth, tenth and eleventh invocation โจ And for dbg_cnt(tail_call), true is returned for the first 10 invocations ๐
-print-file-name=libraryโ prints the full absolute name of the library file library that would be used when linking, and then stops there ๐จ๏ธ 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 selected by any other switches on the command line ๐ That directory is supposed to exist inGCC_EXEC_PREFIX.-print-multi-libโ prints the mapping from multilib directory names to the compiler switches that enable them ๐บ๏ธ The directory name is separated from the switches by;. Each switch starts with@instead of-, with no spaces between multiple switches, which is meant 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 thelibsubdirectory and no multilibs are used, this is usually just.. If they're inlibsuffixsibling directories, it prints something like../lib64,../libor../lib32. If they're inlib/subdirsubdirectories, it prints something likeamd64,sparcv9orev6.-print-multiarchโ prints the path to the OS libraries for the selected multiarch, relative to somelibsubdirectory ๐น-print-prog-name=programโ works like-print-file-name, but searches for a program, such ascpp, instead ๐-print-libgcc-file-nameโ same as-print-file-name=libgcc.a๐
This one is clutch when you use -nostdlib or -nodefaultlibs but still want to link with libgcc.a ๐ You can do something like this:
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, and then stops there ๐๏ธ
Okay so this bit is SO important when gcc starts yelling installation problem, cannot exec cpp0: No such file or directory ๐ญ There are two ways to fix it, bestie: either put cpp0 and the other compiler components exactly where gcc expects to find them, or set the environment variable GCC_EXEC_PREFIX to the directory where you installed them ๐ซถ And don't forget the trailing /! ๐
-print-sysrootโ Prints the target sysroot directory that gets used during compilation ๐บ๏ธ That's the one set at configure time or with the--sysrootoption, possibly with an extra suffix depending on your compilation options. No target sysroot? It prints nothing ๐-print-sysroot-headers-suffixโ Prints the suffix tacked onto the target sysroot when gcc is hunting for headers. If the compiler wasn't configured with one, it throws an error instead. Either way, it doesn't do anything else ๐ซ-dumpmachineโ Prints the compiler's target machine, likei686-pc-linux-gnu, and then stops right there ๐ง-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 (major version), two numbers separated by a dot (major and minor version), or three numbers separated by dots (major, minor and patchlevel version).-dumpfullversionโ Prints the full compiler version and nothing else โจ The output is always three numbers separated by dots: major, minor and patchlevel version.-dumpspecsโ Prints the compiler's built-in specs and nothing else ๐ธ (This is only used when GCC itself is being built.)
๐ฆ Machine-Dependent Options ๐ฆ
Every target machine GCC supports can have its own options, bestie ๐ Think: compiling for a particular processor variant or ABI, or tweaking optimizations that are specific to that machine. By convention, the names of machine-specific options start with -m ๐
Some configurations also support extra target-specific options, usually so they can play nicely with other compilers on the same platform ๐
โจ AArch64 Options โจ
These options are defined for AArch64 implementations ๐
-mabi=nameโ Generates code for the specified data model ๐ง The valid values areilp32, a SysV-like model whereint,long intand pointers are 32 bits, andlp64, a SysV-like model whereintis 32 bits butlong intand pointers are 64 bits. The default depends on your specific target configuration. Heads up, bestie: the LP64 and ILP32 ABIs are not link-compatible ๐ญ You have to compile your entire program with the same ABI and link it against a compatible set of libraries.-mbig-endianโ Generates big-endian code ๐ This is the default when GCC is configured for anaarch64_be-*-*target.-mgeneral-regs-onlyโ Only uses the general-purpose registers ๐ This stops the compiler from touching the floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler.-mlittle-endianโ Generates little-endian code ๐ซถ This is the default when GCC is configured for anaarch64-*-*target but not anaarch64_be-*-*target.-mcmodel=tinyโ Generates code for the tiny code model ๐ฃ The program and its statically defined symbols must be within 1MB of each other. Programs can be statically or dynamically linked.-mcmodel=smallโ Generates code for the small code model ๐ท The program and its statically defined symbols must be within 4GB of each other. Programs can be statically or dynamically linked. This is the default code model.-mcmodel=largeโ Generates code for the large code model ๐ It makes no assumptions about addresses and sizes of sections. Programs can only be statically linked. Also,-mcmodel=largeis incompatible with-mabi=ilp32,-fpicand-fPIC๐ซ-mstrict-align,-mno-strict-alignโ Avoid or allow generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification ๐-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ Omit or keep the frame pointer in leaf functions ๐ The former behavior is the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generates stack protection code using a canary atguard๐ก๏ธ The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register. With thesysregchoice,-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsetpick which system register is used as the base register for reading the canary, and what offset from that base register to use. There's no default register or offset, because this is entirely for use within the Linux kernel ๐ง-mtls-dialect=descโ Uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables ๐ This is the default.-mtls-dialect=traditionalโ Uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐ฐ๏ธ-mtls-size=sizeโ Specifies the bit size of immediate TLS offsets. The valid values are12,24,32and48. This option requires binutils 2.26 or newer ๐ง-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ Enables or disables the workaround for ARM Cortex-A53 erratum number 835769 ๐ฉน This involves inserting a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions.-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419โ Enables or disables the workaround for ARM Cortex-A53 erratum number 843419 ๐ฉน This erratum workaround is done at link time, so this option only passes the corresponding flag to the linker.-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ Enables or disables the reciprocal square root approximation ๐งฎ This only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of reciprocal square root results to about 16 bits for single precision and 32 bits for double precision.-mlow-precision-sqrt,-mno-low-precision-sqrtโ Enables or disables the square root approximation ๐งฎ This only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of square root results to about 16 bits for single precision and 32 bits for double precision. If enabled, it implies-mlow-precision-recip-sqrt.-mlow-precision-div,-mno-low-precision-divโ Enables or disables the division approximation โ This only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of division results to about 16 bits for single precision and 32 bits for double precision.-mtrack-speculation,-mno-track-speculationโ Enables or disables generating extra code to track 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โ Enables or disables calls to out-of-line helpers that implement atomic operations โ๏ธ These helpers figure out at runtime whether the LSE instructions from ARMv8.1-A can be used. If they can't, they fall back to the load/store-exclusive instructions that are present in the base ARMv8.0 ISA.
This option is only applicable when compiling for the base ARMv8.0 instruction set. If you're using a later revision, like -march=armv8.1-a or -march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for -mcpu= when the selected CPU supports the lse feature. This option is on by default ๐
-march=nameโ Specifies the name of the target architecture and, optionally, one or more feature modifiers ๐๏ธ This option takes the form-march=arch{+[no]feature}*.
Here's the lowdown on the values for arch and what they turn on by default:
armv8-a(Armv8-A) โ includes by default:+fp,+simdarmv8.1-a(Armv8.1-A) โ includes by default:armv8-a,+crc,+lse,+rdmaarmv8.2-a(Armv8.2-A) โ includes by default:armv8.1-aarmv8.3-a(Armv8.3-A) โ includes by default:armv8.2-a,+pautharmv8.4-a(Armv8.4-A) โ includes by default:armv8.3-a,+flagm,+fp16fml,+dotprodarmv8.5-a(Armv8.5-A) โ includes by default:armv8.4-a,+sb,+ssbs,+predresarmv8.6-a(Armv8.6-A) โ includes by default:armv8.5-a,+bf16,+i8mmarmv8-r(Armv8-R) โ includes by default:armv8-r
The value native is available on native AArch64 GNU/Linux and makes the compiler pick the architecture of the host system ๐ฅ๏ธ This option has no effect if the compiler can't recognize the architecture of the host system,
The permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most feature wins ๐
GCC uses name to figure out what kind of instructions it can emit when generating assembly code. If -march is specified without -mtune or -mcpu also being specified, the code is tuned to perform well across a range of target processors that implement the target architecture ๐ฏ
-mtune=nameโ Specifies the name of the target processor that GCC should tune the performance of the code for ๐ The permissible values are:generic,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a65,cortex-a65ae,cortex-a34,cortex-a78,cortex-a78ae,cortex-a78c,ares,exynos-m1,emag,falkor,neoverse-512tvb,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-v1,neoverse-v2,grace,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,ampere1,ampere1a,cobalt-100andnative๐
okay so the big.LITTLE pairings are up next, bestie ๐ง these 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 all tell GCC to tune for a big.LITTLE system ๐
neoverse-512tvb is giving very specific energy โจ It tells GCC to tune for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle. So basically, GCC is tuned for Neoverse cores that can run 4 128-bit Advanced SIMD arithmetic instructions a cycle, plus 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 down below ๐ฆ
Also, on native AArch64 GNU/Linux systems, the value native tunes performance to whatever host system you're on ๐ฅ๏ธ If the compiler can't recognize the processor of the host system, this option just does nothing ๐
Where none of -mtune=, -mcpu= or -march= are specified, the code is tuned to perform well across a range of target processors ๐ And this option cannot be suffixed by feature modifiers ๐
โโ๏ธ
-mcpu=nameโ Pick the target processor, optionally with one or more feature modifiers tacked on the end ๐ The form is-mcpu=cpu{+[no]feature}*, and the allowed values forcpuare the same ones you get for-mtune. The allowedfeaturevalues are documented in the sub-sectionaarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you throw conflicting feature modifiers at it, the right-most one wins ๐ GCC usesnameto figure out what kind of instructions it's allowed to emit when generating assembly (as if you'd used-march), and which processor to tune performance for (as if you'd used-mtune) โจ If you use this together with-marchor-mtune, those take precedence over the matching part of this option ๐-mcpu=neoverse-512tvbis special, because it doesn't refer to one specific core. It refers to all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle ๐ฅ Unless you override it with-march,-mcpu=neoverse-512tvbgenerates code that can run on a Neoverse V1 core, since Neoverse V1 is the first Neoverse core with these properties ๐ซถ And unless you override it with-mtune,-mcpu=neoverse-512tvbtunes code the same way as-mtune=neoverse-512tvb๐ธ-moverride=stringโ Overrides the tuning decisions the back-end makes in response to a-mtune=switch ๐ Heads up: the syntax, semantics, and accepted values forstringare not guaranteed to stay consistent across releases. This option is only really meant for developing GCC itself ๐ง-mverbose-cost-dumpโ Turns on verbose cost model dumping in the debug dump files ๐ This one is only here for debugging the compiler ๐-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ Enables or disables PC-relative literal loads ๐ฆ With this option 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 permissible values arenone, which turns return address signing off;non-leaf, which enables pointer signing for functions that aren't leaf functions; andall, which enables pointer signing for all functions. The default isnone๐ This option has been deprecated by-mbranch-protection, so bestie, use that one instead ๐-mbranch-protection=none|standard|pac-ret[+leaf+b-key]|btiโ Picks which branch protection features to use ๐ก๏ธnoneis the default and turns off all types of branch protection.standardturns on all types of branch protection features, and if a feature has extra tuning options,standardsets it to its standard level.pac-ret[+leaf]turns on return address signing to its standard level, which means signing functions that save the return address to memory (non-leaf functions will practically always do this) using the a-key. The optionalleafargument extends the signing to include leaf functions ๐ The optionalb-keyargument lets you sign the functions with the B-key instead of the A-key. Andbtiturns 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 options:retbrandblr. On top of that,-mharden-sls=allenables all SLS hardening, while-mharden-sls=nonedisables all of it ๐-msve-vector-bits=bitsโ Specifies the number of bits in an SVE vector register ๐ This option only does something when SVE is enabled. GCC supports two forms of SVE code generation: "vector-length agnostic" output, which works with any size of vector register, and "vector-length specific" output, which lets GCC make assumptions about the vector length when that helps with optimization ๐ง The possible values ofbitsarescalable,128,256,512,1024and2048. Specifyingscalableselects vector-length agnostic output. Right now,-msve-vector-bits=128also generates vector-length agnostic output for big-endian targets. All the other values generate vector-length specific code. These values might change in future releases, so no value exceptscalableshould be relied on for code that's portable across different hardware SVE vector lengths โ ๏ธ The default is-msve-vector-bits=scalable, which produces vector-length agnostic code ๐ฆ
โจ -march and -mcpu Feature Modifiers โจ
Feature modifiers used with -march and -mcpu can be any of the following, and each one also has an inverse, nofeature ๐ Here's the full list, bestie:
crcโ Enables the CRC extension ๐ This is on by default for-march=armv8.1-acryptoโ Enables the Crypto extension ๐ This also enables Advanced SIMD and floating-point instructionsfpโ Enables floating-point instructions ๐ธ This is on by default for all possible values for-marchand-mcpusimdโ Enables Advanced SIMD instructions ๐ถ This also enables floating-point instructions. It's on by default for all possible values for-marchand-mcpusveโ Enables Scalable Vector Extension instructions ๐ This also enables Advanced SIMD and floating-point instructionslseโ Enables Large System Extension instructions ๐ This is on by default for-march=armv8.1-ardmaโ Enables Round Double Multiply Accumulate instructions ๐งฎ This is on by default for-march=armv8.1-afp16โ Enables the FP16 extension ๐ This also enables floating-point instructionsfp16fmlโ Enables the FP16 fmla extension ๐ This also enables FP16 extensions and floating-point instructions. It's enabled by default for-march=armv8.4-a. Using this with architectures prior to Armv8.2-A is not supported ๐rcpcโ Enables the RcPc extension ๐งฉ This doesn't change code generation from GCC, but it gets passed on to the assembler, so inline asm statements can use instructions from the RcPc extensiondotprodโ Enables the Dot Product extension ๐ญ This also enables Advanced SIMD instructionsaesโ Enables the Armv8-aaesandpmullcrypto extension ๐ This also enables Advanced SIMD instructionssha2โ Enables the Armv8-asha2crypto extension ๐ This also enables Advanced SIMD instructionssha3โ Enables thesha512andsha3crypto extension ๐ง This also enables Advanced SIMD instructions. Using this with architectures prior to Armv8.2-A is not supported ๐ซsm4โ Enables thesm3andsm4crypto extension ๐ This also enables Advanced SIMD instructions. Using this with architectures prior to Armv8.2-A is not supportedprofileโ Enables the Statistical Profiling extension ๐ This is only to turn the extension on at the assembler level, and it does not affect code generationrngโ Enables the Armv8.5-a Random Number instructions ๐ฒ This is only to turn the extension on at the assembler level, and it does not affect code generationmemtagโ Enables the Armv8.5-a Memory Tagging Extensions ๐ท๏ธ Using this with architectures prior to Armv8.5-A is not supportedsbโ Enables the Armv8-a Speculation Barrier instruction ๐ง This is only to turn the extension on at the assembler level, and it does not affect code generation. It's enabled by default for-march=armv8.5-assbsโ Enables the Armv8-a Speculative Store Bypass Safe instruction ๐ This is only to turn the extension on at the assembler level, and it does not affect code generation. It's enabled by default for-march=armv8.5-apredresโ Enables the Armv8-a Execution and Data Prediction Restriction instructions ๐ฎ This is only to turn the extension on at the assembler level, and it does not affect code generation. It's enabled by default for-march=armv8.5-asve2โ Enables the Armv8-a Scalable Vector Extension 2 ๐ This also enables SVE instructionssve2-bitpermโ Enables SVE2 bitperm instructions ๐งท This also enables SVE2 instructionssve2-sm4โ Enables SVE2 sm4 instructions ๐ This also enables SVE2 instructionssve2-aesโ Enables SVE2 aes instructions ๐๏ธ This also enables SVE2 instructionssve2-sha3โ Enables SVE2 sha3 instructions ๐ช This also enables SVE2 instructionstmeโ Enables the Transactional Memory Extension ๐งตi8mmโ Enables 8-bit Integer Matrix Multiply instructions ๐ข This also enables Advanced SIMD and floating-point instructions. It's enabled by default for-march=armv8.6-a. Using this with architectures prior to Armv8.2-A is not supported ๐ โโ๏ธf32mmโ Enables 32-bit Floating point Matrix Multiply instructions ๐งฑ This also enables SVE instructions. Using this with architectures prior to Armv8.2-A is not supportedf64mmโ Enables 64-bit Floating point Matrix Multiply instructions ๐ช This also enables SVE instructions. Using this with architectures prior to Armv8.2-A is not supported ๐bf16โ okay bestie, this one switches on brain half-precision floating-point instructions ๐ง โจ It also turns on Advanced SIMD and floating-point instructions. It's on by default for-march=armv8.6-a๐flagmโ enables the Flag Manipulation instructions Extension ๐ฉpauthโ enables the Pointer Authentication Extension ๐
Using bf16 with architectures prior to Armv8.2-A is not supported ๐
โโ๏ธ
Heads up: crypto implies aes, sha2, and simd, which implies fp. Conversely, nofp implies nosimd, which implies nocrypto, noaes and nosha2 ๐ซถ
๐ธ Adapteva Epiphany Options ๐ธ
These -m options are defined for Adapteva Epiphany ๐ง
-mhalf-reg-fileโ we don't allocate any register in the range"r32"..."r63". That lets your code run on hardware variants that don't have these registers ๐-mprefer-short-insn-regsโ prefers registers that allow short instruction generation. This can bump up the instruction count, so overall code size might go down or up ๐คทโโ๏ธ-mbranch-cost=numโ sets the cost of branches to roughly num"simple"instructions. It's just a heuristic, so don't expect consistent results across releases ๐-mcmoveโ enables the generation of conditional moves โจ-mnops=numโ emits num NOPs before every other generated instruction ๐ด-mno-soft-cmpsfโ for single-precision floating-point comparisons, it emits an"fsub"instruction and tests the flags. That's faster than a software comparison, but it can give incorrect results with NaNs, or when two different small numbers are compared and their difference comes out as zero ๐ฌ The default is-msoft-cmpsf, which uses slower but IEEE-compliant software comparisons ๐-mstack-offset=numโ sets the offset between the top of the stack and the stack pointer. For example, a value of 8 means the eight bytes in the range"sp+0...sp+7"can be used by leaf functions without stack allocation ๐ Values other than 8 or 16 are untested and unlikely to work. This option also changes the ABI, so compiling a program with a different stack offset than the libraries were built with generally doesn't work ๐ซ It's useful if you want to see whether a different stack offset gives you better code, but to actually build working programs, you should 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โ unless an attribute says otherwise, it assumes all calls might be beyond the offset range of the"b"/"bl"instructions. So it loads the function address into a register before doing a (otherwise direct) call. This is the default ๐-mshort-callsโ unless an attribute says otherwise, it assumes all direct calls are in range of the"b"/"bl"instructions, so it uses those instructions 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 the floating-point mode that's provided and expected at function call and return time. Matching this to the mode you mostly need at function start can make your programs smaller and faster by avoiding unnecessary mode switches ๐
mode can be set to one of the following values:
callerโ any mode at function entry is valid, and it's retained or restored when the function returns and when it calls other functions. This is useful for compiling libraries or other compilation units you might want to bring into different programs with different prevailing FPU modes. The convenience of using a single object file outweighs the size and speed overhead of any extra mode switching you'd need compared to a more specific choice of prevailing FPU mode ๐ซถtruncateโ the mode used for floating-point calculations with truncating (i.e. round towards zero) rounding mode. That includes conversion from floating point to integer ๐ธround-nearestโ the mode used for floating-point calculations with round-to-nearest-or-even rounding mode ๐intโ the mode used to perform integer calculations in the FPU, e.g. integer multiply, or integer multiply-and-accumulate ๐ข
The default is -mfp-mode=caller ๐
-mno-split-lohi,-mno-postinc,-mno-postmodifyโ code generation tweaks that disable, respectively, splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses. The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify๐ง-mnovect-doubleโ changes the preferred SIMD mode toSImode. The default is-mvect-double, which usesDImodeas the preferred SIMD mode ๐ถ-max-vect-align=numโ the maximum alignment for SIMD vector mode types. num may be 4 or 8, and the default is 8. Heads up: this is an ABI change, though lots of library function interfaces are unaffected as long as they don't use SIMD vector modes in places that affect the size and/or alignment of relevant types ๐-msplit-vecmove-earlyโ splits vector moves into single word moves before reload. In theory this can give better register allocation, but so far the reverse seems to be generally the case ๐-m1reg-regโ specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster โก Allowable values for reg arer43andr63, which use that register as a fixed register, andnone, which means no register is used for this purpose. The default is-m1reg-none๐
๐ฅ AMD GCN Options ๐ฅ
These options are defined specifically for the AMD GCN port ๐
-march=gpu,-mtune=gpuโ sets the architecture type or tuning for gpu. Supported values for gpu are: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 affect run-time performance. The default is 32KB when using OpenACC or OpenMP, and 1MB otherwise ๐ฆ-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. Right now this option is a placeholder for support that isn't implemented yet ๐ง
๐ฆ ARC Options ๐ฆ
The following options control the architecture variant the 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 call using thejli_sinstruction. This option is valid only for the ARCv2 architecture ๐-mcpu=cpuโ sets the architecture type, register usage, and instruction scheduling parameters for cpu. There are also shortcut alias options for backward compatibility and convenience. Supported values for cpu are: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 with"norm"instructions enabled ๐งarc600_mul32x16โ compile for ARC 600 CPU with"norm"and 32x16-bit multiply instructions enabled โ๏ธarc600_mul64โ compile for ARC 600 CPU with"norm"and"mul64"-family instructions enabled โ๏ธarc601_normโ compile for ARC 601 CPU with"norm"instructions enabled ๐งarc601_mul32x16โ compile for ARC 601 CPU with"norm"and 32x16-bit multiply instructions enabled โ๏ธarc601_mul64โ compile for ARC 601 CPU with"norm"and"mul64"-family instructions enabled โ๏ธnps400โ compile for ARC 700 on the NPS400 chip ๐em_miniโ compile for ARC EM minimalist configuration featuring a reduced register set ๐ฑ
-mdpfp,-mdpfp-compactโ generates double-precision FPX instructions, tuned for the compact implementation ๐-mdpfp-fastโ generates double-precision FPX instructions, tuned for the fast implementation โก-mno-dpfp-lrsrโ disables"lr"and"sr"instructions from using FPX extension aux registers ๐ซ-meaโ generates extended arithmetic instructions. Right now only"divaw","adds","subs", and"sat16"are supported. This is only valid for-mcpu=ARC700โจ-mno-mpyโ ๐ Skip the "mpy"-family instructions for ARC700. This one is deprecated, so please don't build new stuff around it ๐-mmul32x16โ โจ Turns on 32x16-bit multiply and multiply-accumulate instructions.-mmul64โ ๐ฅ Generates themul64andmulu64instructions. Only valid with-mcpu=ARC600, so don't try it anywhere else ๐ โโ๏ธ-mnormโ ๐ Generates thenorminstructions. This is already the default when-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โ ๐ฆ Turns on ARC SIMD instructions through target-specific builtins. Only valid with-mcpu=ARC700.-msoft-floatโ ๐ซ This one is basically ignored! It's only here for compatibility. Software floating-point code is emitted by default, and you can override that default with the FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision.-mswapโ ๐ Generatesswapinstructions.-matomicโ ๐ Enables the locked load/store conditional extension so the atomic memory built-in functions can work. Not available for ARC 6xx or ARC EM cores, so skip it there ๐ญ-mdiv-remโ โ Enables thedivandreminstructions for ARCv2 cores.-mcode-densityโ ๐ง Enables code density instructions for ARC EM. It's on by default for ARC HS.-mll64โ ๐ Enables double load/store operations for ARC HS cores.-mtp-regno=regnoโ ๐งต Sets the thread pointer register number.-mmpy-option=multoโ ๐ Compiles ARCv2 code with a multiplier design option. You can pick the option with a string or a number formulto, andwlh1is the default. Here's the menu:0ornoneโ No multiplier available.1orwโ 16x16 multiplier, fully pipelined. This enablesmpywandmpyuw.2orwlh1โ 32x32 multiplier, fully pipelined (1 stage). This also enablesmpy,mpyu,mpym,mpymu, andmpy_s.3orwlh2โ 32x32 multiplier, fully pipelined (2 stages). This also enablesmpy,mpyu,mpym,mpymu, andmpy_s.4orwlh3โ Two 16x16 multipliers, blocking, sequential. This also enablesmpy,mpyu,mpym,mpymu, andmpy_s.5orwlh4โ One 16x16 multiplier, blocking, sequential. This also enablesmpy,mpyu,mpym,mpymu, andmpy_s.6orwlh5โ One 32x4 multiplier, blocking, sequential. This also enablesmpy,mpyu,mpym,mpymu, andmpy_s.7orplus_dmpyโ ARC HS SIMD support.8orplus_macdโ ARC HS SIMD support.9orplus_qmacwโ ARC HS SIMD support.
This option is only available for ARCv2 cores โจ
-mfpu=fpuโ ๐ Turns on specific floating-point hardware extensions for ARCv2 cores. Here are the supported values forfpu:fpusโ Single-precision floating-point hardware extensions.fpudโ Double-precision floating-point hardware extensions. The single-precision extension gets enabled too. Not available for ARC EM.fpudaโ Double-precision extensions using double-precision assist instructions. The single-precision extension is also enabled. This is only for ARC EM.fpuda_divโ Double-precision extensions using double-precision assist instructions. The single-precision, square-root, and divide extensions are also enabled. ARC EM only.fpuda_fmaโ Double-precision extensions using double-precision assist instructions. The single-precision and fused multiply and add extensions are also enabled. ARC EM only.fpuda_allโ Double-precision extensions using double-precision assist instructions. All single-precision extensions are enabled too. ARC EM only.fpus_divโ Single-precision, square-root, and divide hardware extensions.fpud_divโ Double-precision, square-root, and divide hardware extensions. This one includesfpus_div. Not available for ARC EM.fpus_fmaโ Single-precision and fused multiply and add hardware extensions.fpud_fmaโ Double-precision and fused multiply and add hardware extensions. This one includesfpus_fma. Not available for ARC EM.fpus_allโ All single-precision floating-point hardware extensions.fpud_allโ All single- and double-precision floating-point hardware extensions. Not available for ARC EM.
-mirq-ctrl-saved=register-range, blink, lp_countโ ๐ก๏ธ Picks the general-purpose registers the processor saves and restores automatically on interrupt entry and exit. Theregister-rangeis written as two registers separated by a dash. The range always starts atr0, and the upper limit is thefpregister.blinkandlp_countare optional. This option is only valid for ARC EM and ARC HS cores.-mrgf-banked-regs=numberโ ๐ฆ Sets how many registers get replicated into the second register bank when a fast interrupt is entered. Fast interrupts are the ones with the highest priority level, P0. They only save the PC and STATUS32 registers so there are no memory transactions during entry and exit. Use this when you're working with fast interrupts on an ARC V2 family processor. The permitted values are4,8,16, and32.-mlpc-width=widthโ ๐ข Sets the width of thelp_countregister. Valid widths are8,16,20,24,28, and32bits. The default is fixed at 32 bits. If the width is less than 32, the compiler won't try to turn your loops into the zero-delay loop mechanism unless it's known thatlp_countcan hold the loop counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for various needs. This option defines the macro__ARC_LPC_WIDTH__with the value ofwidth.-mrf16โ ๐ฏ Tells the compiler to generate code for a 16-entry register file. It also defines the__ARC_RF16__preprocessor macro.-mbranch-indexโ ๐งญ Enables the use ofbiorbihinstructions to implement jump tables.
The following options are passed through to the assembler, and they also define preprocessor macro symbols ๐
-mdsp-packaโ ๐ฆ Passed down to the assembler to enable the DSP Pack A extensions. It also sets the preprocessor symbol__Xdsp_packa. This option is deprecated.-mdvbfโ ๐ฆ Passed down to the assembler to enable the dual Viterbi butterfly extension. It also sets the preprocessor symbol__Xdvbf. This option is deprecated.-mlockโ ๐ Passed down to the assembler to enable the locked load/store conditional extension. It also sets the preprocessor symbol__Xlock.-mmac-d16โ Passed down to the assembler. It also sets the preprocessor symbol__Xxmac_d16. This option is deprecated.-mmac-24โ Passed down to the assembler. It also sets the preprocessor symbol__Xxmac_24. This option is deprecated.-mrtscโ โฑ๏ธ Passed down to the assembler to enable the 64-bit time-stamp counter extension instruction. It also sets the preprocessor symbol__Xrtsc. This option is deprecated.-mswapeโ ๐ Passed down to the assembler to enable the swap byte ordering extension instruction. It also sets the preprocessor symbol__Xswape.-mtelephonyโ ๐ Passed down to the assembler to enable dual- and single-operand instructions for telephony. It also sets the preprocessor symbol__Xtelephony. This option is deprecated.-mxyโ ๐ง Passed down to the assembler to enable the XY memory extension. It also sets the preprocessor symbol__Xxy.
The following options control how the assembly code gets annotated ๐
-misizeโ ๐ Annotates assembler instructions with estimated addresses.-mannotate-alignโ ๐งฉ Explains which alignment considerations led to the decision to make an instruction short or long.
The following options are passed through to the linker ๐
-marclinuxโ ๐ง Passed through to the linker to specify use of thearclinuxemulation. This is enabled by default in toolchains built for thearc-linux-uclibcandarceb-linux-uclibctargets when profiling is not requested.-marclinux_profโ ๐ Passed through to the linker to specify use of thearclinux_profemulation. This is enabled by default in toolchains built for thearc-linux-uclibcandarceb-linux-uclibctargets when profiling is requested.
The following options control the semantics of the generated code ๐ง โจ
-mlong-callsโ ๐ Generates calls as register indirect calls, which gives you access to the full 32-bit address range.-mmedium-callsโ ๐ฏ Doesn't use less than a 25-bit addressing range for calls. That's the offset available for an unconditional branch-and-link instruction. Conditional execution of function calls is suppressed, so the 25-bit range gets used instead of the 21-bit range you'd get with conditional branch-and-link. This is the default for toolchains built for thearc-linux-uclibcandarceb-linux-uclibctargets ๐-G numโ okay so this one decides which externally-visible data gets tucked into a small data section ๐ง, but only if that data is no bigger thannumbytes. The default fornumis4for any ARC configuration, or8when we have double load/store operations. ๐-mno-sdataโ nosdatareferences for you, bestie ๐ โโ๏ธ. This is the default for tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets.-mvolatile-cacheโ volatile references use ordinarily cached memory accesses. This is the default, and honestly iconic ๐ .-mno-volatile-cacheโ flips the switch and enables cache bypass for volatile references ๐ฅ.
The following options fine tune code generation ๐:
-malign-callโ does alignment optimizations for call instructions โจ.-mauto-modify-regโ enables the use of pre/post modify with register displacement ๐ฆ.-mbbit-peepholeโ enables bbit peephole2 ๐.-mno-brccโ this one turns off a target-specific pass inarc_reorgthat would generate compare-and-branch (brcc) instructions. It has no effect on generation of these instructions driven by the combiner pass, so don't expect miracles there ๐.-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 compactcasesipattern. This is the default for-Os, and it's only available for ARCv1 cores. Also, this option is deprecated, so use it with a little side-eye ๐.-mno-cond-execโ disables the ARCompact-specific pass that generates conditional execution instructions.
Okay, so the reason this one exists is that the target-independent pass for conditional execution is often lacking, thanks to delay slot scheduling and interactions between operand numbers, literal sizes, instruction lengths, and the support for conditional execution. The ARC port keeps a special pass around that tries to find more conditional execution opportunities after register allocation, branch shortening, and delay slot scheduling have been done. It generally, but not always, improves performance and code size, at the cost of extra compilation time, which is why there is an option to switch it off ๐ญ. If you have a problem with call instructions exceeding their allowable offset range because they are conditionalized, you should consider using -mmedium-calls instead ๐ซถ.
-mearly-cbranchsiโ enables pre-reload use of thecbranchsipattern ๐ง.-mexpand-adddiโ expandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. This option is deprecated, so it's giving retired vibes ๐.-mindexed-loadsโ enables the use of indexed loads. Be careful here, because some optimizers then assume that indexed stores exist, which is not the case ๐. This can be problematic, so proceed with caution.-mlraโ enables Local Register Allocation. This is 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 often get shortened by calling a special function in libgcc. This is called a millicode call. These calls can pose performance issues and/or cause linking issues when linking in a nonstandard way, so this option lets you turn millicode call generation on or off ๐.-mcode-density-frameโ lets the compiler emitenterandleaveinstructions. These are only valid for CPUs with the code-density feature ๐งโโ๏ธ.-mmixed-codeโ tweaks register allocation to help with 16-bit instruction generation. This generally decreases the average instruction size while increasing the instruction count ๐ญ.-mq-classโ this one is deprecated, and it enables q instruction alternatives. It is the default for-Os๐ฅน.-mRcqโ enables Rcq constraint handling. Most short code generation depends on this. This is the default ๐.-mRcwโ enables Rcw constraint handling. Most ccfsm condexec depends on this. This is the default too ๐.-msize-level=levelโ fine-tunes size optimization with regards to instruction lengths and alignment. The recognized values forlevelare:0โ no size optimization. This level is deprecated and treated like1๐.1โ short instructions are used opportunistically โจ.2โ in addition, alignment of loops and of code after barriers is dropped ๐.3โ in addition, optional data alignment is dropped, and the optionOsis enabled ๐.
This defaults to 3 when -Os is in effect. Otherwise, the behavior when this is not set is equivalent to level 1 ๐
.
-mtune=cpuโ sets instruction scheduling parameters forcpu, overriding any 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โ sets the probability threshold for unaligning branches. When tuning for ARC700 and optimizing for speed, branches without a filled delay slot are preferably emitted unaligned and long, unless profiling indicates that the probability for the branch to be taken is belowprobability. The default is(REG_BR_PROB_BASE/2), i.e.5000๐ซง.
The following options are maintained for backward compatibility, but they are now deprecated and will be removed in a future release. Bestie, let's say goodbye to these ๐ญ๐ซก:
These options are deprecated and will be removed in a future release, so don't build new stuff around them ๐.
-margonautโ obsolete FPX ๐ชฆ.-mbig-endian,-EBโ compiles code for big-endian targets. Use of these options is now deprecated. Big-endian code is supported by configuring GCC to buildarceb-elf32andarceb-linux-uclibctargets, for which big endian is the default ๐.-mlittle-endian,-ELโ compiles code for little-endian targets. Use of these options is now deprecated. Little-endian code is supported by configuring GCC to buildarc-elf32andarc-linux-uclibctargets, 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 ๐ฆพ:
-mabi=nameโ generates code for the specified ABI. Permissible values are:apcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt๐งฉ.-mapcs-frameโ generates a stack frame that is compliant with the ARM Procedure Call Standard for all functions, even if this isn't strictly necessary for correct execution of the code. Specifying-fomit-frame-pointerwith this option causes the stack frames not to be generated for leaf functions. The default is-mno-apcs-frame. This option is deprecated ๐ฅ.-mapcsโ a synonym for-mapcs-frame, and it's deprecated too ๐ฅ.-mthumb-interworkโ generates code that supports calling between the ARM and Thumb instruction sets. Without this option, on pre-v5 architectures, the two instruction sets cannot 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 that 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 this information 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 causes GCC to generate output containing library calls for floating-point operations. softfp allows the generation of code 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. This is a big no-no if you mix them ๐ซ.
-mgeneral-regs-onlyโ generates code which uses only the general-purpose registers. This prevents the compiler from using floating-point and Advanced SIMD registers, but it doesn'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 is dependent on the selected target architecture. For ARMv6 and later architectures the default is BE8, and 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 ๐๏ธ.
Okay so, these are the permissible names you're allowed to use, bestie ๐: 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, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, armv8.1-m.main, iwmmxt and iwmmxt2 ๐
Then there's a little group of deprecated ones ๐ฅ that are still recognized but have no Thumb execution state support, so they're on thin ice: armv4. Use with caution, it's giving "please don't" ๐
Many of these architectures have extensions โจ You add one by tacking +extension onto the end of the architecture name. The extension options get processed in order, and the capabilities accumulate (they stack up, like a good outfit ๐). An extension will also turn on any base extensions it needs, so for example +crypto will always enable +simd ๐ซถ
The one exception to the stacking vibe is anything prefixed with +no.... Those disable the option they name, plus any other extensions that depend on it ๐ญ For example, -march=armv7-a+simd+nofp+vfpv4 is the same as writing -march=armv7-a+vfpv4, because the +nofp that comes after +simd wipes +simd out completely ๐
Most extension names are generic, but what they actually do depends on which architecture they're attached to ๐ฆ For example, +simd works on both armv7-a and armv8-a, but on armv7-a it turns on the original ARMv7-A Advanced SIMD (Neon) extensions, while on armv8-a it gives you the ARMv8-A version instead ๐
Here's the rundown of which extensions each architecture supports. Anything not mentioned below has no extensions at all, so don't go looking ๐
armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk
+fpโ The VFPv2 floating-point instructions. The extension+vfpv2can be used as an alias for this extension.+nofpโ Disable the floating-point instructions.
armv7
This one is the common subset of the ARMv7-A, ARMv7-R and ARMv7-M architectures, so it's the everyday basic ๐ธ
+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers. The extension+vfpv3-d16can be used as an alias for this extension. Note that floating-point is not supported by the base ARMv7-M architecture, but is compatible with both the ARMv7-A and ARMv7-R architectures โ ๏ธ+nofpโ Disable the floating-point instructions.
armv7-a
+mpโ The multiprocessing extension.+secโ The security extension.+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers. The extension+vfpv3-d16can be used as an alias for this extension.+simdโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions. The extensions+neonand+neon-vfpv3can be used as aliases for this extension.+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers.+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations.+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and the half-precision floating-point conversion operations.+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers.+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations.+neon-vfpv4โ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions.+nosimdโ Disable the Advanced SIMD instructions (does not disable floating point).+nofpโ Disable the floating-point and Advanced SIMD instructions.
armv7ve
This is the extended version of the ARMv7-A architecture, with support for virtualization ๐ฆ
+fpโ The VFPv4 floating-point instructions, with 16 double-precision registers. The extension+vfpv4-d16can be used as an alias for this extension.+simdโ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions. The extension+neon-vfpv4can be used as an alias for this extension.+vfpv3-d16โ The VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers.+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations.+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and the half-precision floating-point conversion operations.+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers.+neonโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions. The extension+neon-vfpv3can be used as an alias for this extension.+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations.+nosimdโ Disable the Advanced SIMD instructions (does not disable floating point).+nofpโ Disable the floating-point and Advanced SIMD instructions.
armv8-a
+crcโ The Cyclic Redundancy Check (CRC) instructions.+simdโ The ARMv8-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions.+nocryptoโ Disable the cryptographic instructions.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.
armv8.1-a
+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions.+nocryptoโ Disable the cryptographic instructions.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.
armv8.2-a, armv8.3-a
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions.+fp16fmlโ The half-precision floating-point fmla extension. This also enables the half-precision floating-point extension and 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โ Enable the Dot Product extension. This also enables Advanced SIMD instructions.+nocryptoโ Disable the cryptographic extension.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.+i8mmโ 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions.+bf16โ Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions.
armv8.4-a
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension and the half-precision floating-point fmla extension.+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions as well as the Dot Product extension.+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension.+nocryptoโ Disable the cryptographic extension.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.+i8mmโ 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions.+bf16โ Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions.
armv8.5-a
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension and the half-precision floating-point fmla extension.+simdโ okay bestie, this one turns on the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension โจ
๐ฆ armv8.6-a
+fp16โ the half-precision floating-point data processing instructions ๐. This also enables the Advanced SIMD and floating-point instructions, the Dot Product extension, and the half-precision floating-pointfmlaextension ๐ซถ+simdโ the same ARMv8.3-A Advanced SIMD and floating-point instructions as before, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension โจ+nocryptoโ disable the cryptographic extension ๐ โโ๏ธ+nofpโ disable the floating-point, Advanced SIMD and cryptographic instructions ๐+i8mmโ 8-bit Integer Matrix Multiply instructions ๐ง. This also enables Advanced SIMD and floating-point instructions+bf16โ Brain half-precision floating-point instructions ๐. This also enables Advanced SIMD and floating-point instructions
๐ armv7-r
+fp.spโ the single-precision VFPv3 floating-point instructions ๐ธ.+vfpv3xdcan be used as an alias for this extension+fpโ the VFPv3 floating-point instructions with 16 double-precision registers ๐.+vfpv3-d16can be used as an alias for this extension+vfpv3xd-d16-fp16โ the single-precision VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐ง+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐ง+nofpโ disable the floating-point extension ๐+idivโ the ARM-state integer division instructions โ+noidivโ disable the ARM-state integer division extension ๐ซ
๐
armv7e-m
+fpโ the single-precision VFPv4 floating-point instructions โญ+fpv5โ the single-precision FPv5 floating-point instructions ๐ฅ+fp.dpโ the single- and double-precision FPv5 floating-point instructions ๐+nofpโ disable the floating-point extensions ๐
๐ง armv8.1-m.main
+dspโ the DSP instructions ๐ถ+mveโ the M-Profile Vector Extension (MVE) integer instructions ๐+mve.fpโ the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions ๐+fpโ the single-precision floating-point instructions โจ+fp.dpโ the single- and double-precision floating-point instructions ๐+nofpโ disable the floating-point extension ๐+cdecp0, +cdecp1, ... , +cdecp7โ enable the Custom Datapath Extension (CDE) on selected coprocessors, according to the numbers given in the options in the range 0 to 7 ๐ฆ
๐ armv8-m.main
+dspโ the DSP instructions ๐ถ+nodspโ disable the DSP extension ๐ โโ๏ธ+fpโ the single-precision floating-point instructions โจ+fp.dpโ the single- and double-precision floating-point instructions ๐+nofpโ disable the floating-point extension ๐+cdecp0, +cdecp1, ... , +cdecp7โ enable the Custom Datapath Extension (CDE) on selected coprocessors, according to the numbers given in the options in the range 0 to 7 ๐ฆ
๐ซง armv8-r
+crcโ the Cyclic Redundancy Check (CRC) instructions ๐+fp.spโ the single-precision FPv5 floating-point instructions ๐ธ+simdโ the ARMv8-A Advanced SIMD and floating-point instructions ๐+cryptoโ the cryptographic instructions ๐+nocryptoโ disable the cryptographic instructions ๐ โโ๏ธ+nofpโ disable the floating-point, Advanced SIMD and cryptographic instructions ๐
-march=native is giving auto-detect vibes ๐. It makes the compiler sniff out the architecture of the build computer. Right now this only works on GNU/Linux, and not every architecture gets recognized ๐ฅบ. If the auto-detect doesn't work out, the option just has no effect, so no drama ๐ซถ
๐ -mtune=name
This option tells GCC which target ARM processor it should tune the performance of the code for ๐
. Some ARM implementations can get a glow-up in performance when you use this option โจ. The permissible names are: arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, 0strongarm1110, 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, ares, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, 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 ๐ง ๐. The permissible names are: cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a72.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55.
-mtune=generic-arch tells GCC to tune the performance for a blend of processors within architecture arch ๐. The goal is code that runs well on the most popular processors right now, balancing optimizations that help some CPUs in the range while avoiding performance pitfalls on the others ๐ซถ. 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 ๐. Again, this only works on GNU/Linux right now, and not every architecture is recognized. If the auto-detect is unsuccessful, the option has no effect ๐ฅ.
๐ -mcpu=name[+extension...]
This specifies the name of the target ARM processor ๐. GCC uses this name to figure out the target ARM architecture (as if you had said -march), and the ARM processor type to tune for performance (as if you had said -mtune) ๐ง . If you use this option together with -march or -mtune, those options take precedence over the matching part of this option ๐
.
Lots of the supported CPUs have optional architectural extensions ๐งฉ. When they do, those extensions are usually enabled by default โจ. If implementations that lack the extension exist, you can use the extension syntax to disable the ones that were left out ๐
โโ๏ธ. For floating-point and Advanced SIMD (Neon) instructions, you also need to think about the settings of -mfloat-abi and -mfpu ๐: floating-point and Advanced SIMD instructions will only be used if -mfloat-abi is not set to soft, and any setting of -mfpu other than auto will override the available floating-point and SIMD extension instructions ๐ฅ.
For example, cortex-a9 comes in three major configurations: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD ๐ธ. The default is to enable all the instructions, but you can use the extensions +nosimd and +nofp to disable just the SIMD instructions, or both the SIMD and floating-point instructions, respectively ๐ซง.
The permissible names for this option are the same as the ones for -mtune ๐.
The following extension options are common to the listed CPUs ๐:
+nodspโ disable the DSP instructions on cortex-m33, cortex-m35p ๐+nofpโ disables the floating-point instructions on arm9e, arm946e-s, arm966e-s, arm968e-s, arm10e, arm1020e, arm1022e, arm926ej-s, arm1026ej-s, cortex-r5, cortex-r7, cortex-r8, cortex-m4, cortex-m7, cortex-m33 and cortex-m35p. It also disables the floating-point and SIMD instructions on generic-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-a53 and cortex-a55 ๐+nofp.dpโ disables the double-precision component of the floating-point instructions on cortex-r5, cortex-r7, cortex-r8, cortex-r52 and cortex-m7 ๐ฅ+nosimdโ disables the SIMD (but not floating-point) instructions on generic-armv7-a, cortex-a5, cortex-a7 and cortex-a9 ๐
okay so +crypto is the one that switches on the cryptographic instructions ๐โจ it works on cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, exynos-m1, xgene1, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53 and cortex-a75.cortex-a55 ๐
the generic-armv7-a pseudo target is giving its own thing ๐ฆ by default it comes with VFPv3 and 16 double-precision registers. it takes these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16 and neon-vfpv4. they mean the same thing as the extensions for -march=armv7-a, so no new vocab to learn ๐ธ
-mcpu=generic-arch is also allowed, and it's the same as -march=arch -mtune=generic-arch. check out -mtune for more tea โ
-mcpu=nativeโ the compiler tries to auto-detect the CPU of the computer doing the build ๐ง right now this only works on GNU/Linux, and not every architecture gets recognised. if the auto-detect doesn't work out, the option just does nothing ๐-mfpu=nameโ this tells the compiler what floating-point hardware (or hardware emulation) the target has ๐ the valid names areauto,vfpv2,vfpv3,vfpv3-fp16,vfpv3-d16,vfpv3-d16-fp16,vfpv3xd,vfpv3xd-fp16,neon-vfpv3,neon-fp16,vfpv4,vfpv4-d16,fpv4-sp-d16,neon-vfpv4,fpv5-d16,fpv5-sp-d16,fp-armv8,neon-fp-armv8andcrypto-neon-fp-armv8.neonis just an alias forneon-vfpv3, andvfpis an alias forvfpv2๐
auto is the default and it's a bit of a diva ๐ it picks the floating-point and Advanced SIMD instructions based on whatever -mcpu and -march are set to.
โ ๏ธ bestie, listen up. if your floating-point hardware has NEON (like-mfpu=neon), GCC's auto-vectorization pass won't generate floating-point operations unless you also add-funsafe-math-optimizations. the reason is that NEON doesn't fully follow the IEEE 754 standard (denormal values get treated as zero), so using NEON instructions can lose precision ๐ญ
you can also set the fpu name per function with the target("fpu=") function attributes or pragmas ๐ฆ
-mfp16-format=nameโ this sets the format of the"__fp16"half-precision floating-point type โจ the valid names arenone,ieeeandalternative. the default isnone, and in that case the"__fp16"type isn't defined at all ๐ฅ-mstructure-size-boundary=nโ every structure and union gets rounded up to a multiple ofnbits ๐ the valid values are8,32and64. the default depends on the toolchain, and for the COFF toolchain it's8.64only works if the underlying ABI supports it ๐
a bigger number can make code faster and more efficient, but it can also make the program bigger. different values can be incompatible, too. code built with one value might not play nice with code or libraries built with another value if they pass structs or unions back and forth ๐
๐ this option is deprecated, so please don't start new projects with it.
-mabort-on-noreturnโ this makes the compiler callabortat the end of anynoreturnfunction. it only runs if that function somehow tries to return ๐จ-mlong-calls,-mno-long-callsโ these tell the compiler to make 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 switched on, not every call becomes a long call. the vibe check goes like this: static functions, functions with the "short_call" attribute, functions inside a #pragma no_long_calls scope, and functions whose definitions were already compiled in the current compilation unit all stay short ๐ซถ the exceptions are weak function definitions, functions with the "long_call" attribute or the "section" attribute, and functions inside a #pragma long_calls scope. those are always long, no debate ๐
this feature is not on by default. -mno-long-calls puts back the default behaviour, and so does wrapping the calls in a #pragma long_calls_off directive. also note that these switches do nothing for calls made through function pointers โจ
-msingle-pic-baseโ the register used for PIC addressing gets treated as read-only, instead of being loaded in the prologue of every function ๐ the runtime system has to set this register to a proper value before execution starts.-mpic-register=regโ this picks the register used for PIC addressing ๐ฏ for the standard PIC base, the default is any suitable register the compiler decides on. for the single PIC base, the default isR9if the target is EABI based or stack-checking is enabled. otherwise it'sR10.-mpic-data-is-text-relativeโ this assumes the gap between the text and data segments is fixed at static link time ๐ง that means PC-relative addressing can be used to reach data we know is in the data segment. on non-VxWorks RTP targets it's enabled by default. if you turn it off on those targets,-msingle-pic-basegets enabled by default instead ๐ฆ-mpoke-function-nameโ this writes the name of each function into the text section, right before the function prologue โ๏ธ the generated code looks something like this:
t0
.ascii "arm_poke_function_name", 0
.align
t1
.word 0xff000000 + (t1 - t0)
arm_poke_function_name
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
when you're doing a stack backtrace, code can look at the pc value stored at fp + 0 ๐ if the trace function checks the location pc - 12 and the top 8 bits are set, then we know there's a function name embedded right before that location. its length is ((pc[-3]) & 0xff000000). the way that's giving detective energy ๐ต๏ธโโ๏ธ
-mthumb,-marmโ pick whether the code 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 or Thumb mode for each function with the target("thumb") and target("arm") function attributes or pragmas ๐
-mflip-thumbโ this switches between ARM and Thumb modes on alternating functions ๐ it's only there for regression testing of mixed Thumb/ARM code generation, so please don't use it for ordinary 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โ same idea, but this one makes stack frames compliant with 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 ๐ช that header switches to Thumb mode before the rest of the function runs. this lets those functions get called from non-interworking code. it's not valid in AAPCS configurations, because interworking is already enabled by default there ๐-mcaller-super-interworkingโ lets calls through function pointers (including virtual functions) run correctly, whether or not the target code was compiled for interworking ๐ธ there's a small overhead when running a function pointer if you turn this on. it's also not valid in AAPCS configurations, since interworking is already on by default there.-mtp=nameโ picks the access model for the thread local storage pointer ๐งต the valid models aresoft, which generates calls to"__aeabi_read_tp";cp15, which fetches the thread pointer fromcp15directly (supported in the arm6k architecture); andauto, which uses the best available method for the processor you picked. the default isautoโญ-mtls-dialect=dialectโ picks the dialect used to access thread local storage ๐ there are two:gnuandgnu2. thegnudialect selects the original GNU scheme for supporting local and global dynamic TLS models. thegnu2dialect selects the GNU descriptor scheme, which performs better for shared libraries ๐ the descriptor scheme is compatible with the original, but it needs new assembler, linker and library support. the initial and local exec TLS models aren't affected by this option and always use the original scheme.-mword-relocationsโ only generates absolute relocations on word-sized values (i.e.R_ARM_ABS32) ๐งฑ this is on by default on targets (uClinux, SymbianOS) where the runtime loader enforces that restriction, and whenever-fpicor-fPICis specified. this option conflicts with-mslow-flash-data.-mfix-cortex-m3-ldrdโ some Cortex-M3 cores can corrupt data whenldrdinstructions use overlapping destination and base registers ๐ฑ this option avoids generating those instructions. it's enabled by default when-mcpu=cortex-m3is specified ๐ก๏ธ-munaligned-access,-mno-unaligned-accessโ enables (or disables) reading and writing 16- and 32-bit values from addresses that aren't 16- or 32-bit aligned ๐งฉ by default, unaligned access is disabled for all pre-ARMv6, all ARMv6-M and ARMv8-M Baseline architectures, and enabled for all other architectures. if unaligned access isn't enabled, words in packed data structures get accessed one byte at a time ๐ข
The Tag_CPU_unaligned_access attribute in the generated object file gets set to true or false depending on this option ๐ฆ. If unaligned access is turned on, the __ARM_FEATURE_UNALIGNED preprocessor symbol gets defined too โจ.
-mneon-for-64bitsโ ๐ This one is deprecated and does absolutely nothing, so bestie, don't bother with it.-mslow-flash-dataโ Okay so this assumes loading data from flash is slower than fetching instructions, which means literal loads get minimized for better performance โก. It's only supported when compiling for ARMv7 M-profile, it's off by default, and it conflicts with-mword-relocations๐ โโ๏ธ.-masm-syntax-unifiedโ Assumes the inline assembler is using unified asm syntax. The default is currently off, which means divided syntax. It has no impact on Thumb2, but ngl this might change in future GCC releases ๐.
Divided syntax should be considered deprecated. It's giving outdated, so plan accordingly ๐.
-mrestrict-itโ Restricts IT block generation so it follows the ARMv8-A rules ๐. IT blocks can only contain a single 16-bit instruction from a select set of instructions. This is on by default for ARMv8-A Thumb mode ๐ธ.-mprint-tune-infoโ Prints CPU tuning info as a comment in the assembler file ๐ง. This is only for regression testing of the compiler and is not meant for ordinary code compiling, so it's disabled by default ๐.
This one is strictly for compiler testing, not everyday use. Keep it away from your normal builds!
-mverbose-cost-dumpโ Enables verbose cost model dumping in the debug dump files ๐. It's here for debugging the compiler, so it's a main-character tool for compiler nerds ๐ค.-mpure-codeโ Do not allow constant data to be placed in code sections ๐ซ. On top of that, when compiling for ELF object format, all text sections get the ELF processor-specific section attributeSHF_ARM_PURECODEโจ. This is only available when generating non-pic code for M-profile targets ๐.-mcmseโ Generates secure code as per the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification" ๐. You can find that spec athttps://developer.arm.com/documentation/ecm0359818/latest/๐.-mfix-cmse-cve-2021-35465โ This mitigates a potential security issue with the "VLLDM" instruction in some M-profile devices when using CMSE (CVE-2021-365465) ๐ก๏ธ. It's enabled by default when-mcpu=is used with "cortex-m33", "cortex-m35p" or "cortex-m55" ๐ . If you want to turn the mitigation off, use-mno-fix-cmse-cve-2021-35465๐ โโ๏ธ.-mfdpic,-mno-fdpicโ Selects the FDPIC ABI, which uses 64-bit function descriptors to represent pointers to functions ๐. When the compiler is configured for "arm-*-uclinuxfdpiceabi" targets, this is on by default and implies-fPIEif none of the PIC/PIE-related options is provided ๐. On other targets, it only enables the FDPIC-specific code generation features, so you'll need to explicitly provide the PIC/PIE-related options as needed ๐ซถ.
Static linking is not supported here, because it would still involve the dynamic linker when the program self-relocates ๐ญ. If that behaviour is fine with you, use -static and -Wl,-dynamic-linker options ๐ฅ.
The opposite -mno-fdpic option is useful (and required!) for building the Linux kernel with the same ("arm-*-uclinuxfdpiceabi") toolchain you use for your userland programs ๐ง.
โจ AVR Options โจ
These options are defined for AVR implementations ๐ฆ:
-mmcu=mcuโ Specifies the Atmel AVR instruction set architecture (ISA) or MCU type ๐.
The default for this option is avr2 ๐ธ.
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.avr25โ "Classic" devices with up to 8 KiB of program memory and with the "MOVW" instruction. mcu =attiny13,attiny13a,attiny24,attiny24a,attiny25,attiny261,attiny261a,attiny2313,attiny2313a,attiny43u,attiny44,attiny44a,attiny45,attiny48,attiny441,attiny461,attiny461a,attiny4313,attiny84,attiny84a,attiny85,attiny87,attiny88,attiny828,attiny841,attiny861,attiny861a,ata5272,ata6616c,at86rf401.avr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory. mcu =at76c711,at43usb355.avr31โ "Classic" devices with 128 KiB of program memory. mcu =atmega103,at43usb320.avr35โ "Classic" devices with 16 KiB up to 64 KiB of program memory and with the "MOVW" instruction. mcu =attiny167,attiny1634,atmega8u2,atmega16u2,atmega32u2,ata5505,ata6617c,ata664251,at90usb82,at90usb162.avr4โ "Enhanced" devices with up to 8 KiB of program memory. mcu =atmega48,atmega48a,atmega48p,atmega48pa,atmega48pb,atmega8,atmega8a,atmega8hva,atmega88,atmega88a,atmega88p,atmega88pa,atmega88pb,atmega8515,atmega8535,ata6285,ata6286,ata6289,ata6612c,at90pwm1,at90pwm2,at90pwm2b,at90pwm3,at90pwm3b,at90pwm81.avr5โ "Enhanced" devices with 16 KiB up to 64 KiB of program memory. mcu =atmega16,atmega16a,atmega16hva,atmega16hva2,atmega16hvb,atmega16hvbrevb,atmega16m1,atmega16u4,atmega161,atmega162,atmega163,atmega164a,atmega164p,atmega164pa,atmega165,atmega165a,atmega165p,atmega165pa,atmega168,atmega168a,atmega168p,atmega168pa,atmega168pb,atmega169,atmega169a,atmega169p,atmega169pa,atmega32,atmega32a,atmega32c1,atmega32hvb,atmega32hvbrevb,atmega32m1,atmega32u4,atmega32u6,atmega323,atmega324a,atmega324p,atmega324pa,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.avr51โ "Enhanced" devices with 128 KiB of program memory. mcu =atmega128,atmega128a,atmega128rfa1,atmega128rfr2,atmega1280,atmega1281,atmega1284,atmega1284p,atmega1284rfr2,at90can128,at90usb1286,at90usb1287.avr6โ "Enhanced" devices with 3-byte PC, i.e. with more than 128 KiB of program memory. mcu =atmega256rfr2,atmega2560,atmega2561,atmega2564rfr2.avrxmega2โ "XMEGA" devices with more than 8 KiB and up to 64 KiB of program memory. mcu =atxmega8e5,atxmega16a4,atxmega16a4u,atxmega16c4,atxmega16d4,atxmega16e5,atxmega32a4,atxmega32a4u,atxmega32c3,atxmega32c4,atxmega32d3,atxmega32d4,atxmega32e5.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.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.avrxmega5โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory and more than 64 KiB of RAM. mcu =atxmega64a1,atxmega64a1u.avrxmega6โ "XMEGA" devices with more than 128 KiB of program memory. mcu =atxmega128a3,atxmega128a3u,atxmega128b1,atxmega128b3,atxmega128c3,atxmega128d3,atxmega128d4,atxmega192a3,atxmega192a3u,atxmega192c3,atxmega192d3,atxmega256a3,atxmega256a3b,atxmega256a3bu,atxmega256a3u,atxmega256c3,atxmega256d3,atxmega384c3,atxmega384d3.avrxmega7โ "XMEGA" devices with more than 128 KiB of program memory and more than 64 KiB of RAM. mcu =atxmega128a1,atxmega128a1u,atxmega128a4u.avrtinyโ "TINY" Tiny core devices with 512 B up to 4 KiB of program memory. mcu =attiny4,attiny5,attiny9,attiny10,attiny20,attiny40.avr1โ This ISA is implemented by the minimal AVR core and is supported for assembler only โ ๏ธ. mcu =attiny11,attiny12,attiny15,attiny28,at90s1200.
-mabsdataโ Assumes all data in static storage can be accessed byLDS/STSinstructions ๐ฏ. This 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 and releases the needed stack space for them just once, in the function prologue/epilogue ๐. Without this option, outgoing arguments are pushed before calling a function and popped afterwards ๐ฅก.
Okay so the stack trick is lowkey genius ๐งโจ Popping arguments after a call can be expensive on AVR ๐ธ, so letting them pile up on the stack can actually lead to smaller executables ๐, since nothing has to be yanked off the stack after each call. ๐
This option can really shrink code for functions that make a bunch of calls to functions that take their arguments on the stack, like printf-like functions ๐จ๏ธ๐ธ
-mbranch-cost=costโ Sets the branch costs for conditional branch instructions tocost๐ฆ Reasonable values are small, non-negative integers, and the default branch cost is0.-mcall-prologuesโ Function prologues and epilogues get expanded as calls to the right subroutines ๐ซถ The bonus here is that the code size comes out smaller ๐-mdouble=bits,-mlong-double=bitsโ Sets the size (in bits) of the"double"or"long double"type, respectively ๐ The possible values forbitsare32and64. Whether a specific value is allowed depends on the--with-double=and--with-long-double=configure options (https://gcc.gnu.org/install/configure.html#avr), and the same goes for the default values of these options ๐ง-mgas-isr-prologuesโ Interrupt service routines (ISRs) can use the"__gcc_isr"pseudo instruction that GNU Binutils supports ๐ฅ If this option is on, you can still turn the feature off for individual ISRs with the AVR Function Attributes,,"no_gccisr"function attribute ๐ This feature is turned on by default if optimization is on (but not with-Og,@pxref{Optimize Options}), and if GNU Binutils supports PR21683 (https://sourceware.org/PR21683) โจ-mint8โ Assumesintis an 8-bit integer ๐ This changes the size of every type: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes.
Heads up bestie: this option does not conform to the C standards ๐ญ It does give you smaller code size though, so it's a trade-off.
-mmain-is-OS_taskโ Stops registers from being saved inmain๐ It's the same as attaching the AVR Function Attributes,,"OS_task"attribute tomain. It's activated by default if optimization is on ๐ฅ-mn-flash=numโ Assumes the flash memory isnumtimes 64 KiB big ๐-mno-interruptsโ The generated code is not compatible with hardware interrupts ๐ The upside is that code size comes out smaller ๐-mrelaxโ Tries to swap aCALLresp.JMPinstruction for the shorterRCALLresp.RJMPinstruction 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 gets located ๐ง So the assembler code the compiler generates stays the same, but the instructions in the executable may differ from what's in the assembler code ๐ซ
Relaxing must be turned on if linker stubs are needed, so check out the section on "EIND" and linker stubs below ๐
-mrmwโ Assumes the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT๐-mshort-callsโ AssumesRJMPandRCALLcan 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โ Treats the stack pointer register as an 8-bit register, aka it assumes the high byte of the stack pointer is zero ๐ง In general, 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 avr2 and avr25 architectures ๐ 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 thus no SPH register) or not ๐ง
-mstrict-Xโ Uses the address registerXthe way the hardware intends ๐ That meansXonly gets 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 by extra instructions ๐ค For example, loading a value with X+const addressing (with a small non-negative const < 64) into a register Rn gets done like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-mtiny-stackโ Only changes the lower 8 bits of the stack pointer ๐ฆ-mfract-convert-truncateโ Lets you use truncation instead of rounding towards zero for fractional fixed-point types ๐-nodevicelibโ Don't link against AVR-LibC's device specific librarylib<mcu>.a๐ โโ๏ธ-nodevicespecsโ Don't add-specs=device-specs/specs-mcuto the compiler driver's command line ๐ You're taking full responsibility for feeding the subprocesses (compiler proper, assembler and linker) the right command line options. That means you have to supply your own private device specs file with-specs=path-to-specs-file. There's no more need for-mmcu=mcueither โจ
This option can also replace the older way of doing custom device-specs files. That one needed -B some-path to point to 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โ Warns about conversions between address spaces when the resulting address space isn't contained in the incoming address space โ ๏ธ-Wmisspelled-isrโ Warns if the ISR is misspelled, i.e. missing the__vectorprefix ๐ 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 stored as a word address, so indirect jumps and calls can target any code address in the range of 64 Ki words ๐
To make indirect jumps work on devices with more than 128 Ki bytes of program memory space, 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 by means of aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved/restored in function or interrupt service routine prologue/epilogue ๐ฌ - For indirect calls to functions and computed goto, the linker generates stubs. Stubs are jump pads (sometimes also called trampolines), so the indirect call/jump lands on such a stub ๐ 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 segmentEINDpoints to ๐บ๏ธ - The startup code from libgcc never sets
EIND. Notice that startup code is a blend of code from libgcc and AVR-LibC. For the impact of AVR-LibC onEIND, see the AVR-LibC user manual (http://nongnu.org/avr-libc/user-manual/) ๐ - It's totally legit for user-specific startup code to set up
EINDearly, for example with initialization code located in section.init3๐ง That code runs before the general startup code that initializes RAM and calls constructors, but after the bit of AVR-LibC startup code that setsEINDto the segment where the vector table 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 so is not supported ๐ซ
int main (void)
{
/* Call function at word address 0x2 */
return ((int(*)(void)) 0x2)();
}
Instead, a stub has to be set up, i.e. the function has to be called through a symbol (func_4 in the example) ๐ฆ
int main (void)
{
extern int func_4 (void);
/* Call function at byte address 0x4 */
return func_4();
}
Then the application needs 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 โจ
So, the RAMP thing is kinda wild, bestie ๐พโจ Some AVR devices have more memory than the 64 KiB you can reach with 16-bit pointers. To get past that, the contents of a RAMP register act as the high part of the address. The X, Y, Z address register gets glued onto RAMPX, RAMPY, RAMPZ respectively to make one wide address ๐ฆ. RAMPD does the same job for direct addressing.
- Startup vibes โ The startup code sets the
RAMPspecial function registers to zero ๐ฑ. - Named address spaces โ If a named address space from AVR Named Address Spaces is used (anything other than generic or
__flash),RAMPZgets set as needed before the operation ๐ . - Reset after the drama โ If the device supports RAM larger than 64 KiB and the compiler has to change
RAMPZto pull off an operation,RAMPZgets reset to zero afterwards ๐งน. - ISR glow-up โ If the device comes with a specific
RAMPregister, the ISR prologue/epilogue saves and restores that SFR, and sets it to zero in case the ISR code might (implicitly) use it ๐ก๏ธ. - The big no โ RAM larger than 64 KiB is not supported by GCC for AVR targets ๐ โโ๏ธ
Warning, bestie: if you use inline assembler to read from locations outside the 16-bit address range and change one of the RAMP registers, you must reset it to zero after the access. No skipping this step ๐
๐ AVR Built-in Macros ๐
Okay so GCC defines a bunch of built-in macros so your code can check whether a feature is there or not ๐. Almost every one of the following built-in macros is deduced from device capabilities, which means 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__โ A built-in macro that resolves to a decimal number identifying the architecture. It depends on the-mmcu=mcuoption. Possible values are:
2, 25, 3, 31, 35, 4, 5, 51, 6
for mcu="avr2", "avr25", "avr3", "avr31", "avr35", "avr4", "avr5",
"avr51", "avr6",
respectively and
100, 102, 103, 104, 105, 106, 107
for mcu="avrtiny", "avrxmega2", "avrxmega3", "avrxmega4",
"avrxmega5", "avrxmega6", "avrxmega7", respectively.
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=devicedefines this built-in macro, which reflects the device's name ๐ธ. For example,-mmcu=atmega8defines the built-in macro__AVR_ATmega8__, and-mmcu=attiny261adefines__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=devicedefines this built-in macro to the device's name. For example, with-mmcu=atmega8the 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 theELPMinstruction.__AVR_HAVE_ELPMX__โ The device has theELPM Rn,ZandELPM Rn,Z+instructions.__AVR_HAVE_MOVW__โ The device has theMOVWinstruction to perform 16-bit register-register moves.__AVR_HAVE_LPMX__โ The device has theLPM Rn,ZandLPM Rn,Z+instructions.__AVR_HAVE_MUL__โ The device has a hardware multiplier ๐ฅ.__AVR_HAVE_JMP_CALL__โ The device has theJMPandCALLinstructions. This is the case for devices with more than 8 KiB of program memory.__AVR_HAVE_EIJMP_EICALL__/__AVR_3_BYTE_PC__โ The device has theEIJMPandEICALLinstructions. This is the case for devices with more than 128 KiB of program memory. This 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__/__AVR_HAVE_16BIT_SP__โ The stack pointer (SP) register is treated by the compiler as an 8-bit or 16-bit register, respectively. The definition of these macros is affected by-mtiny-stack๐ฅ.__AVR_HAVE_SPH__/__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=avr2and-mmcu=avr25, also by-msp8๐ .__AVR_HAVE_RAMPD__/__AVR_HAVE_RAMPX__/__AVR_HAVE_RAMPY__/__AVR_HAVE_RAMPZ__โ The device has theRAMPD,RAMPX,RAMPY,RAMPZspecial function register, respectively.__NO_INTERRUPTS__โ This macro reflects the-mno-interruptscommand-line option ๐.__AVR_ERRATA_SKIP__/__AVR_ERRATA_SKIP_JMP_CALL__โ Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum ๐ญ. The skip instructions areSBRS,SBRC,SBIS,SBICandCPSE. 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,LASandLAT) โก.__AVR_SFR_OFFSET__=offsetโ Instructions that can address I/O special function registers directly, likeIN,OUT,SBI, etc., may use a different address than an instruction accessing RAM, likeLDorSTS. This offset depends on the device architecture and has to be subtracted from the RAM address to get the respective I/O address ๐งฎ.__AVR_SHORT_CALLS__โ The-mshort-callscommand-line option is set ๐.__AVR_PM_BASE_ADDRESS__=addrโ Some devices support reading from flash memory withLD*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's no need to put.rodatainto RAM. This is handled by the default linker description file, and is currently available foravrtinyandavrxmega3. Even more convenient, there's no need to use address spaces like__flashor features like attributeprogmemandpgm_read_*๐ซถ.__WITH_AVRLIBC__โ The compiler is configured to be used together with AVR-Libc. See the--with-avrlibcconfigure option ๐.__HAVE_DOUBLE_MULTILIB__โ Defined if-mdouble=acts as a multilib option.__HAVE_DOUBLE32__/__HAVE_DOUBLE64__โ Defined if the compiler supports 32-bit double or 64-bit double, respectively. The actual layout is specified by option-mdouble=.__DEFAULT_DOUBLE__โ The size in bits ofdoubleif-mdouble=is not set. To test the layout ofdoublein a program, use the built-in macro__SIZEOF_DOUBLE__๐.__HAVE_LONG_DOUBLE32__/__HAVE_LONG_DOUBLE64__/__HAVE_LONG_DOUBLE_MULTILIB__/__DEFAULT_LONG_DOUBLE__โ Same as above, but forlong doubleinstead ofdouble๐.__WITH_DOUBLE_COMPARISON__โ Reflects the--with-double-comparison={tristate|bool|libf7}configure option (https://gcc.gnu.org/install/configure.html#avr) and is defined to 2 or 3 ๐.__WITH_LIBF7_LIBGCC__/__WITH_LIBF7_MATH__/__WITH_LIBF7_MATH_SYMBOLS__โ Reflects the--with-libf7={libgcc|math|math-symbols}configure option (https://gcc.gnu.org/install/configure.html#avr) ๐.
๐ฆ Blackfin Options ๐ฆ
-mcpu=cpu[-sirevision]โ Specifies the name of the target Blackfin processor. Currently, cpu can be one ofbf512,bf514,bf516,bf518,bf522,bf523,bf524,bf525,bf526,bf527,bf531,bf532,bf533,bf534,bf536,bf537,bf538,bf539,bf542,bf544,bf547,bf548,bf549,bf542m,bf544m,bf547m,bf548m,bf549m,bf561,bf592๐.
The optional sirevision specifies the silicon revision of the target Blackfin processor. Any workarounds available for that revision are enabled. If sirevision is none, no workarounds are enabled. If sirevision is any, all workarounds for the targeted processor are enabled. The __SILICON_REVISION__ macro is defined to two hexadecimal digits representing the major and minor numbers in the silicon revision. If sirevision is none, __SILICON_REVISION__ is not defined. If sirevision is any, __SILICON_REVISION__ is defined to be 0xffff. If this optional sirevision 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 has effect only for thebfin-elftoolchain. Certain other options, such as-mid-shared-libraryand-mfdpic, imply-msim๐ฎ.-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions. This avoids the instructions to save, set up and restore frame pointers, and makes an extra register available in leaf functions ๐ฟ.-mspecld-anomalyโ When enabled, the compiler ensures that 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 occurring.-mcsync-anomalyโ When enabled, the compiler ensures that 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 occurring 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.
Wait, I need to pause. Looking at what I've been asked to do: this part is the continuation of a rewrite, and I'm supposed to carry on from part 79 without a greeting. Let me produce the rewritten content for this section.
Okay bestie, let's get into the Blackfin and C6X stuff ๐
Actually, I need to be honest with you about what's happening here. I don't have the earlier parts of this rewrite in front of me, so I can't tell which heading level or section this part picks up in. The text you pasted starts mid-way through the OPTIONS section, and it begins with -mno-low64k, which is a Blackfin option. Because I can't confirm the surrounding context, I'll keep the rewrite to exactly what's in this excerpt and carry on from there without re-adding headings that may already exist.
Here is the rewrite of this part:
-mno-low64kโ okay so this one's the default vibe ๐ธ It assumes your program is arbitrarily large, which is just how it already works, no cap โจ-mstack-check-l1โ bestie, this one does stack checking using the info the uClinux kernel drops into L1 scratchpad memory ๐ฆ-mid-shared-libraryโ generates code that supports shared libraries through the library ID method ๐ This lets you do execute in place and shared libraries even without virtual memory management ๐ It implies-fPIC, and with abfin-elftarget it also implies-msim๐ฅ-mno-id-shared-libraryโ code that doesn't assume ID-based shared libraries are in use ๐ This is the default, periodt ๐-mleaf-id-shared-libraryโ still uses the library ID method, but assumes this library or executable won't link against any other ID shared libraries ๐ง That lets the compiler use faster code for jumps and calls โญ-mno-leaf-id-shared-libraryโ don't assume the code won't link against any ID shared libraries ๐ You get slower code for jump and call instructions ๐ญ-mshared-library-id=nโ sets the identification number of the ID-based shared library being compiled ๐ A value of0gives you more compact code ๐ซถ Other values force that number onto the current library, but it's no more space- or time-efficient than leaving this option out ๐-msep-dataโ lets the data segment live in a different area of memory from the text segment ๐ This enables execute in place without virtual memory management, because it gets rid of relocations against the text section โจ-mno-sep-dataโ assumes the data segment follows the text segment ๐ฉท This is the default โญ-mlong-calls/-mno-long-callsโ makes function calls by loading the function's address into a register first, then calling through that register ๐ You need this if the target function is outside the 24-bit addressing range of the offset-based subroutine call instruction ๐ฆ It's not on by default, and-mno-long-callsputs you back to the default ๐ These switches don't change how function calls through function pointers are generated ๐-mfast-fpโ links with the fast floating-point library ๐ฅ It relaxes some IEEE floating-point rules for checking inputs against Not-a-Number (NAN), for performance ๐จ-minline-pltโ enables inlining of PLT entries for function calls to functions that aren't known to bind locally ๐ง It does nothing without-mfdpic๐-mmulticoreโ builds a standalone application for multicore Blackfin processors ๐ It uses the right start files and link scripts for multicore and defines the macro"__BFIN_MULTICORE"๐ It can only be used with-mcpu=bf561[-sirevision]๐ธ
This also works with -mcorea or -mcoreb for the one-application-per-core model ๐ซถ Without either of those, you get the single-application/dual-core model ๐ In that model, Core B's main function should be named "coreb_main" ๐ง
Without this option, you get the single-core application model โจ
-mcoreaโ builds a standalone application for Core A of BF561 in the one-application-per-core model ๐ฆ It uses the right start files and link scripts for Core A and defines"__BFIN_COREA"๐ It can only be used together with-mmulticore๐ฅ-mcorebโ builds a standalone application for Core B of BF561 in the one-application-per-core model ๐ It uses the right start files and link scripts for Core B and defines"__BFIN_COREB"๐ With this on, use"coreb_main"instead of"main"๐ It can only be used together with-mmulticore๐-msdramโ builds a standalone application for SDRAM ๐ It uses the right start files and link scripts to put the app into SDRAM and defines"__BFIN_SDRAM"๐ฆ The loader needs to initialize SDRAM before loading the app ๐ญ-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โ picks the target architecture name ๐ธ GCC uses it to decide what kind of instructions it can emit when generating assembly ๐ง The allowed names arec62x,c64x,c64x+,c67x,c67x+, andc674x๐-mbig-endianโ generates code for a big-endian target ๐ซถ-mlittle-endianโ generates code for a little-endian target ๐ This is the default โจ-msimโ picks startup files and a linker script that work with the simulator ๐ฅ-msdata=defaultโ puts small global and static data in the".neardata"section, which is pointed to by registerB14๐ Small uninitialized global and static data goes in".bss", which sits right next to".neardata"๐ฆ Small read-only data goes in".rodata"๐ Large data uses".fardata",".far", and".const"instead ๐-msdata=allโ puts all data, not just the small stuff, into the small-data sections ๐ It uses addressing relative to theB14register to get at it ๐ญ-msdata=noneโ no small-data sections at all ๐ Everything gets absolute addresses ๐ All initialized global and static data goes in".fardata", all uninitialized data goes in".far", and all constant data goes in".const"โญ
โจ CRIS Options โจ
These options are defined specifically for the CRIS ports ๐
-march=architecture-type/-mcpu=architecture-typeโ generates code for the specified architecture ๐ง The choices arev3,v8, andv10, which are ETRAX 4, ETRAX 100, and ETRAX 100 LX ๐ธ The default isv0๐-mtune=architecture-typeโ tunes everything applicable about the generated code to that architecture ๐ซถ It doesn't touch the ABI or 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=v8respectively ๐-mmul-bug-workaround/-mno-mul-bug-workaroundโ works around a bug in the"muls"and"mulu"instructions on CPU models where it applies ๐ฆ This is active by default ๐-mpdebugโ turns on CRIS-specific verbose debug info in the assembly code ๐ It also turns off the#NO_APPformatted-code indicator that the assembler normally sees at the top of the assembly file ๐-mcc-initโ don't reuse condition-code results from previous instructions ๐ญ Always emit compare and test instructions before using condition codes ๐-mno-side-effectsโ don't emit instructions with side effects in addressing modes, except post-increment ๐-mstack-align/-mno-stack-align/-mdata-align/-mno-data-align/-mconst-align/-mno-const-alignโ these arrange (or, with theno-forms, un-arrange) alignment of the stack frame, individual data, and constants to the maximum single data access size for the chosen CPU model โญ The default is 32-bit alignment ๐ ABI details like structure layout aren't affected by these ๐ง-m32-bit/-m16-bit/-m8-bitโ like the stack, data, and const align options above, these make the stack frame, writable data, and constants 32-bit, 16-bit, or 8-bit aligned ๐ธ The default is 32-bit alignment ๐-mno-prologue-epilogue/-mprologue-epilogueโ with-mno-prologue-epilogue, the normal function prologue and epilogue that set up the stack frame are left out, and no return instructions or return sequences are generated ๐ Only use this alongside careful visual inspection of the compiled code ๐ญ No warnings or errors are generated when call-saved registers need saving or local variable storage needs allocating ๐-melfโ legacy no-op option ๐ซถ-simโ links with input-output functions from a simulator library ๐ฅ Code, initialized data, and zero-initialized data get allocated consecutively ๐-sim2โ like-sim, but also 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 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 ๐ง Only applies to the ELF compiler ๐ฅ-mint32โ chooses a 32-bit wide integer type ๐-mbit-opsโ generates"sbit"and"cbit"instructions for bit manipulation โจ-mdata-model=modelโ chooses a data model ๐ The choices arenear,far, ormedium, andmediumis the default ๐ฆ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, andck810๐ The default isck810๐ซถ-mcpu=cpuโ okay bestie, this one lets you pick your C-SKY target processor ๐ฆ The validcpuvalues are below, and yes, it's a long list, but every single one is iconic:
ck801, ck801t, ck802, ck802t, ck802j, ck803, ck803h, ck803t,
ck803ht, ck803f, ck803fh, ck803e, ck803eh, ck803et, ck803eht,
ck803ef, ck803efh, ck803ft, ck803eft, ck803efht, ck803r1, ck803hr1,
ck803tr1, ck803htr1, ck803fr1, ck803fhr1, ck803er1, ck803ehr1,
ck803etr1, ck803ehtr1, ck803efr1, ck803efhr1, ck803ftr1, ck803eftr1,
ck803efhtr1, ck803s, ck803st, ck803se, ck803sf, ck803sef, ck803seft,
ck807e, ck807ef, ck807, ck807f, ck810e, ck810et, ck810ef, ck810eft,
ck810, ck810v, ck810f, ck810t, ck810fv, ck810tv, ck810ft,
ck810ftv.
-mbig-endian,-EB,-mlittle-endian,-ELโ pick big-endian or little-endian code ๐ธ Little-endian is the default, so if you do nothing, you're already serving โจ-mfloat-abi=nameโ this one picks which floating-point ABI you're rocking ๐ The permissible values aresoft,softfp, andhard:softโ GCC generates output full of library calls for floating-point operationssoftfpโ you get hardware floating-point instructions, but it still uses the soft-float calling conventionshardโ you get floating-point instructions and FPU-specific calling conventions
The default depends on your specific target configuration ๐ Also, heads up, the hard-float and soft-float ABIs are not link-compatible ๐ญ You have to compile your entire program with the same ABI, and link it with a compatible set of libraries.
-mhard-float,-msoft-floatโ choose hardware or software floating-point implementations ๐ The default is soft float.-mdouble-float,-mno-double-floatโ when-mhard-floatis in effect, this turns on double-precision float instructions ๐ฅ It's the default except when you're compiling for CK803.-mfdivdu,-mno-fdivduโ when-mhard-floatis in effect, this enables the"frecipd","fsqrtd", and"fdivd"instructions ๐ง Also the default except for CK803.-mfpu=fpuโ pick your floating-point processor ๐ฆ This only works with-mhard-float. The values forfpuare:fpv2_sfโ equivalent to-mno-double-float -mno-fdivdufpv2โ equivalent to-mdouble-float -mno-divdufpv2_divdโ equivalent to-mdouble-float -mdivdu
-melrw,-mno-elrwโ enable the extended"lrw"instruction ๐ It defaults to on for CK801 and off for everything else.-mistack,-mno-istackโ enable interrupt stack instructions. The default is off ๐ You need-mistackto handle the"interrupt"and"isr"function attributes, so don't skip it, bestie ๐ซถ-mmpโ enable multiprocessor instructions. Default is off โญ-mcpโ enable coprocessor instructions. Default is off ๐-mcacheโ also enables coprocessor instructions, so yes, it's the same vibe as-mcp๐ Default is off.-msecurityโ enable C-SKY security instructions. Default is off ๐ฅ-mtrustโ enable C-SKY trust instructions. Default is off ๐-mdsp,-medsp,-mvdspโ these enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively โจ All of them default to off.-mdiv,-mno-divโ generate divide instructions ๐ฆ Default is off.-msmart,-mno-smartโ generate code for Smart Mode, which only uses registers numbered 0-7 so you can use those sweet 16-bit instructions ๐ซถ This is ignored for CK801, where it's already required behavior. It defaults to on for CK802. For other targets, it's off.-mhigh-registers,-mno-high-registersโ generate code using the high registers numbered 16-31 ๐ธ This 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 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 is 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, though:
Using this option can result in code that is not compliant with the C-SKY V2 ABI prologue requirements, and that code cannot be debugged or backtraced ๐ It's disabled by default, so only turn it on if you really know what you're doing.
-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 ๐
Okay, so, FSF GCC on Darwin does not create "fat" object files. Instead, it makes an object file for the single architecture GCC was built to target. Apple's GCC, though, does create "fat" files if you use multiple -arch options. It does this by running the compiler or linker multiple times and then joining the results together with lipo ๐ฆ
The subtype of the file that gets created (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 is your friend โจ
The Darwin tools are kind of inconsistent when they hit an ISA mismatch ๐ The assembler, as, only allows instructions that are valid for the subtype of the file it's generating. So you can't put 64-bit instructions in a ppc750 object file. The linker for shared libraries, /usr/bin/libtool, fails and prints an error if you ask it to create a shared library with a less restrictive subtype than its input files. For 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โ adds the framework directorydirto the head of the list of directories searched for header files ๐ธ These directories are interleaved with the ones from-Ioptions, and they're scanned in a left-to-right order.
A framework directory is just a directory with frameworks in it. A framework is a directory that has a Headers and/or PrivateHeaders directory sitting directly inside it, and its name ends in .framework. The name of the framework is the directory name without the .framework part. Headers for the framework are found in one of those two directories, with Headers getting 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 shouldn't share a name with a framework, and if it does, you'll get a warning. Right now a subframework can't have subframeworks of its own, but the mechanism might be extended to support that later ๐
The standard frameworks live in /System/Library/Frameworks and /Library/Frameworks. An example include looks like "#include <Framework/header.h>", where Framework is the framework's name and header.h is found in the PrivateHeaders or Headers directory ๐
-iframeworkdirโ this is like-F, except the directory is treated as a system directory ๐ง The big difference is that with-iframework, the compiler doesn't warn about constructs inside header files found throughdir. 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. It's ON by default.-gfullโ emit debugging information for all symbols and types ๐-fconstant-cfstringsโ this is just an alias for-mconstant-cfstrings๐ฆ-mconstant-cfstringsโ when the NeXT runtime is being used (which is the default on these systems), this overrides any-fconstant-string-classsetting. It also makes"@"...""literals laid out as constant CoreFoundation strings ๐-mmacosx-version-min=versionโ sets the earliest version of MacOS X this executable will run on ๐ Typical values forversioninclude12,10.12, and10.5.8.
If the compiler was built to use the system's headers by default, then the default for this option is the system version the compiler is running on. Otherwise, the default makes choices that are compatible with as many systems and code bases as possible โจ
-mkernelโ enables 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: -mone-byte-bool makes GCC 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 system libraries. Only use it to conform to a non-default data model.
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ generate code that's suitable for fast turnaround development ๐ฅ This lets things like GDB dynamically load.ofiles into already-running programs.-findirect-dataand-ffix-and-continueare only here for backwards compatibility.-all_loadโ loads all members of static archive libraries ๐ง Seeman ld(1)for more information.-arch_errors_fatalโ makes the errors about files with the wrong architecture fatal ๐-bind_at_loadโ โจ Marks the output file so the dynamic linker binds every undefined reference when the file gets loaded or launched. Bestie, that's a whole vibe ๐ฆ-bundleโ ๐ Produces a Mach-O bundle format file. Checkman ld(1)for the tea on this one ๐-bundle_loader executableโ ๐ง Names the executable that's going to load the output file being linked. Also inman ld(1)๐-dynamiclibโ ๐ Makes a dynamic library instead of an executable when linking, using the Darwin libtool command. Iconic ๐-force_cpusubtype_ALLโ ๐ Gives GCC's output file the ALL subtype, instead of the one-mcpuor-marchwould pick. Not me overriding the vibe ๐
Okay so next up is the big squad of Darwin linker options. Each one gets handed straight over to the linker, no cap:
-allowable_client client_nameโ ๐ธ passed straight through to the Darwin linker-client_nameโ ๐ธ passed straight through to the Darwin linker-compatibility_versionโ ๐ธ passed straight through to the Darwin linker-current_versionโ ๐ธ passed straight through to the Darwin linker-dead_stripโ ๐ธ passed straight through to the Darwin linker-dependency-fileโ ๐ธ passed straight through to the Darwin linker-dylib_fileโ ๐ธ passed straight through to the Darwin linker-dylinker_install_nameโ ๐ธ passed straight through to the Darwin linker-dynamicโ ๐ธ passed straight through to the Darwin linker-exported_symbols_listโ ๐ธ passed straight through to the Darwin linker-filelistโ ๐ธ passed straight through to the Darwin linker-flat_namespaceโ ๐ธ passed straight through to the Darwin linker-force_flat_namespaceโ ๐ธ passed straight through to the Darwin linker-headerpad_max_install_namesโ ๐ธ passed straight through to the Darwin linker-image_baseโ ๐ธ passed straight through to the Darwin linker-initโ ๐ธ passed straight through to the Darwin linker-install_nameโ ๐ธ passed straight through to the Darwin linker-keep_private_externsโ ๐ธ passed straight through to the Darwin linker-multi_moduleโ ๐ธ passed straight through to the Darwin linker-multiply_definedโ ๐ธ passed straight through to the Darwin linker-multiply_defined_unusedโ ๐ธ passed straight through to the Darwin linker-noall_loadโ ๐ธ passed straight through to the Darwin linker-no_dead_strip_inits_and_termsโ ๐ธ passed straight through to the Darwin linker-nofixprebindingโ ๐ธ passed straight through to the Darwin linker-nomultidefsโ ๐ธ passed straight through to the Darwin linker-noprebindโ ๐ธ passed straight through to the Darwin linker-noseglinkeditโ ๐ธ passed straight through to the Darwin linker-pagezero_sizeโ ๐ธ passed straight through to the Darwin linker-prebindโ ๐ธ passed straight through to the Darwin linker-prebind_all_twolevel_modulesโ ๐ธ passed straight through to the Darwin linker-private_bundleโ ๐ธ passed straight through to the Darwin linker-read_only_relocsโ ๐ธ passed straight through to the Darwin linker-sectalignโ ๐ธ passed straight through to the Darwin linker-sectobjectsymbolsโ ๐ธ passed straight through to the Darwin linker-whyloadโ ๐ธ passed straight through to the Darwin linker-seg1addrโ ๐ธ passed straight through to the Darwin linker-sectcreateโ ๐ธ passed straight through to the Darwin linker-sectorderโ ๐ธ passed straight through to the Darwin linker-segaddrโ ๐ธ passed straight through to the Darwin linker-segs_read_only_addrโ ๐ธ passed straight through to the Darwin linker-segs_read_write_addrโ ๐ธ passed straight through to the Darwin linker-seg_addr_tableโ ๐ธ passed straight through to the Darwin linker-seg_addr_table_filenameโ ๐ธ passed straight through to the Darwin linker-seglinkeditโ ๐ธ passed straight through to the Darwin linker-segprotโ ๐ธ passed straight through to the Darwin linker-single_moduleโ ๐ธ passed straight through to the Darwin linker-staticโ ๐ธ passed straight through to the Darwin linker-sub_libraryโ ๐ธ passed straight through to the Darwin linker-sub_umbrellaโ ๐ธ passed straight through to the Darwin linker-twolevel_namespaceโ ๐ธ passed straight through to the Darwin linker-umbrellaโ ๐ธ passed straight through to the Darwin linker-undefinedโ ๐ธ passed straight through to the Darwin linker-unexported_symbols_listโ ๐ธ passed straight through to the Darwin linker-weak_reference_mismatchesโ ๐ธ passed straight through to the Darwin linker-whatsloadedโ ๐ธ passed straight through to the Darwin linker
These are all passed to the Darwin linker, and the Darwin linker's man page describes them in detail. Read that one if you want the full story ๐ซถ
โจ DEC Alpha Options โจ
These -m options are defined for the DEC Alpha implementations ๐ง
-mno-soft-float,-msoft-floatโ ๐ Use (or don't use) the hardware floating-point instructions for floating-point operations. With-msoft-float, functions inlibgcc.ado the floating-point work. Unless they're swapped out for routines that emulate those operations, or compiled to call such emulation routines, these routines issue floating-point operations. If you're compiling for an Alpha without floating-point operations, you have to make sure the library is built so it doesn't call them ๐ญ
Note that Alpha implementations without floating-point operations are required to have floating-point registers ๐ธ
-mfp-reg,-mno-fp-regsโ ๐ฆ Generates code that uses (or doesn't use) the floating-point register set.-mno-fp-regsimplies-msoft-float. If the floating-point register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results get passed in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value that's called by code compiled with-mno-fp-regsmust also be compiled with that option ๐
A typical use of this option is building a kernel that doesn't use, and so doesn't need to save and restore, any floating-point registers ๐ฅ
-mieeeโ ๐ The Alpha architecture has floating-point hardware optimized for maximum performance. It's mostly compliant with the IEEE floating-point standard, but full compliance needs 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 result 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. The reason is that the software functions in the GNU libc math libraries generate denormalized numbers, NaNs, and infs, and all of those will cause a program toSIGFPEwhen it tries to use the results without-mieee๐
-mieee-with-inexactโ ๐ง This is like-mieee, except the generated code also maintains the IEEE inexact-flag. Turning this on makes the generated code fully-compliant IEEE math. On top of"_IEEE_FP", the macro"_IEEE_FP_EXACT"gets defined too. On some Alpha implementations the resulting code may run significantly slower than the default. Since very little code 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โ ๐ Controls which floating-point related traps are enabled. Other Alpha compilers call this option-fptm trap-mode. The trap mode can be set to one of four values:nโ ๐ The default, normal setting. The only traps enabled are the ones that can't be disabled in software (like the division by zero trap).uโ ๐ธ On top of everythingnenables, underflow traps are enabled too.suโ ๐ฆ Likeu, but the instructions are marked as safe for software completion (check the Alpha architecture manual for details).suiโ ๐ฅ Likesu, but inexact traps are enabled as well.
-mfp-rounding-mode=rounding-modeโ ๐ Selects the IEEE rounding mode. Other Alpha compilers call this option-fprm rounding-mode. Therounding-modecan be one of:nโ โญ Normal IEEE rounding mode. Floating-point numbers get rounded towards the nearest machine number, or towards the even machine number in case of a tie.mโ ๐ Round towards minus infinity.cโ ๐ง Chopped rounding mode. Floating-point numbers get rounded towards zero.dโ ๐ Dynamic rounding mode. A field in the floating-point control register (fpcr, see the Alpha architecture reference manual) controls which rounding mode is 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 help it's impossible to recover from a floating trap, and program execution normally has to be terminated. GCC can generate code that helps operating system trap handlers figure out the exact location that caused a floating-point trap. Depending on what your application needs, you can pick different levels of precision:pโ ๐ธ Program precision. This is the default, and it means a trap handler can only identify which program caused a floating-point exception.fโ ๐ฆ Function precision. The trap handler can determine the function that caused a floating-point exception.iโ ๐ Instruction precision. The trap handler can determine the exact instruction that caused a floating-point exception.
Other Alpha compilers provide the equivalent options called -scope_safe and -resumption_safe ๐ซถ
-mieee-conformantโ ๐ Marks the generated code as IEEE conformant. You must not use this option unless you also specify-mtrap-precision=iand either-mfp-trap-mode=suor-mfp-trap-mode=sui. Its only effect is to emit the line.eflag 48in the function prologue of the generated assembly file ๐-mbuild-constantsโ ๐ง Normally GCC examines a 32- or 64-bit integer constant to see if it can build it from smaller constants in two or three instructions. If it can't, it outputs the constant as a literal and generates code to load it from the data segment at run time.
Use this option to require GCC to build all integer constants using code, even if it takes more instructions (the maximum is six) ๐
You typically use this option to build a shared library dynamic loader. Since it's a shared library itself, it has to relocate itself in memory before it can find the variables and constants in its own data segment ๐ญ
-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ ๐ Indicate whether GCC should generate code that uses the optional BWX, CIX, FIX and MAX instruction sets. The default is to use the instruction sets supported by the CPU type you specify with the-mcpu=option, or by the CPU GCC was built on if you don't specify one โจ-mfloat-vax,-mfloat-ieeeโ ๐ธ Generates code that uses (or doesn't use) VAX F and G floating-point arithmetic instead of IEEE single and double precision ๐ฆ-mexplicit-relocs,-mno-explicit-relocsโ ๐ Older Alpha assemblers had no way to generate symbol relocations except through assembler macros, and those macros don't allow optimal instruction scheduling. GNU binutils as of version 2.12 supports a new syntax that lets the compiler explicitly mark which relocations apply to which instructions. This option is mostly useful for debugging, since GCC detects the assembler's capabilities when it's built and sets the default to match ๐ง-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 get 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 with a single instruction ๐
The default is -mlarge-data. With this option the data area is limited to just below 2GB. Programs that need more than 2GB of data must use "malloc" or "mmap" to allocate the data in the heap instead of in the program's data segment ๐ฅ
When generating code for shared libraries, -fpic implies -msmall-data, and -fPIC implies -mlarge-data ๐ซถ
okay so these two are a whole size-vs-reach situation ๐ซถ
-msmall-text,-mlarge-textโ with-msmall-text, the compiler assumes the code for the entire program (or shared library) fits in 4MB ๐, so it's reachable with a branch instruction ๐ฆ. When you use-msmall-data, the compiler can assume all local symbols share the same$gpvalue, which means a function call drops from 4 instructions to just 1 โจ. The default is-mlarge-text. ๐-mcpu=cpu_typeโ sets the instruction set and instruction scheduling parameters for the machine typecpu_type๐ฅ. You can give 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 one, GCC defaults to the processor the compiler was built on ๐๏ธ.
Supported values for cpu_type are:
ev4,ev45,21064โ schedules as an EV4 with no instruction set extensions ๐ธev5,21164โ schedules as an EV5 with no instruction set extensions ๐ธev56,21164aโ schedules as an EV5 and supports theBWXextension ๐pca56,21164pc,21164PCโ schedules as an EV5 and supports theBWXandMAXextensions ๐ev6,21264โ schedules as an EV6 and supports theBWX,FIX, andMAXextensions ๐ฆev67,21264aโ schedules as an EV6 and supports theBWX,CIX,FIX, andMAXextensions ๐ฆ
Native toolchains also support the value native, which picks the best architecture option for the host processor ๐ง. -mcpu=native has no effect if GCC doesn't recognize the processor ๐.
-mtune=cpu_typeโ sets only the instruction scheduling parameters forcpu_type. The instruction set doesn't change, so no vibe shift there ๐ซถ.
Native toolchains also support the value native here too, 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โ sets the latency the scheduler should assume for typical memory references as the application sees them ๐ง . This number really depends on the application's memory access patterns and how big the external cache on the machine is ๐.
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, covering the Level 1, 2 & 3 caches (also called Dcache, Scache, and Bcache) and main memory ๐ง. Heads up thatL3is only valid for EV5 โ ๏ธ.
๐ง eBPF Options ๐ง
-mframe-limit=bytesโ 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 the targeted version of the Linux kernel imposes ๐ง.-mkernel=versionโ sets the minimum kernel version that will run your compiled program ๐ง. GCC uses this to figure out which instructions to use, which kernel helpers to allow, and so on ๐ค. Right nowversioncan 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,latest, ornative๐ .-mbig-endianโ generates code for a big-endian target ๐.-mlittle-endianโ generates code for a little-endian target. This is the default ๐.-mxbpfโ generates code for an expanded version of BPF ๐. It relaxes some of the restrictions the BPF architecture normally imposes, including this bit:-<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 ๐ฃ. It 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 is already provided, so there's no need to include the simulator library (libsim.a) on the linker command line ๐ง.
๐ฆ FT32 Options ๐ฆ
These options are defined specifically for the FT32 port ๐.
-msimโ says the program will run on the simulator ๐ฎ. This links in an alternate runtime startup and library. โ ๏ธ You must not use this option when generating programs that will run on real hardware! You have to provide your own runtime library for whatever I/O functions you need ๐.-mlraโ enables Local Register Allocation โจ. It's still experimental for FT32, so by default the compiler uses standard reload ๐งช.-mnodivโ doesn't usedivandmodinstructions ๐ .-mft32bโ enables use of the extended instructions of theFT32Bprocessor ๐.-mcompressโ compresses all code using theFt32Bcode compression scheme ๐๏ธ.-mnopmโ doesn't generate code that reads program memory ๐.
๐ FRV Options ๐
-mgpr-32โ only uses the first 32 general-purpose registers ๐.-mgpr-64โ uses all 64 general-purpose registers ๐ฆพ.-mfpr-32โ uses only the first 32 floating-point registers ๐ซ.-mfpr-64โ uses all 64 floating-point registers ๐.-mhard-floatโ uses hardware instructions for floating-point operations ๐ฅ.-msoft-floatโ uses library routines for floating-point operations instead ๐.-malloc-ccโ dynamically allocates condition code registers ๐ช.-mfixed-ccโ doesn't try to dynamically allocate condition code registers. It only usesicc0andfcc0๐.-mdwordโ changes the ABI to use double word instructions ๐งฉ.-mno-dwordโ doesn't use double word instructions ๐ .-mdoubleโ uses floating-point double instructions ๐.-mno-doubleโ doesn't use floating-point double instructions ๐ .-mmediaโ uses media instructions ๐ถ.-mno-mediaโ doesn't use media instructions ๐ .-mmuladdโ uses multiply and add/subtract instructions โ๏ธ.-mno-muladdโ doesn'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 does nothing without-mfdpic. It's on by default if you're optimizing for speed and compiling shared libraries (i.e.,-fPICor-fpic), or when an optimization option like-O3or above is on the command line ๐๏ธ.-mTLSโ assumes a large TLS segment when generating thread-local code ๐งต.-mtlsโ does not assume a large TLS segment when generating thread-local code ๐งถ.-mgprel-roโ enables the use of"GPREL"relocations in the FDPIC ABI for data known to be in read-only sections ๐. It's on by default, except for-fpicor-fpie. Even though it may help make the global offset table smaller, it trades 1 instruction for 4 in those cases ๐ค. With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols. It also avoids the need for a GOT entry for the referenced symbol, so it's more likely to be a win ๐. If it isn't,-mno-gprel-rocan be used to disable it ๐ .-multilib-library-picโ links with the (library, not FD) pic libraries ๐. It's implied by-mlibrary-pic, as well as by-fPICand-fpicwithout-mfdpic. You should never have to use it explicitly ๐ซ .-mlinked-fpโ follows the EABI requirement of always creating a frame pointer whenever a stack frame is allocated ๐ผ๏ธ. It's on by default and can be turned off with-mno-linked-fpโฌ๏ธ.-mlong-callsโ uses indirect addressing to call functions outside the current compilation unit ๐. This lets the functions be placed anywhere within the 32-bit address space ๐.-malign-labelsโ tries to align labels to an 8-byte boundary by inserting NOPs into the previous packet ๐. This only does something when VLIW packing is enabled. It doesn't create new packets; it just adds NOPs to existing ones ๐ง.-mlibrary-picโ generates position-independent EABI code ๐.-macc-4โ uses only the first four media accumulator registers 4๏ธโฃ.-macc-8โ uses all eight media accumulator registers 8๏ธโฃ.-mpackโ packs VLIW instructions ๐ฆ.-mno-packโ doesn't pack VLIW instructions ๐ .-mno-eflagsโ doesn't mark ABI switches ine_flags๐ซ.-mcond-moveโ enables the use of conditional-move instructions. This is the default โ .
๐ This switch is mainly for debugging the compiler, and it'll 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 it'll likely be removed in a future version.
-msccโ enables the use of conditional set instructions. This is the default โ .
๐ This switch is mainly for debugging the compiler, and it'll 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 it'll likely be removed in a future version.
-mcond-execโ enables the use of conditional execution. This is the default โ .
๐ This switch is mainly for debugging the compiler, and it'll 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 it'll likely be removed in a future version.
-mvliw-branchโ runs a pass to pack branches into VLIW instructions. This is the default โ .
๐ This switch is mainly for debugging the compiler, and it'll likely be removed in a future version.
-mno-vliw-branchโ doesn't run a pass to pack branches into VLIW instructions ๐ .
๐ This switch is mainly for debugging the compiler, and it'll likely be removed in a future version.
-mmulti-cond-execโ enables optimization of"&&"and"||"in conditional execution. This is the default โ .
๐ This switch is mainly for debugging the compiler, and it'll likely be removed in a future version.
โจ Machine-Dependent Options, Part Two โจ
-mno-multi-cond-execโ bestie, this one turns OFF the optimization of"&&"and"||"in conditional execution ๐
This switch is mainly for debugging the compiler and will likely be removed in a future version, so don't build your whole life around it ๐
-mnested-cond-execโ turns ON nested conditional execution optimizations, and it's on by default ๐
Same deal: this one is mainly for compiler debugging and will likely get removed in a future version ๐ง
-mno-nested-cond-execโ the opposite energy! It turns OFF nested conditional execution optimizations ๐ฅฒ
Again, mainly a debugging tool, and it'll likely be removed in a future version โจ
-moptimize-membarโ this one cleans up the clutter by removing redundant"membar"instructions from the compiler-generated code ๐งน It's enabled by default, so you're already getting this glow-up ๐ฆ-mno-optimize-membarโ the no-cap opt-out! It disables that automatic removal of redundant"membar"instructions from the generated code ๐ โโ๏ธ-mtomcat-statsโ tells gas to print out tomcat statistics ๐ฑ๐-mcpu=cpuโ pick your processor type, the main character of the codegen ๐ The possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300andsimple๐ธ
โจ GNU/Linux Options โจ
These -m options are defined for GNU/Linux targets, so if you're on Linux it's giving relevant ๐ง๐
-mglibcโ use the GNU C library ๐ This is the default, except on*-*-linux-*uclibc*,*-*-linux-*musl*and*-*-linux-*android*targets ๐-muclibcโ use the uClibc C library ๐ This is the default on*-*-linux-*uclibc*targets ๐-mmuslโ use the musl C library ๐ This is the default on*-*-linux-*musl*targets โจ-mbionicโ use the Bionic C library ๐ฑ This is the default on*-*-linux-*android*targets ๐ค-mandroidโ compile code that's compatible with the Android platform ๐ฆ This is the default on*-*-linux-*android*targets, and it's a whole vibe ๐ฅ
When compiling, this option enables -mbionic, -fPIC, -fno-exceptions and -fno-rtti by default ๐ซถ When linking, it makes the GCC driver pass Android-specific options to the linker ๐ And finally, it causes the preprocessor macro "__ANDROID__" to be defined ๐
-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 driver passes standard Linux linking options to the linker ๐ง
โจ H8/300 Options โจ
These -m options are defined for the H8/300 implementations, so if that's your chip, this section is literally for you ๐ง
-mrelaxโ shortens some address references at link time, when it's possible ๐ช It does this by using the linker option-relax๐-mhโ generate code for the H8/300H ๐ธ-msโ generate code for the H8S ๐-mnโ generate code for the H8S and H8/300H in the normal mode ๐ This switch has to be used with either-mhor-ms, so don't forget your partner ๐ซถ-ms2600โ generate code for the H8S/2600 ๐ฆ This switch has to be used with-ms๐-mexrโ the extended registers get stored on the stack before a function with the monitor attribute executes ๐ This is the default option, and it's only valid for H8S targets ๐ฅ-mno-exrโ the extended registers do not get stored on the stack before a function with the monitor attribute executes ๐ โโ๏ธ This is the default for that scenario, and it's also 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 default for the H8/300H and H8S is to align longs and floats on 4-byte boundaries, but-malign-300causes them to be aligned on 2-byte boundaries instead ๐ This option has no effect on the H8/300 ๐
โจ HPPA Options โจ
These -m options are defined for the HPPA family of computers, so if you're giving HP-UX or PA-RISC energy, this part's for you ๐ฅ๏ธ๐
-march=architecture-typeโ generate code for the architecture you specify ๐๏ธ The choices for architecture-type are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors ๐ฅ
To figure out the right architecture option for your machine, refer to /usr/lib/sched.models on an HP-UX system ๐ Code compiled for lower numbered architectures runs on higher numbered architectures, but not the other way around, so don't be that person ๐
-mpa-risc-1-0,-mpa-risc-1-1,-mpa-risc-2-0โ these are synonyms for-march=1.0,-march=1.1, and-march=2.0respectively ๐ฏโโ๏ธ-mcaller-copiesโ the caller copies function arguments that get passed by hidden reference ๐ซฑ This option should be used with care, because it is not compatible with the default 32-bit runtime ๐ฌ However, only aggregates larger than eight bytes are passed by hidden reference, and this option gives better compatibility with OpenMP ๐ซถ-mjump-in-delayโ this one gets ignored โ It's only here for compatibility purposes, so it's basically a vibe with no effect ๐-mdisable-fpregsโ prevents 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. Yep, it just stops. Don't say I didn't warn you ๐
-mdisable-indexingโ prevents the compiler from using indexing address modes ๐ This avoids 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 generate faster indirect calls and use unscaled index address modes โก
Such code is suitable for level 0 PA systems and kernels ๐ฅ๏ธ
-mfast-indirect-callsโ generates code that assumes calls never cross space boundaries ๐โโ๏ธ This lets GCC emit code that performs faster indirect calls โก
Heads up though: 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 that the register allocator cannot use, which is super useful when compiling kernel code ๐งฉ A register range is specified as two registers separated by a dash, and you can specify multiple register ranges separated by a comma ๐-mlong-load-storeโ generates 3-instruction load and store sequences, which are sometimes required by the HP-UX 10 linker ๐ This is equivalent to the+koption to the HP compilers ๐-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 for cpu-type are700 7100,7100LC,7200,7300and8000๐ Refer to/usr/lib/sched.modelson an HP-UX system to determine the proper scheduling option for your machine ๐ The default scheduling is8000โจ-mlinker-optโ enables the optimization pass in the HP-UX linker ๐ง
Heads up, bestie: this makes symbolic debugging impossible ๐ญ It also triggers a bug in the HP-UX 8 and HP-UX 9 linkers, where they give bogus error messages when linking some programs ๐
-msoft-floatโ generates output containing library calls for floating point ๐งฎ
Warning, this one is a whole thing: the requisite libraries are not available for all HPPA targets ๐จ Normally the facilities of the machine's usual C compiler are used, but this cannot be done directly in cross-compilation, so you have to make your own arrangements to provide suitable library functions for cross-compilation ๐ ๏ธ
Also, -msoft-float changes the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐งต In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work ๐ซถ
-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 does not affect which ld gets called, it only changes what parameters get passed to that ld ๐คทโโ๏ธ The ld that gets called is determined by the --with-ld configure option, GCC's program search path, and finally by the user's PATH ๐บ๏ธ You can print the linker GCC uses with which `gcc -print-prog-name=ld` ๐ This option is only available on the 64-bit HP-UX GCC, i.e. configured with hppa*64*-*-hpux* ๐ง
-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 ๐จ๏ธ
Same tea as before: this option does not affect which ld is called, it only changes what parameters are passed to that ld ๐ซ The ld that is called is determined by the --with-ld configure option, GCC's program search path, and finally by the user's PATH ๐บ๏ธ The linker used by GCC can be printed using which `gcc -print-prog-name=ld` ๐ This option is only available on the 64-bit HP-UX GCC, i.e. configured with hppa*64*-*-hpux* ๐ง
-mlong-callsโ generates code that uses long call sequences ๐ This ensures that a call is always able to reach linker generated stubs ๐งญ
The default is to generate long calls only when the distance from the call site to the beginning of the function or translation unit (depending on the case) goes past a predefined limit set by the branch type being used ๐ The limits for normal calls are 7,600,000 and 240,000 bytes, respectively for the PA 2.0 and PA 1.X architectures ๐ Sibcalls are always limited at 240,000 bytes ๐ชง
Distances are measured from the beginning of functions when using the -ffunction-sections option, or when using the -mgas and -mno-portable-runtime options together under HP-UX with the SOM linker ๐งต
Honestly, it's normally not desirable to use this option because it degrades performance ๐ But it may be useful in large applications, particularly when partial linking is used to build the application ๐๏ธ
The types of long calls used depend on the capabilities of the assembler and linker, and the type of code being generated ๐งฉ The impact on systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, should be relatively small ๐ท However, an indirect call is used on 32-bit ELF systems in pic code, and it is quite long ๐ข
-munix=unix-stdโ okay bestie, this one sets up the compiler predefines and picks a startfile for whichever UNIX standard you name. The choices are93,95and98๐93is supported on all HP-UX versions ๐ฆ95is available on HP-UX 10.10 and later98is available on HP-UX 11.11 and later- The defaults are
93for HP-UX 10.00,95for HP-UX 10.10 through 11.00, and98for HP-UX 11.11 and later ๐ธ -munix=93gives you the same predefines as GCC 3.3 and 3.4-munix=95adds the predefines"XOPEN_UNIX"and"_XOPEN_SOURCE_EXTENDED", plus the startfileunix95.oโจ-munix=98adds the predefines"_XOPEN_UNIX","_XOPEN_SOURCE_EXTENDED","_INCLUDE__STDC_A1_SOURCE"and"_INCLUDE_XOPEN_SOURCE_500", plus the startfileunix98.o๐
โ ๏ธ Be careful with this one, bestie. It changes the interfaces for various library routines and affects the operational behavior of the C library. Thus, extreme care is needed when using this option ๐ญ
Library code that is meant to work with more than one UNIX standard has to test, set and restore the variable __xpg4_extended_mask as appropriate. Most GNU software doesn't provide this capability ๐
-nolibdldโ this stops the generation of link options that searchlibdld.slwhen-staticis specified on HP-UX 10 and later ๐ง-staticโ the HP-UX version ofsetlocalein libc depends onlibdld.sl, and there isn't an archive version oflibdld.sl. So when you use-static, you need special link options to sort that dependency out ๐ On HP-UX 10 and later, the GCC driver adds those options for you when-staticis used, and 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 GCC driver adding these link options, use-nolibdld๐ซถ-threadsโ adds support for multithreading with the dce thread library under HP-UX. This one sets flags for both the preprocessor and the linker โจ
๐ธ IA-64 Options ๐ธ
These are the -m options defined for the Intel IA-64 architecture ๐
-mbig-endianโ generates code for a big-endian target. This is the default for HP-UX ๐-mlittle-endianโ generates code for a little-endian target. This is the default for AIX5 and GNU/Linux ๐ฆ-mgnu-as,-mno-gnu-asโ generates (or doesn't generate) code for the GNU assembler. This is the default ๐-mgnu-ld,-mno-gnu-ldโ generates (or doesn't generate) code for the GNU linker. This is the default ๐-mno-picโ generates code that does not use a global pointer register. The result is not position independent code, and it violates the IA-64 ABI ๐-mvolatile-asm-stop,-mno-volatile-asm-stopโ generates (or doesn't generate) a stop bit immediately before and after volatile asm statements ๐-mregister-names,-mno-register-namesโ generates (or doesn't generate)in,loc, andoutregister names for the stacked registers. This may make assembler output more readable ๐ง-mno-sdata,-msdataโ disables (or enables) optimizations that use the small data section. This may be useful for working around optimizer bugs ๐-mconstant-gpโ generates code that uses a single constant global pointer value. This is useful when compiling kernel code ๐-mauto-picโ generates code that is self-relocatable. This implies-mconstant-gp, and it's useful when compiling firmware code ๐ฅ-minline-float-divide-min-latencyโ generates code for inline divides of floating-point values using the minimum latency algorithm โญ-minline-float-divide-max-throughputโ generates code for inline divides of floating-point values using the maximum throughput algorithm โญ-mno-inline-float-divideโ does not generate inline code for divides of floating-point values ๐-minline-int-divide-min-latencyโ generates code for inline divides of integer values using the minimum latency algorithm ๐-minline-int-divide-max-throughputโ generates code for inline divides of integer values using the maximum throughput algorithm ๐-mno-inline-int-divideโ does not generate inline code for divides of integer values ๐-minline-sqrt-min-latencyโ generates code for inline square roots using the minimum latency algorithm ๐ธ-minline-sqrt-max-throughputโ generates code for inline square roots using the maximum throughput algorithm ๐ธ-mno-inline-sqrtโ does not generate inline code for"sqrt"๐-mfused-madd,-mno-fused-maddโ does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions. The default is to use these instructions ๐ฅ-mno-dwarf2-asm,-mdwarf2-asmโ doesn't (or does) generate assembler code for the DWARF line number debugging info. This may be useful when you're not using the GNU assembler ๐ฆ-mearly-stop-bits,-mno-early-stop-bitsโ allows stop bits to be placed earlier than immediately before the instruction that triggered the stop bit. This can improve instruction scheduling, but it doesn't always do so โจ-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers. A fixed register is one the register allocator cannot use, which is useful when compiling kernel code. A register range is written as two registers separated by a dash, and you can separate multiple register ranges with a comma ๐-mtls-size=tls-sizeโ specifies the bit size of immediate TLS offsets. Valid values are14,22, and64๐-mtune=cpu-typeโ tunes the instruction scheduling for a particular CPU. Valid values areitanium,itanium1,merced,itanium2, andmckinley๐ง-milp32,-mlp64โ generates code for a 32-bit or 64-bit environment. The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits. These are HP-UX specific flags ๐-mno-sched-br-data-spec,-msched-br-data-specโ (dis/en)ables data speculative scheduling before reload. This results in generation of"ld.a"instructions and the corresponding check instructions ("ld.c"/"chk.a"). The default setting is disabled ๐ฆ-msched-ar-data-spec,-mno-sched-ar-data-specโ (en/dis)ables data speculative scheduling after reload. This results in generation of"ld.a"instructions and the corresponding check instructions ("ld.c"/"chk.a"). The default setting is enabled ๐-mno-sched-control-spec,-msched-control-specโ (dis/en)ables control speculative scheduling. This feature is only available during region scheduling (that is, before reload). It results in generation of the"ld.s"instructions and the corresponding check instructions"chk.s". The default setting is disabled ๐ฅ-msched-br-in-data-spec,-mno-sched-br-in-data-specโ (en/dis)ables speculative scheduling of the instructions that depend on the data speculative loads before reload. This is only effective with-msched-br-data-specenabled. The default setting is enabled ๐ธ-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ (en/dis)ables speculative scheduling of the instructions that depend on the data speculative loads after reload. This is only effective with-msched-ar-data-specenabled. The default setting is enabled ๐ธ-msched-in-control-spec,-mno-sched-in-control-specโ (en/dis)ables speculative scheduling of the instructions that depend on the control speculative loads. This is only effective with-msched-control-specenabled. The default setting is enabled ๐ธ-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ if enabled, data-speculative instructions are only chosen for scheduling when there are no other choices at the moment. This makes the use of data speculation much more conservative. The default setting is disabled ๐-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ if enabled, control-speculative instructions are only chosen for scheduling when there are no other choices at the moment. This makes the use of control speculation much more conservative. The default setting is disabled ๐-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ if enabled, speculative dependencies are considered when computing the instruction priorities. This makes the use of speculation a bit more conservative. The default setting is disabled ๐-msched-spec-ldcโ 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 are not likely to cause a conflict when placed into the same instruction group. This option is disabled by default ๐-msel-sched-dont-check-control-specโ generates checks for control speculation in selective scheduling. This flag is disabled by default ๐-msched-max-memory-insns=max-insnsโ sets a limit on the number of memory insns per instruction group, giving lower priority to subsequent memory insns that try to schedule in the same instruction group. This is frequently useful for preventing cache bank conflicts. The default value is1๐-msched-max-memory-insns-hard-limitโ makes the limit set bymsched-max-memory-insnsa hard limit, disallowing more than that number in an instruction group. Otherwise the limit is "soft", which means non-memory operations are preferred when the limit is reached, but memory operations may still be scheduled ๐
๐ง LM32 Options ๐ง
These -m options are defined for the LatticeMico32 architecture ๐
-mbarrel-shift-enabledโ enables barrel-shift instructions ๐ฆ-mdivide-enabledโ enables divide and modulus instructions ๐ฆ-mmultiply-enabledโ enables multiply instructions ๐ฆ-msign-extend-enabledโ enables sign extend instructions ๐ฆ-muser-enabledโ enables user-defined instructions ๐ฆ
๐ M32C Options ๐
-mcpu=nameโ okay so this one picks the CPU you're generating code for ๐ name can ber8cfor the R8C/Tiny series,m16cfor the M16C (up to /60) series,m32cmfor the M16C/80 series, orm32cfor the M32C/80 series ๐
โจ M32R/D Options โจ
These -m options are defined for Renesas M32R/D architectures ๐ฆ
-msimโ bestie, this tells GCC the program will run on the simulator ๐ง It links in an alternate runtime library that supports stuff like file I/O. > Never use this on real hardware! You need to provide your own runtime library for whatever I/O functions you need.-memregs=numberโ this 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 the available registers and the performance hit of using memory instead of registers. Every module in a program has to be compiled with the same value for this option. > Don't use this with GCC's default runtime libraries. It's not it, sis ๐
โจ M32R/D Options โจ
These -m options are defined for Renesas M32R/D architectures ๐ฆ
-m32r2โ generate code for the M32R/2 ๐ธ-m32rxโ generate code for the M32R/X ๐ธ-m32rโ generate code for the M32R. This is the default ๐-mmodel=smallโ this is the default ๐ It assumes all objects live in the lower 16MB of memory (so their addresses can be loaded with theld24instruction), and that all subroutines are reachable with theblinstruction. The addressability of a particular object can be set with themodelattribute.-mmodel=mediumโ objects may be anywhere in the 32-bit address space (the compiler generatesseth/add3instructions to load their addresses), and all subroutines are reachable with theblinstruction ๐-mmodel=largeโ objects may be anywhere in the 32-bit address space (the compiler generatesseth/add3instructions to load their addresses), and subroutines may not be reachable with theblinstruction. The compiler generates the much slowerseth/add3/jlinstruction sequence ๐ข-msdata=noneโ disables the small data area ๐ โโ๏ธ Variables go into one of.data,.bss, or.rodata(unless thesectionattribute has been specified). This is the default. The small data area consists of the sections.sdataand.sbss. Objects can be explicitly put in the small data area with thesectionattribute using one of these sections.-msdata=sdataโ puts small global and static data in the small data area, but doesn't generate special code to reference them ๐-msdata=useโ puts small global and static data in the small data area and generates special instructions to reference them โจ-G numโ puts global and static objects less than or equal tonumbytes into the small data or BSS sections instead of the normal data or BSS sections ๐ง The default value ofnumis8. The-msdataoption must be set to one ofsdataorusefor this option to have any effect. All modules should be compiled with the same-G numvalue. Mixing different values ofnummay or may 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 programs ๐-malign-loopsโ aligns all loops to a 32-byte boundary ๐-mno-align-loopsโ doesn't enforce a 32-byte alignment for loops. This is the default ๐-missue-rate=numberโ issuesnumberinstructions per cycle.numbercan only be1or2โก-mbranch-cost=numberโnumbercan only be1or2. If it's1, branches are preferred over conditional code. If it's2, the opposite applies ๐-mflush-trap=numberโ specifies the trap number to use to flush the cache. The default is12. Valid numbers are between0and15inclusive ๐ชค-mno-flush-trapโ specifies that the cache cannot be flushed by using a trap ๐ซ-mflush-func=nameโ specifies the name of the operating system function to call to flush the cache. The default is_flush_cache, but a function call is only used if a trap is not available ๐-mno-flush-funcโ indicates there is no OS function for flushing the cache ๐ค
โจ M680x0 Options โจ
These are the -m options defined for M680x0 and ColdFire processors ๐ธ The default settings depend on which architecture was selected when the compiler was configured, so the defaults for the most common choices are given below.
-march=archโ generates code for a specific M680x0 or ColdFire instruction set architecture ๐๏ธ Valid values ofarchfor M680x0 architectures are:68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures are selected according to Freescale's ISA classification, and the valid values are:isaa,isaaplus,isabandisac.
GCC defines a macro __mcfarch__ whenever it's generating code for a ColdFire target. The arch in this macro is one of the -march arguments above.
When used together, -march and -mtune select code that runs on a family of similar processors but is optimized for a particular microarchitecture ๐ง
-mcpu=cpuโ generates code for a specific M680x0 or ColdFire processor ๐ป The M680x0 cpus are:68000,68010,68020,68030,68040,68060,68302,68332andcpu32. The ColdFire cpus are in the table below, which also sorts the CPUs into families ๐
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
-mcpu=cpu overrides -march=arch if arch is compatible with cpu. Other combinations 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 is given by the table above ๐ช
-mtune=tuneโ tunes the code for a particular microarchitecture, within the constraints set by-marchand-mcpu๐ฏ The M680x0 microarchitectures are:68000,68010,68020,68030,68040,68060andcpu32. The ColdFire microarchitectures are:cfv1,cfv2,cfv3,cfv4andcfv4e.
You can also use -mtune=68020-40 for code that needs to run relatively well on 68020, 68030 and 68040 targets. -mtune=68020-60 is similar but includes 68060 targets as well. These two options select the same tuning decisions as -m68020-40 and -m68020-60 respectively ๐ฅฐ
GCC defines the macros __mcarch and __mcarch__ when tuning for 680x0 architecture arch. It also defines mcarch unless either -ansi or a non-GNU -std option is used. If GCC is tuning for a range of architectures, as selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in 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 inhibits the use of 68881/68882 instructions that have to be emulated by software on the 68040. Use this 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 inhibits the use of 68020 and 68881/68882 instructions that have to be emulated by software on the 68060. Use this if your 68060 doesn't have code to emulate those instructions ๐ ๏ธ-mcpu32โ generates output for a CPU32. This is the default when the compiler is configured for CPU32-based systems. It's equivalent to-march=cpu32๐ท Use this for microcontrollers with a CPU32 or CPU32+ core, including the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360.-m5200โ generates output for a 520X ColdFire CPU. This is the default when the compiler is configured for 520X-based systems. It's equivalent to-mcpu=5206, and is now deprecated in favor of that option ๐ฅ Use this for microcontrollers with a 5200 core, including the MCF5202, MCF5203, MCF5204 and MCF5206.-m5206eโ generates output for a 5206e ColdFire CPU. The option is now deprecated in favor of the equivalent-mcpu=5206e๐ฅ-m528xโ generates output for a member of the ColdFire 528X family. The option is now deprecated in favor of the equivalent-mcpu=528x๐ฅ-m5307โ generates output for a ColdFire 5307 CPU. The option is now deprecated in favor of the equivalent-mcpu=5307๐ฅ
๐ ColdFire Options, Continued ๐
-m5407โ okay so this one makes output for a ColdFire 5407 CPU ๐ but it's deprecated now, so just use-mcpu=5407instead, it's the same thing โจ-mcfv4eโ this is for the ColdFire V4e family (think 547x/548x chips) ๐ฆ It also lets you use the hardware floating-point instructions. It's equivalent to-mcpu=547x, and it's deprecated, so-mcpu=547xis the move ๐-m68020-40โ makes output for a 68040 but doesn't touch any of the new instructions ๐ธ The result runs pretty efficiently on a 68020/68881, a 68030, or a 68040. The generated code does use the 68881 instructions that get emulated on the 68040.
This is equivalent to -march=68020 -mtune=68020-40.
-m68020-60โ same energy, but for a 68060 ๐ Again no new instructions, and the code runs relatively efficiently on a 68020/68881, a 68030, or a 68040. The generated code does use the 68881 instructions that get emulated on the 68060.
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 that have an FPU. It defines the macro__HAVE_68881__on M680x0 targets and__mcffpu__on ColdFire targets.-msoft-floatโ the opposite vibe ๐ซถ No floating-point instructions at all, you get library calls instead. This is the default for 68000, 68010, and 68832 targets, and also for ColdFire devices with no FPU.-mdiv,-mno-divโ-mdivgenerates ColdFire hardware divide and remainder instructions, and-mno-divskips them ๐ง If-marchis used without-mcpu, the default is "on" for ColdFire architectures and "off" for M680x0 architectures. Otherwise the default comes from the target CPU, either the default CPU or whichever one you picked with-mcpu. For example, the default is "off" for-mcpu=5206and "on" for-mcpu=5206e.
GCC defines the macro __mcfhwdiv__ when this option is enabled.
-mshortโ treats typeintas 16 bits wide, likeshort intโจ Parameters passed on the stack also get aligned to a 16-bit boundary, even on targets whose API says to promote them to 32-bit.-mno-shortโ the default, whereintis not 16 bits wide ๐-mnobitfield,-mno-bitfieldโ no bit-field instructions for you ๐ โโ๏ธ The-m68000,-mcpu32, and-m5200options all imply-mnobitfield.-mbitfieldโ yes to bit-field instructions ๐ The-m68020option implies-mbitfield, and it's the default if you use a configuration designed for a 68020.-mrtdโ okay this one is a whole vibe ๐ It switches to a different function-calling convention, where functions with a fixed number of arguments return with thertdinstruction, which pops their arguments while it returns. That saves one instruction in the caller, since the caller doesn't have to pop anything.
But 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). Otherwise you get 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 not with this one, so be careful ๐
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 alignsint,long,long long,float,double, andlong doublevariables 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 the -malign-int switch, GCC aligns structures containing the above types differently than most published application binary interface specifications for the m68k. Heads up, bestie ๐
-mpcrelโ uses the pc-relative addressing mode of the 68000 directly, instead of going through a global offset table ๐ฆ At the moment this option implies-fpic, which allows at most a 16-bit offset for pc-relative addressing.-fPICisn't presently 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 that unaligned memory references get handled by the system, and-mstrict-alignmeans it does assume that ๐ซถ-msep-dataโ generates code that lets the data segment live in a different area of memory from the text segment ๐ง This allows execute-in-place in an environment without virtual memory management. 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 allows 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โ specifies the identification number of the ID-based shared library being compiled ๐ Specifying0generates more compact code. Specifying other values forces the allocation of that number to the current library, but that's no more space- or time-efficient than leaving this option out.-mxgot,-mno-xgotโ when generating position-independent code for ColdFire,-mxgotgenerates code that works if the GOT has more than 8192 entries ๐ฅ This code is larger and slower than code generated without this option. On M680x0 processors 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 that happens, recompile your code with -mxgot, and it should work with very large GOTs. Just know that code generated with -mxgot is less efficient, since it takes 4 instructions to fetch the value of a global symbol.
Some linkers, including newer versions of the GNU linker, can create multiple GOTs and sort GOT entries. If you have one of those, you should only need -mxgot when compiling a single object file that accesses more than 8192 GOT entries. Very few do ๐ญ
These options have no effect unless GCC is generating position-independent code.
-mlong-jump-table-offsetsโ uses 32-bit offsets inswitchtables ๐ The default is 16-bit offsets.
๐ฆ MCore Options ๐ฆ
These are the -m options defined for the Motorola M*Core processors ๐
-mhardlit,-mno-hardlitโ inlines constants into the code stream if it can be done in two instructions or less โจ-mdiv,-mno-divโ-mdivuses 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โ-mwide-bitfieldsalways treats bit-fields asint-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 the simulator library (libsim.a) gets left off the linker command line ๐-mstack-increment=sizeโ sets the maximum amount for a single stack increment operation ๐ Big values can speed up programs with functions that need a lot of stack space, but they can also cause a segmentation fault if the stack gets extended too much. The default value is0x1000.
๐ง MeP Options ๐ง
-mabsdiffโ enables theabsinstruction, which gives you the absolute difference between two registers ๐-mall-optsโ enables all the optional instructions ๐ฅ That's average, multiply, divide, bit operations, leading zero, absolute difference, min/max, clip, and saturation. Full main character energy ๐-maverageโ enables theaveinstruction, which computes the average of two registers โจ-mbased=nโ variables of sizenbytes or smaller get placed in the.basedsection by default ๐ Based variables use the$tpregister as a base register, and the.basedsection 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 ๐ธ Thenamecan betiny,near, orfar.-mclipโ enables theclipinstruction ๐ซถ Heads up:-mclipisn't useful unless you also provide-mminmax.-mconfig=nameโ picks one of the built-in core configurations ๐ Each MeP chip has one or more modules in it, and each module has a core CPU plus a bunch 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 matching 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.-mdcโ causes constant variables to be placed in the.nearsection โจ-mdivโ enables thedivanddivuinstructions ๐-mebโ generates big-endian code ๐
-mel
- Hmm, okay so this one is about little-endian code. Bestie,
-meltells the compiler to generate little-endian code ๐ -mio-volatileโ okay this one is giving "treat it with care" energy ๐ซถ It tells the compiler that any variable marked with the "io" attribute is to be considered volatile โจ-mlโ causes variables to be assigned to the ".far" section by default ๐ง-mleadzโ enables the "leadz" (leading zero) instruction ๐ธ-mmโ causes variables to be assigned to the ".near" section by default ๐ฆ-mminmaxโ enables the "min" and "max" instructions ๐-mmultโ enables the multiplication and multiply-accumulate instructions ๐ฅ-mno-optsโ disables all the optional instructions enabled by-mall-opts๐-mrepeatโ enables the "repeat" and "erepeat" instructions, 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%gpbase 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" ๐ซถ-msdramโ links the SDRAM-based runtime instead of the default ROM-based runtime ๐-msimโ links the simulator run-time libraries ๐-msimnovecโ links the simulator runtime libraries, excluding 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 ๐ธ-mtiny=nโ variables that arenbytes or smaller are allocated to the ".tiny" section ๐ง These variables use the$gpbase register. The default for this option is4, but note that there's a 65536-byte limit to the ".tiny" section ๐ญ
โจ MicroBlaze Options โจ
-msoft-floatโ uses software emulation for floating point (default) ๐-mhard-floatโ uses hardware floating-point instructions ๐ฅ-mmemcpyโ does not optimize block moves, uses "memcpy" instead ๐-mno-clearbssโ this option is deprecated. Use-fno-zero-initialized-in-bssinstead ๐-mcpu=cpu-typeโ uses features of, and schedules code for, the given CPU ๐ Supported values are in the formatvX.YY.Z, whereXis a major version,YYis the minor version, andZis compatibility code. Example values arev3.00.a,v4.00.b,v5.00.a,v5.00.b,v6.00.a๐-mxl-soft-mulโ uses software multiply emulation (default) ๐ฆ-mxl-soft-divโ uses software emulation for divides (default) ๐ซถ-mxl-barrel-shiftโ uses the hardware barrel shifter ๐-mxl-pattern-compareโ uses pattern compare instructions ๐ง-msmall-dividesโ uses table lookup optimization for small signed integer divisions ๐ธ-mxl-stack-checkโ this option is deprecated. Use-fstack-checkinstead ๐-mxl-gp-optโ uses GP-relative ".sdata"/".sbss" sections ๐-mxl-multiply-highโ uses multiply high instructions for the high part of a 32x32 multiply ๐ฅ-mxl-float-convertโ uses hardware floating-point conversion instructions โจ-mxl-float-sqrtโ uses the hardware floating-point square root instruction โญ-mbig-endianโ generates code for a big-endian target ๐-mlittle-endianโ generates code for a little-endian target ๐-mxl-reorderโ uses reorder instructions (swap and byte reversed load/store) ๐-mxl-mode-app-modelโ selects application modelapp-model. Valid models are:executableโ normal executable (default), uses startup codecrt0.o๐-mpic-data-is-text-relativeโ assumes 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 ๐ฆxmdstubโ for use with 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. 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 usescrt3.oas a startup file ๐ง
Option -xl-mode-app-model is a deprecated alias for -mxl-mode-app-model ๐
โจ MIPS Options โจ
-EBโ generates big-endian code ๐ธ-ELโ generates little-endian code. This is the default formips*el-*-*configurations ๐-march=archโ generates code that runs onarch, which can be the name of a generic MIPS ISA, or the name of a particular processor ๐ The ISA names are:mips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5andmips64r6. The processor names are:4kc,4km,4kp,4ksc,4kec,4kem,4kep,4ksd,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,24kec,24kef2_1,24kef1_1,34kc,34kf2_1,34kf1_1,34kn,74kc,74kf2_1,74kf1_1,74kf3_2,1004kc,1004kf2_1,1004kf1_1,i6400,i6500,interaptiv,loongson2e,loongson2f,loongson3a,gs464,gs464e,gs264e,m4k,m14k,m14kc,m14ke,m14kec,m5100,m5101,octeon,octeon+,octeon2,octeon3,orion,p5600,p6600,r2000,r3000,r3900,r4000,r4400,r4600,r4650,r4700,r5900,r6000,r8000,rm7000,rm9000,r10000,r12000,r14000,r16000,sb1,sr71000,vr4100,vr4111,vr4120,vr4130,vr4300,vr5000,vr5400,vr5500,xlrandxlp. The special valuefrom-abiselects the most compatible architecture for the selected ABI (that is,mips1for 32-bit ABIs andmips3for 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 the target architecture, as a string. The second has the form "_MIPS_ARCH_foo", where foo is the capitalized value of "_MIPS_ARCH". For example, -march=r2000 sets "_MIPS_ARCH" to "r2000" and defines the macro "_MIPS_ARCH_R2000" ๐ง
Note that the "_MIPS_ARCH" macro uses the processor names given above. In other words, it has the full prefix and does not abbreviate 000 as k. In the case of from-abi, the macro names the resolved architecture (either "mips1" or "mips3"). It names the default architecture when no -march option is given ๐
-mtune=archโ optimizes forarch๐ Among other things, this option controls the way instructions are scheduled, and the perceived cost of arithmetic operations. The list ofarchvalues 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 ๐
-mips1โ equivalent to-march=mips1๐ฆ-mips2โ equivalent to-march=mips2๐ซถ-mips3โ equivalent to-march=mips3๐-mips4โ equivalent to-march=mips4๐ง-mips32โ equivalent to-march=mips32๐ธ-mips32r3โ equivalent to-march=mips32r3๐-mips32r5โ equivalent to-march=mips32r5๐ฅ-mips32r6โ equivalent to-march=mips32r6โจ-mips64โ equivalent to-march=mips64โญ-mips64r2โ equivalent to-march=mips64r2๐-mips64r3โ equivalent to-march=mips64r3๐-mips64r5โ equivalent to-march=mips64r5๐-mips64r6โ equivalent to-march=mips64r6๐-mips16/-mno-mips16โ generates (or does 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 ๐ซถ
-mflip-mips16โ generates 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 ๐-minterlink-compressed/-mno-interlink-compressedโ requires (or does 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-mips16/-mno-interlink-mips16โ aliases of-minterlink-compressedand-mno-interlink-compressed. These options predate the microMIPS ASE and are retained for backwards compatibility ๐-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generates 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 <http://gcc.gnu.org/projects/mipso64-abi.html> ๐ฆ
GCC supports a variant of the o32 ABI in which floating-point registers are 64 rather than 32 bits wide. You can select this combination with -mabi=32 -mfp64. This ABI relies on the "mthc1" and "mfhc1" instructions and is therefore only supported for MIPS32R2, MIPS32R3 and MIPS32R5 processors ๐ซถ
The register assignments for arguments and return values stay the same, okay? ๐
But each scalar value now rides in a single 64-bit register instead of a pair of 32-bit ones ๐ฅ. Scalar floating-point values come back in $f0 only, not a $f0/$f1 pair ๐ฆ. The call-saved set doesn't change either, because the even-numbered double-precision registers are still the ones that get saved โจ.
Two extra variants of the o32 ABI exist so you can transition from 32-bit to 64-bit registers ๐. The first is -mfpxx (FPXX), and it's giving flexibility ๐ซถ. FPXX means all code has to run correctly with 32-bit or 64-bit registers. You can interlink it with FP32 or FP64, but never both ๐ซ. The second is -mfp64 -mno-odd-spreg (FP64A) ๐. It's basically FP64, except it bans the odd-numbered single-precision registers. Pair it with the "FRE" mode of FPUs in MIPS32R5 processors and FP32 and FP64A code can interlink and run in the same process without changing FPU modes. That's a whole glow-up, no cap ๐ธ.
-mabicalls,-mno-abicallsโ Generates (or doesn't generate) code that fits SVR4-style dynamic objects ๐.-mabicallsis the default on SVR4-based systems ๐.-mshared,-mno-sharedโ Generates (or doesn't) 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, even without options like -fPIC and -fpic ๐ง. But as an extension, the GNU toolchain lets executables use absolute accesses for locally-binding symbols โจ. It can also use shorter GP initialization sequences and generate direct calls to locally-defined functions ๐ฅ. That's the mode -mno-shared selects ๐.
-mno-shared depends on binutils 2.16 or higher, and the objects it makes can only be linked by the GNU linker ๐. The ABI of the final executable doesn't change, though. 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โ Assumes (or doesn't assume) that the static and dynamic linkers support PLTs and copy relocations ๐. This only affects-mno-shared-mabicalls๐ . For the n64 ABI, this option does nothing without-msym32๐.
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt โจ.
-mxgot,-mno-xgotโ Lifts (or doesn't lift) the usual size limits on the global offset table ๐ฅ.
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 and the linker reports an error like this:
relocation truncated to fit: R_MIPS_GOT16 foobar
If that happens, recompile your code with -mxgot ๐ซถ. It works with very large GOTs, but the code is less efficient, since it takes three instructions to fetch the value of a global symbol ๐ข.
Some linkers can create multiple GOTs. If you have one of those, you usually only need -mxgot when a single object file accesses more than 64k's worth of GOT entries. Very few linkers do ๐ง.
These options do nothing unless GCC is generating position-independent code ๐.
-mgp32โ Assumes general-purpose registers are 32 bits wide ๐.-mgp64โ Assumes general-purpose registers are 64 bits wide โจ.-mfp32โ Assumes floating-point registers are 32 bits wide ๐ธ.-mfp64โ Assumes floating-point registers are 64 bits wide ๐ฆ.-mfpxxโ Doesn't assume any particular width for floating-point registers ๐ซถ.-mhard-floatโ Uses floating-point coprocessor instructions ๐ฅ.-msoft-floatโ Doesn't use floating-point coprocessor instructions. Floating-point math goes through library calls instead ๐ง.-mno-floatโ Same as-msoft-float, but it also swears the program doesn't do any floating-point operations at all ๐ โโ๏ธ. Right now this is only supported by some bare-metal MIPS configurations, which might pick a special set of libraries with zero floating-point support, including things like the floating-point"printf"formats ๐.
Warning, bestie: if code compiled with -mno-float accidentally has floating-point operations in it, it's likely to fail at link time or at run time ๐ญ.
-msingle-floatโ Assumes the floating-point coprocessor only supports single-precision operations ๐.-mdouble-floatโ Assumes the floating-point coprocessor supports double-precision operations. This is the default ๐.-modd-spreg,-mno-odd-spregโ Enables (or disables) the use of odd-numbered single-precision floating-point registers for the o32 ABI ๐ . Odd-numbered registers are on by default for processors known to support them. When you use the o32 FPXX ABI,-mno-odd-spregis set by default ๐ฆ.-mabs=2008,-mabs=legacyโ These control how special not-a-number (NaN) IEEE 754 floating-point data gets treated by the"abs.fmt"and"neg.fmt"machine instructions ๐.
legacy is the default, and also what you get with -mabs=legacy. Here, those instructions count as arithmetic, so they get avoided wherever correct operation matters and the input might be a NaN ๐. A longer sequence that manipulates the sign bit of the floating-point datum by hand gets used instead, unless -ffinite-math-only is also specified โจ.
-mabs=2008 selects the IEEE 754-2008 treatment. Here, those instructions count as non-arithmetic, so they work correctly in every case, especially when the input operand is a NaN ๐. That's why they're always used for the respective operations ๐ฅ.
-mnan=2008,-mnan=legacyโ These control how special not-a-number (NaN) IEEE 754 floating-point data gets encoded ๐ง.
-mnan=legacy picks the legacy encoding. Quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, and signaling NaNs (sNaNs) by that same bit being 1 ๐ธ.
-mnan=2008 picks the IEEE 754-2008 encoding, which flips it. qNaNs have the first bit of their trailing significand field set to 1, and sNaNs have it set to 0 ๐ฆ.
The default is -mnan=legacy, unless GCC was configured with --with-nan=2008 ๐.
-mllsc,-mno-llscโ Uses (or doesn't use)ll,sc, andsyncinstructions to implement atomic memory built-in functions ๐. If you specify neither option, GCC uses the instructions whenever the target architecture supports them ๐ซถ.
-mllsc helps when the runtime environment can emulate those instructions ๐. -mno-llsc can help when you're compiling for nonstandard ISAs ๐ง. You can make either one the default by configuring GCC with --with-llsc or --without-llsc. --with-llsc is the default for some configurations, so check the installation documentation for details ๐.
-mdsp,-mno-dspโ Uses (or doesn't use) revision 1 of the MIPS DSP ASE ๐. This option defines the preprocessor macro"__mips_dsp"and sets"__mips_dsp_rev"to1โจ.-mdspr2,-mno-dspr2โ Uses (or doesn't use) revision 2 of the MIPS DSP ASE ๐ฅ. This option defines the preprocessor macros"__mips_dsp"and"__mips_dspr2", and sets"__mips_dsp_rev"to2๐.-msmartmips,-mno-smartmipsโ Uses (or doesn't use) the MIPS SmartMIPS ASE ๐ .-mpaired-single,-mno-paired-singleโ Uses (or doesn't use) paired-single floating-point instructions ๐ฆ. This option needs hardware floating-point support to be enabled ๐.-mdmx,-mno-mdmxโ Uses (or doesn't use) MIPS Digital Media Extension instructions ๐. This only works when generating 64-bit code, and it also needs hardware floating-point support enabled ๐.-mips3d,-mno-mips3dโ Uses (or doesn't use) the MIPS-3D ASE ๐ง.-mips3dimplies-mpaired-singleโจ.-mmicromips,-mno-micromipsโ Generates (or doesn't generate) microMIPS code ๐ธ.
You can also control microMIPS code generation per function, using the "micromips" and "nomicromips" attributes ๐ซถ.
-mmt,-mno-mtโ Uses (or doesn't use) MT Multithreading instructions ๐.-mmcu,-mno-mcuโ Uses (or doesn't use) the MIPS MCU ASE instructions ๐ .-meva,-mno-evaโ Uses (or doesn't use) the MIPS Enhanced Virtual Addressing instructions ๐.-mvirt,-mno-virtโ Uses (or doesn't use) the MIPS Virtualization (VZ) instructions ๐ฅ.-mxpa,-mno-xpaโ Uses (or doesn't use) the MIPS eXtended Physical Address (XPA) instructions ๐.-mcrc,-mno-crcโ Uses (or doesn't use) the MIPS Cyclic Redundancy Check (CRC) instructions ๐ฆ.-mginv,-mno-ginvโ Uses (or doesn't use) the MIPS Global INValidate (GINV) instructions ๐ซถ.-mloongson-mmi,-mno-loongson-mmiโ Uses (or doesn't use) the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐.-mloongson-ext,-mno-loongson-extโ Uses (or doesn't use) the MIPS Loongson EXTensions (EXT) instructions โจ.-mloongson-ext2,-mno-loongson-ext2โ Uses (or doesn't use) the MIPS Loongson EXTensions r2 (EXT2) instructions ๐ง.-mlong64โ Forces"long"types to be 64 bits wide ๐. Check out-mlong32for an explanation of the default and how the pointer size gets determined ๐.-mlong32โ Forces"long","int", and pointer types to be 32 bits wide ๐ธ.
The default size of "int"s, "long"s, and pointers depends on the ABI. Every supported ABI uses 32-bit "int"s ๐
. The n64 ABI uses 64-bit "long"s, and so does the 64-bit EABI. The others use 32-bit "long"s ๐. Pointers are the same size as "long"s, or the same size as integer registers, whichever is smaller ๐ฅ.
-msym32,-mno-sym32โ Assumes (or doesn't assume) that all symbols have 32-bit values, no matter which ABI you picked ๐ฆ. This is useful together with-mabi=64and-mno-abicalls, because it lets GCC generate shorter and faster references to symbolic addresses ๐โจ.-G numโ okay bestie, this one tells GCC to tuck externally-visible data into a little small data section as long as it's no bigger than num bytes ๐ง That lets GCC generate way more efficient accesses to the data, so peep-mgpoptfor the deets โจ The default-Gvalue depends on the configuration, so it's not one-size-fits-all ๐-mlocal-sdata,-mno-local-sdataโ these extend (or don't extend) the-Gbehavior to local data too, like static variables in C ๐ฆ-mlocal-sdatais the default for all configurations ๐ If the linker starts complaining that your app is using too much small data, try rebuilding the less performance-critical parts with-mno-local-sdata๐ญ You might also wanna build big libraries with-mno-local-sdataso they leave more room for the main program ๐ซถ-mextern-sdata,-mno-extern-sdataโ this is where it gets lowkey intense ๐-mextern-sdatameans GCC assumes (and-mno-extern-sdatameans it doesn'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.
If you compile a module Mod with -mextern-sdata -G num -mgpopt, and Mod references a variable Var that's no bigger than num bytes, you must make sure Var gets placed in a small data section ๐ If Var is defined by another module, you either have to compile that module with a high-enough -G setting, or attach a "section" attribute to Var's definition. If Var is common, you must link the application with a high-enough -G setting.
The easiest way to keep everyone happy is to compile and link every module with the same -G option ๐ But if you're building a library that supports several different small data limits, 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 for cases where the $gp register might not hold the value of "_gp". For example, if the code is part of a library that might be used in a boot monitor, programs that call boot monitor routines pass an unknown value in $gp. (In those situations, the boot monitor itself is usually compiled with -G0.) -mno-gpopt implies -mno-local-sdata and -mno-extern-sdata โจ
-membedded-data,-mno-embedded-dataโ allocates variables to the read-only data section first if possible, then to the small data section if possible, and otherwise to data ๐ The code is slightly slower than the default, but it cuts down on the RAM needed while executing, so some embedded systems might prefer it ๐ง-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ puts uninitialized"const"variables in the read-only data section ๐ This only means something when it's used together with-membedded-data.-mcode-readable=settingโ tells GCC whether it's allowed to generate code that reads from executable sections ๐ฅ There are three possible settings:-mcode-readable=yesโ instructions can freely access executable sections. This is the default setting ๐-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must not do so. This is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It's also useful on processors that can be configured to have a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM ๐ฆ-mcode-readable=noโ instructions must not access executable sections. This can be useful on targets configured to have 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 one's been superseded by-mexplicit-relocs, but it's 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-relocsis 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 it can be overridden at configure time using --with-divide=breaks. Divide-by-zero checks can be completely disabled with -mno-check-zero-division ๐ซถ
-mload-store-pairs,-mno-load-store-pairsโ enable (or disable) an optimization that pairs consecutive load or store instructions to enable load/store bonding ๐ It's on by default, but it only takes effect when the selected architecture is known to support bonding.-mmemcpy,-mno-memcpyโ force (or don't force) the use of"memcpy"for non-trivial block moves ๐ง The default is-mno-memcpy, which lets GCC inline most constant-sized copies โจ-mlong-calls,-mno-long-callsโ disable (or don't disable) use of the"jal"instruction ๐ Calling functions with"jal"is more efficient, but it requires the caller and callee to be in the same 256 megabyte segment ๐ธ
This option has no effect on abicalls code. The default is -mno-long-calls ๐
-mmad,-mno-madโ enable (or disable) use of the"mad","madu"and"mul"instructions, as provided by the R4650 ISA ๐ฆ-mimadd,-mno-imaddโ enable (or disable) use of the"madd"and"msub"integer instructions. The default is-mimaddon architectures that support"madd"and"msub", except for the 74k architecture, where it was found to generate slower code ๐-mfused-madd,-mno-fused-maddโ 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. This may be undesirable in some circumstances. ๐
On other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions โจ
-nocppโ tells the MIPS assembler to not run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐-mfix-24k,-mno-fix-24kโ works around the 24K E48 (lost data on stores during refill) errata ๐ ๏ธ The workarounds are implemented by the assembler rather than by GCC.
-mfix-r4000,-mno-fix-r4000โ works around certain R4000 CPU errata:- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
- A double-word or a variable shift may give an incorrect result if executed while an integer multiplication is in progress.
- An integer division may give an incorrect result if started in a delay slot of a taken branch or a jump.
-mfix-r4400,-mno-fix-r4400โ works around certain R4400 CPU errata:- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
-mfix-r10000,-mno-fix-r10000โ works around certain R10000 errata:"ll"/"sc"sequences may not behave atomically on revisions prior to 3.0. They may deadlock on revisions 2.6 and earlier.
This option can only be used if the target architecture supports branch-likely instructions. -mfix-r10000 is the default when -march=r10000 is used; -mno-fix-r10000 is the default otherwise.
-mfix-r5900,-mno-fix-r5900โ do not attempt to schedule the preceding instruction into the delay slot of a branch instruction placed at the end of a short loop of six instructions or fewer, and always schedule a"nop"instruction there instead ๐ The short loop bug can, under certain conditions, cause loops to execute only once or twice, due to a hardware bug in the R5900 chip ๐ต The workaround is implemented by the assembler rather than by GCC.-mfix-rm7000,-mno-fix-rm7000โ works around the RM7000"dmult"/"dmultu"errata. The workarounds are implemented by the assembler rather than by GCC.-mfix-vr4120,-mno-fix-vr4120โ works around certain VR4120 errata:"dmultu"does not always produce the correct result."div"and"ddiv"do not always produce the correct result if one of the operands is negative.
The workarounds for the division errata rely on special functions in libgcc.a. At present, these functions are only provided by the "mips64vr*-elf" configurations. Other VR4120 errata require a NOP to be inserted between certain pairs of instructions. These errata are handled by the assembler, not by GCC itself.
-mfix-vr4130โ works around the VR4130"mflo"/"mfhi"errata. The workarounds are implemented by the assembler rather than by GCC, although GCC avoids using"mflo"and"mfhi"if the VR4130"macc","macchi","dmacc"and"dmacchi"instructions are available instead.-mfix-sb1,-mno-fix-sb1โ works around certain SB-1 CPU core errata. (This flag currently works around the SB-1 revision 2"F1"and"F2"floating-point errata.) ๐-mr10k-cache-barrier=settingโ specifies whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors ๐ฅ
Okay so the R10K is lowkey a chaotic processor ๐ It tries to guess which way a conditional branch will go and starts running instructions down the "taken" path before it knows. If the guess was wrong, it throws those instructions away, but even the aborted ones can leave marks behind ๐
This mostly hurts kernel stores and, depending on the system, kernel loads ๐ญ Picture a speculative store pulling its target memory into cache and marking that line as dirty, even though the store got cancelled. If a DMA operation writes to that same memory before the dirty line gets flushed, the cached data overwrites the DMA data. Yikes. For the full tea, including other problems, check the R10K processor manual ๐โจ
One workaround is to drop cache barrier instructions in front of every memory access that might run speculatively and might have side effects even when aborted. -mr10k-cache-barrier=setting controls how GCC does this. It assumes that aborted accesses to any byte in these regions have no side effects:
- the memory taken up by the current function's stack frame ๐ฅ
- the memory taken up by an incoming stack argument ๐ฆ
- the memory taken up by an object with a link-time-constant address ๐
It is the kernel's job to make sure speculative accesses to these regions are actually safe ๐ซถ
If your input program has a function declaration like this:
void foo (void);
then the implementation of foo has to let j foo and jal foo run speculatively ๐ GCC follows this rule for functions it compiles itself. It expects non-GCC functions, like hand-written assembly, to do the same thing ๐
The option comes in three flavours:
-mr10k-cache-barrier=load-storeโ Inserts a cache barrier before a load or store that might run speculatively and might have side effects even if it gets aborted โจ-mr10k-cache-barrier=storeโ Inserts a cache barrier only before a store that might run speculatively and might have side effects even if it gets aborted ๐-mr10k-cache-barrier=noneโ Turns off cache barrier insertion entirely. This is the default setting ๐ธ-mflush-func=func,-mno-flush-funcโ Picks the function to call for flushing the I and D caches, or tells GCC 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 number3(to flush both caches) ๐ฅ The default depends on the target GCC was configured for, but it's commonly either_flush_funcor__cpu_flush๐ฆmbranch-cost=numโ Sets the cost of branches to roughlynum"simple" instructions ๐ This is only a heuristic, so don't expect it to give the same results across releases ๐ A cost of zero just picks the default, which is based on the-mtunesetting ๐-mbranch-likely,-mno-branch-likelyโ Turns Branch Likely instructions on or off, no matter what the selected architecture defaults to ๐ By default they may get generated if the selected architecture supports them. The exception is the MIPS32 and MIPS64 architectures, plus processors that implement them. For those, Branch Likely instructions are not generated by default, because MIPS32 and MIPS64 specifically deprecate them ๐ซ-mcompact-branches=neverโ Makes sure compact branch instructions never get generated ๐ โโ๏ธ-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 picked instead, as long as one is available ๐ง This is the default โจ-mcompact-branches=alwaysโ Makes sure a compact branch instruction gets generated whenever one is available. If none is available, a delay slot form of the branch gets used instead ๐
These options control which form of branches gets generated. The default is -mcompact-branches=optimal. Also, the always option is only supported from MIPS Release 6 onwards ๐
-mfp-exceptions,-mno-fp-exceptionsโ Says whether FP exceptions are enabled. This affects how FP instructions get scheduled on some processors ๐ฅ FP exceptions are enabled by default ๐
For instance, 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 option is enabled, GCC aligns pairs of instructions it thinks should run in parallel ๐ฆ
This option only does something when you're optimizing for the VR4130 โจ It usually makes code faster, but the tradeoff is that the code gets bigger ๐ It's enabled by default at optimization level -O3 ๐
-msynci,-mno-synciโ Enables (or disables) generatingsynciinstructions on architectures that support them ๐ธ Thesynciinstructions, if enabled, 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 code for single processor systems, it's generally safe to use synci. But on many multi-core (SMP) systems, it doesn't invalidate the instruction caches on all cores and may lead to undefined behavior ๐ Be careful, bestie!
-mrelax-pic-calls,-mno-relax-pic-callsโ Tries to turn PIC calls that are normally dispatched via register$25into direct calls ๐ฆ This only works if the linker can resolve the destination at link time and 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 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 is 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 ๐ฅ When you use the o32 ABI, calling functions allocate 16 bytes on the stack for the called function to write out register arguments. When this optimization is enabled, it suppresses that frame header allocation if it can be determined that the header is unused ๐ง
This optimization is off by default at all optimization levels ๐ญ
-mlxc1-sxc1,-mno-lxc1-sxc1โ When applicable, enables (or disables) generatinglwxc1,swxc1,ldxc1, andsdxc1instructions ๐ Enabled by default โจ-mmadd4,-mno-madd4โ When applicable, enables (or disables) generating 4-operandmadd.s,madd.d, and related instructions ๐ Enabled by default ๐
๐ MMIX Options ๐
These options are defined for the MMIX ๐ง
-mlibfuncs,-mno-libfuncsโ Specifies that intrinsic library functions are being compiled, passing all values in registers no matter the size ๐-mepsilon,-mno-epsilonโ Generates floating-point comparison instructions that compare with respect to therEepsilon register ๐ข-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code that passes function parameters and return values 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, uses (or doesn't use) zero-extending load instructions by default, instead of sign-extending ones ๐ฆ-mknuthdiv,-mno-knuthdivโ-mknuthdivmakes the result of a division yielding 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โ Generates (or doesn't generate) code that uses base addresses ๐ Using a base address automatically generates a request, handled by the assembler and the linker, for a constant to be set up in a global register. That register is used for one or more base address requests within the range 0 to 255 from the value held in the register. This generally leads to short and fast code, but the number of different data items that can be addressed is limited. So a program that uses lots of static data may require-mno-base-addresses๐ฆ-msingle-exit,-mno-single-exitโ Forces (or doesn't force) generated code to have a single exit point in each function ๐ช
๐ MN10300 Options ๐
These -m options are defined for Matsushita MN10300 architectures ๐
-mmult-bugโ Generates code to avoid bugs in the multiply instructions for the MN10300 processors. This is the default ๐ก๏ธ-mno-mult-bugโ okay so this one tells GCC to not generate code that works around bugs in the multiply instructions on MN10300 processors ๐-mam33โ generate code using AM33-specific features โจ-mno-am33โ the opposite: no AM33-specific features. This is the default ๐ธ-mam33-2โ generate code using features specific to the AM33/2.0 processor ๐ฆ-mam34โ generate code using AM34-specific features ๐-mtune=cpu-typeโ bestie, this tells the scheduler which CPU's timing to follow when it lines up instructions. It does not change the target processor, so it's giving scheduling tips, not a glow-up. The CPU type has to bemn10300,am33,am33-2oram34๐-mreturn-pointer-on-d0โ when a function returns a pointer, it gets returned in both"a0"and"d0". Otherwise the pointer only lives in"a0", and calling those functions without a prototype throws errors ๐. This one is on by default, but you can switch 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. Choose wisely, bestie ๐ญ
-mliwโ lets the compiler generate Long Instruction Word instructions when the target is AM33 or later. This is the default, and it defines the preprocessor macro"__LIW__"๐-mno-liwโ no LIW instructions allowed. This one defines the preprocessor macro"__NO_LIW__"๐ซถ-msetlbโ lets the compiler generateSETLBandLccinstructions when the target is AM33 or later. Also the default, and it defines"__SETLB__"๐ฅ-mno-setlbโ noSETLBorLccinstructions. Defines"__NO_SETLB__"๐ฅ
โจ Moxie Options โจ
-mebโ big-endian code. This is the default formoxie-*-*configurations ๐-melโ 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, so they're giving MSP430 realness ๐
-masm-hexโ forces assembly output to always use hex constants. Normally they show up as signed decimals, but this one is there for testsuite and/or aesthetic purposes ๐-mmcu=โ picks the MCU you're targeting. GCC makes a C preprocessor symbol from the MCU name, in upper case, wrapped in__on both sides. Themsp430.hheader then uses that to pick an MCU-specific supplementary header file โจ- It also sets the ISA. If the MCU is one that only supports the 430 ISA, that's what gets selected. Otherwise the 430X ISA gets the spotlight. The generic
msp430name selects the 430 ISA, and the genericmsp430xname selects the 430X ISA ๐ - An MCU-specific linker script gets added to the linker command line. The script is named after the MCU with
.ldtacked on, so-mmcu=xxxdefines the C preprocessor symbol"__XXX__"and makes the linker search for a script calledxxx.ld๐ - The ISA and hardware multiply support for each MCU is hard-coded into GCC. But an external
devices.csvfile can extend device support past the hard-coded ones ๐ฆ - GCC searches for
devices.csvin this order of precedence, where the first method beats the second and the second beats the third:- Include paths from
-Iand-L:devices.csvgets searched in every directory on the include paths and linker library search paths ๐ - The
MSP430_GCC_INCLUDE_DIRenvironment variable: set it to the full path of the directory holdingdevices.csv, and GCC searches there. If it finds the file, that directory also gets registered as an include path and a linker library path. That means headers and linker scripts in there work without manually specifying-Iand-Lon the command line ๐ซถ msp430-elf{,bare}/include/devices: GCC checks this directory under the toolchain root. It doesn't exist in a default installation, but if you made it and copieddevices.csvin there, the MCU data gets read. Same deal as above, so this directory also gets registered as an include path and a linker library path ๐ธ
- Include paths from
- If none of those search methods find
devices.csv, the hard-coded MCU data is used instead ๐
- It also sets the ISA. If the MCU is one that only supports the 430 ISA, that's what gets selected. Otherwise the 430X ISA gets the spotlight. The generic
-mwarn-mcu,-mno-warn-mcuโ these 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. They also toggle warnings about unrecognized MCU names. On by default ๐-mcpu=โ specifies the ISA to use. Accepted values aremsp430,msp430xandmsp430xv2.
This option is deprecated! Use -mmcu= to select the ISA instead ๐ญ
-msimโ links to the simulator runtime libraries and linker script. It overrides any scripts that-mmcu=would have selected ๐ฅ-mlargeโ uses large-model addressing, with 20-bit pointers and a 20-bit"size_t"๐-msmallโ uses small-model addressing, with 16-bit pointers and a 16-bit"size_t"๐-mrelaxโ passed to the assembler and linker. It lets the linker do certain optimizations that can only happen at the final link โจmhwmult=โ describes the type of hardware multiply the target supports. Accepted values are:nonefor no hardware multiply16bitfor the original 16-bit-only multiply on early MCUs32bitfor the 16/32-bit multiply on later MCUsf5seriesfor the 16/32-bit multiply on F5-series MCUsauto, which tells GCC to figure out the hardware multiply support from the MCU name given by-mmcu. If there's no-mmcuoption, or the MCU name isn't recognized, no hardware multiply support is assumed."auto"is the default setting ๐ง
Hardware multiplies usually get handled by calling a library routine, which saves space in the generated code. When you compile at -O3 or higher, though, the hardware multiplier is invoked inline. That makes the code bigger but faster ๐๏ธ
The hardware multiply routines disable 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. It's meant 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 are not reentrant, so be careful with them in multi-threaded applications ๐
Stream support has been removed, so the string to print always goes to stdout via the "write" syscall. The string isn't buffered before it's sent to write. This option requires Newlib Nano IO, so GCC must be configured with --enable-newlib-nano-formatted-io ๐ธ
-mmax-inline-shift=โ takes an integer from 0 to 64 inclusive, and sets the maximum number of inline shift instructions that get emitted to do a shift by a constant amount. Once that limit would be exceeded, an mspabi helper function is used instead. The default is 4 โจ
This only matters when a shift by multiple positions can't be finished with a single instruction, like all shifts >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 the result is used instead ๐งฎ
-mcode-region=,-mdata-region=โ these tell the compiler where to place functions and data that don't have one of the"lower","upper","either"or"section"attributes. Possible values are"lower","upper","either"or"any". The first three behave like the matching attribute."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 fixes for the named silicon errata ๐ง-msilicon-errata-warn=โ passes a request to the assembler to enable warning messages when a silicon erratum might need to be applied โ ๏ธ-mwarn-devices-csv,-mno-warn-devices-csvโ warn ifdevices.csvisn't found, or if there are problems parsing it. Default is on ๐
๐ NDS32 Options ๐
These options are defined for NDS32 implementations, so they're giving NDS32 vibes ๐
-mbig-endianโ generate code in big-endian mode ๐-mlittle-endianโ generate code in little-endian mode ๐ธ-mreduced-regsโ use reduced-set registers for register allocation ๐ฆ-mfull-regsโ use full-set registers for register allocation ๐-mcmovโ generate conditional move instructions โจ-mno-cmovโ 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 ๐ฅ Nope, no performance extension 2 instructions for this build, bestie. ๐ โโ๏ธ
-mext-stringโ โจ Turns on the string extension instructions.-mno-ext-stringโ ๐ซ Keeps the string extension instructions out.-mv3pushโ ๐ Generates the v3push25/pop25instructions.-mno-v3pushโ ๐ Skips the v3push25/pop25instructions.-m16-bitโ ๐ฆ Generates 16-bit instructions.-mno-16-bitโ ๐ค No 16-bit instructions for you.-misr-vector-size=numโ ๐ Sets how big each interrupt vector is. It has to be4or16, no other vibes allowed.-mcache-block-size=numโ ๐ง Sets the size of each cache block. It must be a power of 2 between4and512, so pick wisely.-march=archโ ๐บ๏ธ Names the target architecture.-mcmodel=code-modelโ ๐ง Picks the code model. You choose one of these:smallโ โจ All the data and read-only data segments have to live within 512KB of addressing space. The text segment has to stay within 16MB of addressing space.mediumโ ๐ธ The data segment has to stay within 512KB, but the read-only data segment can stretch across 4GB of addressing space. The text segment should still stay within 16MB of addressing space.largeโ ๐ All the text and data segments can spread across 4GB of addressing space. Main character energy.
-mctor-dtorโ ๐ง Enables the constructor/destructor feature.-mrelaxโ ๐ช Tells the linker to relax instructions.
โจ Nios II Options โจ
These are the options for the Altera Nios II processor, so if you're building for Nios II, this part is literally for you. ๐
-G numโ ๐ Puts global and static objects that arenumbytes or smaller into the small data or BSS sections, instead of the normal data or BSS sections. The default value ofnumis8.-mgpopt=option,-mgpopt,-mno-gpoptโ ๐ Generates (or doesn't generate) GP-relative accesses. These option names are recognized:noneโ ๐ โโ๏ธ Doesn't generate GP-relative accesses at all.localโ ๐ซถ Generates GP-relative accesses for small data objects that aren't external, weak, or uninitialized common symbols. It also uses GP-relative addressing for objects you've explicitly placed in a small data section with asectionattribute.globalโ ๐ฅ Same aslocal, but it also generates GP-relative accesses for small data objects that are external, weak, or common. If you use this one, every part of your program (libraries included) has to be compiled with the same-Gsetting, no exceptions.dataโ ๐ท Generates GP-relative accesses for all data objects in the program. If you go with this, the entire data and BSS segments of your program have to fit in 64K of memory, and you need an appropriate linker script to allocate them within the addressable range of the global pointer.allโ ๐ Generates GP-relative addresses for function pointers as well as data pointers. If you use this option, the entire text, data, and BSS segments of your program have to fit in 64K of memory, and you need 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. Heads up though: the Nios II ABI does not allow GP-relative accesses from shared libraries. ๐
You might need to specify -mno-gpopt explicitly when building programs with lots 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โ ๐งญ Adds extra section names that can be accessed via GP-relative addressing. It's most useful alongsidesectionattributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression.
This option doesn't change how -G behaves. The sections you list here come in addition to the standard .sdata and .sbss small-data sections that -mgpopt already recognizes.
-mr0rel-sec=regexpโ ๐ฏ Names sections that can be reached via a 16-bit offset fromr0, meaning the low 32K or high 32K of the 32-bit address space. It's most useful alongsidesectionattributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression.
Unlike GP-relative addressing for small data, zero-based addressing is never generated by default. Also, there are no conventional section names in standard linker scripts for the low or high areas of memory, so you're on your own there. ๐ซ
-mel,-mebโ ๐ Generates little-endian (default) or big-endian (experimental) code, respectively.-march=archโ ๐งฌ Specifies the name of the target Nios II architecture. GCC uses this name to figure out what kind of instructions it can emit when generating assembly code. The permissible names arer1andr2.
The preprocessor macro __nios2_arch__ is available to your programs, with a value of 1 or 2, which tells you the targeted ISA level. โจ
-mbypass-cache,-mno-bypass-cacheโ ๐โโ๏ธ Forces all load and store instructions to always bypass the cache by using I/O variants of the instructions. The default is not to bypass the cache.-mno-cache-volatile,-mcache-volatileโ ๐ Volatile memory access bypasses the cache using the I/O variants of the load and store instructions. The default is not to bypass the cache.-mno-fast-sw-div,-mfast-sw-divโ ๐ข Doesn't 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โ โก Enables or disables the compiler emitting themul,mulx, anddivfamily of instructions. The default is to emitmuland to not emitdivandmulx.-mbmx,-mno-bmx,-mcdx,-mno-cdxโ ๐งฉ Enables or disables generation of Nios II R2 BMX (bit manipulation) and CDX (code density) instructions. Turning these on also requires-march=r2. Since these are 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.
Here are the supported values of insn. Unless noted otherwise, floating-point operations are expected to use normal IEEE 754 semantics and 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_lroundffunction when-fno-math-errnois used.floatis,floatus,floatid,floatudโ ๐ Conversion from signed or unsigned integer types to floating-point types.
Also, all of the following transfer instructions for the internal registers X and Y must be provided in order to 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 of a unary operation) is given to the custom arithmetic instruction with the least significant half in source register src1 and the most significant half in src2. A custom instruction that returns a double-precision result returns the most significant 32 bits in the destination register and the other half in 32-bit register Y. GCC automatically generates the necessary code sequences to write register X and/or read register Y when double-precision floating-point instructions are used. ๐ค
fwrxโ โ๏ธ Writessrc1into the least significant half ofXandsrc2into the most significant half ofX.fwryโ โ๏ธ Writessrc1intoY.frdxhi,frdxloโ ๐ Reads the most or least (respectively) significant half ofXand stores it indest.frdyโ ๐ Reads the value ofYand stores it intodest.
Note that you can get more local control over generation of Nios II custom instructions by using thetarget("custom-insn=N")andtarget("no-custom-insn")function attributes or pragmas. ๐
-mcustom-fpu-cfg=name Okay so this option is bestie's go-to for picking a whole pre-made bundle of custom instruction encodings, named and ready to go ๐ โจ (see -mcustom-insn above for the deets). Here's the current lineup:
Okay the first one, -mcustom-fpu-cfg=60-1, is basically the same as: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -fsingle-precision-constant ๐
And -mcustom-fpu-cfg=60-2 is giving: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant ๐ฆ
Then there's -mcustom-fpu-cfg=72-3, which 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 ๐
And last but not least, -mcustom-fpu-cfg=fph2, which 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 ๐
ngl, the explicit-mcustom-insn=options always win over-mcustom-fpu-cfg=, no matter what order you type them on the command line. Main character energy for your own picks ๐
Lowkey wild: fph2 is short for Nios II Floating Point Hardware 2 Component ๐ง. Also, the custom instructions -mcustom-fmins=233 and -mcustom-fmaxs=234 only get generated if -ffinite-math-only is specified ๐. The custom instruction -mcustom-round=248 only shows up if -fno-math-errno is specified ๐. And unlike the other configs, -fsingle-precision-constant is not set for fph2 ๐ซถ.
Heads up: you can get more local control over which FPU config is used by using the target("custom-fpu-cfg=name") function attribute or pragma ๐.
These additional -m options are available for the Altera Nios II ELF (bare-metal) target ๐ธ:
-mhalโ Link with the HAL BSP. This skips linking the GCC-provided C runtime startup and termination code, and is usually paired with-msys-crt0=to point at the alternate startup code from the HAL BSP ๐ฆ-msmallcโ Link with a limited version of the C library,-lsmallc, instead of Newlib ๐-msys-crt0=startfileโ startfile is the file name of the startup file (crt0) to use when linking. Only useful alongside-mhal๐-msys-lib=systemlibโ systemlib is the library name for the low-level system calls the C library needs, like "read" and "write". Usually used to link with a library from a HAL BSP โจ
โจ Nvidia PTX Options โจ
These options are defined for Nvidia PTX ๐:
-m64โ Ignored, but kept around for backward compatibility. Only the 64-bit ABI is supported ๐ฅ-misa=ISA-stringโ Generate 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๐-mmainkernelโ Link in code for a__mainkernel. This is for stand-alone execution instead of offloading ๐ง-moptimizeโ Apply partitioned execution optimizations. This is the default whenever any level of optimization is selected ๐-msoft-stackโ Generate 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 for underlying storage, makes it possible to access automatic variables from other threads, or with atomic instructions. This code generation variant is used for OpenMP offloading, but the option is exposed on its own for the purpose of testing the compiler. To generate code suitable for linking into programs using OpenMP offloading, use option-mgompinstead ๐ซถ-muniform-simtโ Switch to a code generation variant that lets all threads in each warp execute, while keeping memory state and side effects as if only one thread in each warp was active outside of OpenMP SIMD regions. All atomic operations and calls to runtime (malloc, free, vprintf) are conditionally executed (iff current lane index equals the master lane index), and the register being assigned is copied via a shuffle instruction from the master lane. Outside of SIMD regions lane 0 is the master; inside, each thread sees itself as the master. Shared memory arrayint __nvptx_uni[]stores all-zeros or all-ones bitmasks for each warp, indicating current mode (0 outside of SIMD regions). Each thread can bitwise-and the bitmask at positiontid.ywith current lane index to compute the master lane index ๐ฎ-mgompโ Generate code for use in OpenMP offloading. This enables-msoft-stackand-muniform-simtand selects the corresponding multilib variant ๐
โจ OpenRISC Options โจ
These options are defined for OpenRISC ๐ธ:
-mboard=nameโ Configure 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. This used to select linker and preprocessor options for use with newlib ๐-msoft-div,-mhard-divโ Pick software or hardware divide (l.div,l.divu) instructions. The default is hardware divide ๐-msoft-mul,-mhard-mulโ Pick software or hardware multiply (l.mul,l.muli) instructions. The default is hardware multiply โจ-msoft-float,-mhard-floatโ Pick 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โ Enable generation of conditional move (l.cmov) instructions. By default the equivalent gets generated using set and branch ๐ง-mrorโ Enable generation of rotate right (l.ror) instructions. By default, functions from libgcc are used for rotate right operations ๐-mroriโ Enable generation of rotate right with immediate (l.rori) instructions. By default, functions from libgcc are used for rotate right with immediate operations ๐ซถ-msextโ Enable generation of sign extension (l.ext*) instructions. By default, memory loads are used to do sign extension ๐ฎ-msfimmโ Enable generation of compare and set flag with immediate (l.sf*i) instructions. By default, extra instructions get generated to store the immediate to a register first ๐-mshftimmโ Enable generation of shift with immediate (l.srai,l.srli,l.slli) instructions. By default, extra instructions get generated to store the immediate to a register first ๐ธ
โจ PDP-11 Options โจ
These options are defined for the PDP-11 ๐ฆ:
-mfpuโ Use hardware FPP floating point. This is the default. (FIS floating point on the PDP-11/40 is not supported.) Implies-m45๐-msoft-floatโ Don't use hardware floating point ๐-mac0โ Return floating-point results in ac0 (fr0 in Unix assembler syntax) โจ-mno-ac0โ Return floating-point results in memory. This is the default ๐-m40โ Generate code for a PDP-11/40. Implies-msoft-float -mno-split๐ฅ-m45โ Generate code for a PDP-11/45. This is the default ๐-m10โ Generate code for a PDP-11/10. Implies-msoft-float -mno-split๐ง-mint16,-mno-int32โ Use 16-bit "int". This is the default ๐-mint32,-mno-int16โ Use 32-bit "int" ๐ซถ-msplitโ Target has split instruction and data space. Implies-m45๐ฎ-munix-asmโ Use Unix assembler syntax ๐-mdec-asmโ Use DEC assembler syntax ๐ธ-mgnu-asmโ Use GNU assembler syntax. This is the default ๐ฆ-mlraโ Use 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โ Set the instruction set, register set, and instruction scheduling parameters for array element type ae_type. Supported values for ae_type areANY,MUL, andMACโจ-mae=ANYselects a completely generic AE type. Code generated with this option runs on any of the other AE types. The code is not as efficient as it would be if compiled for a specific AE type, and some types of operation (e.g., multiplication) do not work properly on all types of AE ๐-mae=MULselects a MUL AE type. This is the most useful AE type for compiled code, and is the default ๐ฅ-mae=MACselects a DSP-style MAC AE. Code compiled with this option may suffer from poor performance of byte (char) manipulation, since the DSP AE does not provide hardware support for byte load/stores ๐
-msymbol-as-addressโ Lets the compiler directly use a symbol name as an address in a load/store instruction, without first loading it into a register. Usually this option makes bigger programs that run faster than when it isn't used. However, results vary from program to program, so it's left as a user option rather than being permanently enabled ๐ง-mno-inefficient-warningsโ Disables warnings about the generation of inefficient code. These warnings can be generated, for example, when compiling code that performs byte-level memory operations on the MAC AE type. The MAC AE has no hardware support for byte-level memory operations, so all byte load/stores must be synthesized from word load/store operations. This is inefficient, and a warning is generated to indicate that you should rewrite the code to avoid byte operations, or to target an AE type that has the necessary hardware support. This option disables these warnings ๐
โจ PowerPC Options โจ
These are listed under
๐ PRU Options ๐
okay bestie, these flags are only for the PRU target ๐ฆ so only reach for them if you're building for PRU โจ
-minrtโ links with a minimum runtime ๐ง with no support for static initializers and constructors. This can seriously shrink your final ELF binary ๐
โ ๏ธ Warning: the compiler could still generate code with static initializers and constructors. It's on you to make sure your source program doesn't use those features ๐
-mmcu=mcuโ picks the PRU MCU variant you want ๐ For the exact list of supported MCUs, check Newlib ๐-mno-relaxโ GCC passes--no-relaxto the linker instead of--relax๐-mloopโ lets GCC use the LOOP instruction, or doesn't, depending on whether you turn it on or off ๐-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're different:
๐ธ Function Pointer Size
TI ABI says function (code) pointers are 16-bit, but GNU only supports 32-bit data and code pointers ๐
๐ฆ Optional Return Value Pointer
Function return values bigger than 64 bits get passed through a hidden pointer as the function's first argument. TI ABI says that pointer is allowed to be NULL if the caller doesn't care about the returned value. GNU always passes and expects a valid return value pointer โจ
The current -mabi=ti implementation just throws a compile error whenever any of the above code constructs shows up ๐ญ Because of that, the standard C library can't be built, so it gets left out when you link with -mabi=ti.
Relaxation is a GNU feature, so for safety reasons it's turned off when you use -mabi=ti ๐ก๏ธ The TI toolchain doesn't emit relocations for QBBx instructions, which means the GNU linker can't adjust them when it shortens adjacent LDI32 pseudo instructions. Not it ๐
โโ๏ธ
๐ง RISC-V Options ๐ง
these flags are defined for RISC-V targets ๐ฟ
-mbranch-cost=nโ sets the cost of branches to roughlyninstructions ๐-mplt,-mno-pltโ when generating PIC code, these decide whether PLTs are allowed or not ๐ฆ They get ignored for non-PIC. The default is-mplt.-mabi=ABI-stringโ sets the integer and floating-point calling convention ๐ An ABI string has two parts: the size of integer types, and the registers used for floating-point types. For example,-march=rv64ifd -mabi=lp64dmeanslongand pointers are 64-bit (sointis implicitly 32-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 that uses 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 is system dependent, so if you want a specific calling convention, please specify one explicitly ๐ซถ The valid calling conventions are: ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d. Some combos are just impossible on certain ISAs ๐ For example, -march=rv32if -mabi=ilp32d is invalid, because the 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 proceed with caution ๐งช
-mfdiv,-mno-fdivโ turns hardware floating-point divide and square root instructions on or off ๐งฎ This needs the F or D extensions for floating-point registers. By default they get used if the architecture you picked has those instructions โจ-mdiv,-mno-divโ turns hardware instructions for integer division on or off ๐ข This needs the M extension. Same deal: the default is to use them if your specified architecture has them ๐-march=ISA-stringโ generates code for the given RISC-V ISA, likerv64im๐ ISA strings must be lower-case! Examples includerv64i,rv32g,rv32e, andrv32imaf๐
When -march= isn't specified, it uses the setting from -mcpu. If both -march and -mcpu= are left out, the default is system dependent, so if you want specific architecture extensions, specify them yourself ๐
-mcpu=processor-stringโ uses the architecture of, and optimizes the output for, the given processor, picked by its particular CPU name ๐ง The permissible values are:sifive-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, picked by microarchitecture or particular CPU name โญ The permissible values are:rocket,sifive-3-series,sifive-5-series,sifive-7-series,size, and all valid options for-mcpu=.
When -mtune= isn't specified, it uses the setting from -mcpu. If both are unspecified, the default is rocket ๐
The size choice isn't really meant for end-users ๐ It's used when -Os is specified. It overrides the instruction cost info provided by -mtune=, but it does not override the pipeline info. This helps reduce code size while still giving good performance ๐ซง
-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐งฑ If you don't specify-mpreferred-stack-boundary, the default is 4 (16 bytes, or 128 bits) ๐ธ
โ ๏ธ Warning: if you use this switch, you must build all modules with the same value, including any libraries. That covers the system libraries and startup modules too ๐ญ
-msmall-data-limit=nโ puts global and static data smaller thannbytes into a special section (on some targets) ๐ฆ-msave-restore,-mno-save-restoreโ decides whether you use smaller but slower prologue and epilogue code that calls library functions ๐ข The default is to use fast inline prologues and epilogues โก-mshorten-memrefs,-mno-shorten-memrefsโ decides whether GCC tries to use more compressed load/store instructions ๐๏ธ It does this 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 no unaligned memory accesses, and-mno-strict-alignmeans GCC is allowed to 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 have to live inside 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 have to be within any single 2 GiB address range. Programs can be statically or dynamically linked ๐-mexplicit-relocs,-mno-exlicit-relocsโ decides whether you 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โ controls how GCC aligns variables and constants of array, structure, or union types ๐ The supported values fortypearexlen, which uses the x register width as the alignment value, andnatural, which uses natural alignment.xlenis the default ๐ธ-mbig-endianโ generates big-endian code ๐ซถ This is the default when GCC is configured for ariscv64be-*-*orriscv32be-*-*target ๐-mlittle-endianโ generates little-endian code ๐ This is the default when GCC is configured for ariscv64-*-*orriscv32-*-*target, but not ariscv64be-*-*orriscv32be-*-*target ๐-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard๐ก๏ธ The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block ๐งต
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to decide which register is the base register for reading the canary, and what offset from that base register it lives at ๐ฏ There's no default register or offset here, because this is entirely for use within the Linux kernel ๐ง
๐ RL78 Options ๐
-msimโ links in additional target libraries so your code can run inside a simulator ๐ฅ๏ธ-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ picks the type of hardware multiplication and division support to use ๐งฎ The simplest one is"none", which uses software for both multiplication and division. That'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 value"rl78"is an alias for"g14", and the value"mg10"is an alias for"none"๐ซง
A C preprocessor macro also gets defined based on the setting of this option ๐งฉ The possible values are: "__RL78_MUL_NONE__", "__RL78_MUL_G13__", or "__RL78_MUL_G14__" โจ
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ picks which RL78 core you're targeting ๐ฏ The default is the G14 core, also known as an S3 core or just RL78 ๐ The G13 (or S2) core doesn't have multiply or divide instructions. Instead it uses a hardware peripheral for those operations ๐ง The G10 (or S1) core doesn't have register banks, so it uses a different calling convention ๐ฅน
okay so the RL78 vibes continue ๐ Setting -mcpu also picks your hardware multiply support, 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 straight up turns off hardware multiplication altogether ๐.
Ngl this part is lowkey important ๐. The RL78/G14 core is the default target, BUT passing -mcpu=g14 or -mcpu=rl78 on the command line actually changes how your toolchain behaves, because it turns on G14 hardware multiply support โจ. If you don't pass either one, software multiplication routines get used even though your code targets the RL78 core ๐. That's just for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ฆ.
There's also a C preprocessor macro that gets defined based on this setting ๐. The possible values are "__RL78_G10__", "__RL78_G13__" or "__RL78_G14__".
-mg10,-mg13,-mg14,-mrl78โ ๐ง these are just aliases for the matching-mcpu=option. They're only around for backwards compatibility.-mallregsโ lets the compiler use all the available registers ๐ . By defaultr24..r31are reserved for interrupt handlers, but with this on, they can be used in ordinary functions too.-m64bit-doubles,-m32bit-doublesโ makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) ๐. The default is-m32bit-doubles.-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ tells interrupt handler functions to preserve the MDUC registers ๐ซถ. This only matters if normal code might touch the MDUC registers, like when it does multiplication and division. By default the MDUC registers get ignored, because that makes the interrupt handlers faster โญ. The target option-mg13needs to be passed for this to work, since this feature is only available on the G13 target (S2 core). The MDUC registers only get saved if the interrupt handler does a multiplication or division, or calls another function.
โจ IBM RS/6000 and PowerPC Options โจ
These -m options are defined for the IBM RS/6000 and PowerPC ๐ฆ. You use them to specify which instructions are available on the processor you're using ๐. The default value of these options is determined when GCC is configured. Specifying -mcpu=cpu_type overrides these, and we really recommend using -mcpu=cpu_type instead of the options below ๐ซถ.
-mpowerpc-gpopt,-mno-powerpc-gpoptโ ๐ธ-mpowerpc-gpoptlets GCC use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root.-mpowerpc-gfxopt,-mno-powerpc-gfxoptโ ๐ธ-mpowerpc-gfxoptlets GCC use the optional PowerPC architecture instructions in the Graphics group, including floating-point select.-mpowerpc64,-mno-powerpc64โ ๐ฅ-mpowerpc64lets GCC generate the extra 64-bit instructions from the full PowerPC64 architecture, and treat GPRs as 64-bit doubleword quantities. GCC defaults to-mno-powerpc64.-mmfcrf,-mno-mfcrfโ ๐-mmfcrflets GCC generate the move from condition register field instruction, which was implemented on the POWER4 processor and other processors supporting the PowerPC V2.01 architecture.-mpopcntb,-mno-popcntbโ ๐ง-mpopcntblets GCC generate the popcount and double-precision FP reciprocal estimate instruction, which was implemented on the POWER5 processor and other processors supporting the PowerPC V2.02 architecture.-mpopcntd,-mno-popcntdโ ๐-mpopcntdlets GCC generate the popcount instruction, which was implemented on the POWER7 processor and other processors supporting the PowerPC V2.06 architecture.-mfprnd,-mno-fprndโ โจ-mfprndlets GCC generate the FP round to integer instructions, which were implemented on the POWER5+ processor and other processors supporting the PowerPC V2.03 architecture.-mcmpb,-mno-cmpbโ ๐-mcmpblets GCC generate the compare bytes instruction, which was implemented on the POWER6 processor and other processors supporting the PowerPC V2.05 architecture.-mhard-dfp,-mno-hard-dfpโ ๐-mhard-dfplets GCC generate the decimal floating-point instructions implemented on some POWER processors.-mcpu=cpu_typeโ ๐ this sets the architecture type, register usage, and instruction scheduling parameters for the machine typecpu_type. The supported values forcpu_typeare:
401, 403, 405, 405fp, 440, 440fp, 464, 464fp, 476, 476fp, 505,
601, 602, 603, 603e, 604, 604e, 620, 630, 740, 7400, 7450, 750, 801,
821, 823, 860, 970, 8540, a2, e300c2, e300c3, e500mc, e500mc64,
e5500, e6500, ec603e, G3, G4, G5, titan, power3, power4, power5,
power5+, power6, power6x, power7, power8, power9, power10, powerpc,
powerpc64, powerpc64le, rs64, and native.
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le are the pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC architecture machine types ๐ง. They come with an appropriate generic processor model assumed for scheduling purposes.
Specifying native as the cpu type detects the host processor of the system doing the compilation, and selects the architecture option that matches it ๐. -mcpu=native has no effect if GCC doesn't recognize the processor ๐.
The other options specify a specific processor ๐. Code generated under those options runs best on that processor, and may not run at all on others ๐.
The -mcpu options automatically enable or disable the following options ๐ธ:
-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple -mpopcntb
-mpopcntd -mpowerpc64 -mpowerpc-gpopt -mpowerpc-gfxopt -mmulhw
-mdlmzb -mmfpgpr -mvsx -mcrypto -mhtm -mpower8-fusion
-mpower8-vector -mquad-memory -mquad-memory-atomic -mfloat128
-mfloat128-hardware -mprefixed -mpcrel -mmma -mrop-protect
The exact options set for any particular CPU change between compiler versions, depending on what setting seems to produce optimal code for that CPU ๐. So they don't necessarily reflect the actual hardware's capabilities ๐. If you want to set one individual option to a particular value, put it after the -mcpu option, like -mcpu=970 -mno-altivec ๐
.
On AIX, the-maltivecand-mpowerpc64options are not enabled or disabled by the-mcpuoption at present, 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โ ๐ฏ this sets the instruction scheduling parameters for the machine typecpu_type, but it does not set the architecture type or register usage the way-mcpu=cpu_typedoes. The same values forcpu_typework for-mtuneas for-mcpu. If you specify both, the code uses the architecture and registers 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โ โจ generates code that uses (or doesn't use) AltiVec instructions, and also enables the built-in functions that give you more direct access to the AltiVec instruction set ๐ . You may also need to set-mabi=altivecto adjust the current ABI with the AltiVec ABI enhancements.
When -maltivec is used, the element order for AltiVec intrinsics such as "vec_splat", "vec_extract", and "vec_insert" matches the array element order for the endianness of the target ๐ฅ. Element zero is the leftmost element in a vector register when targeting a big-endian platform, and the rightmost element in a vector register when targeting a little-endian platform ๐.
-mvrsave,-mno-vrsaveโ ๐ฆ generates VRSAVE instructions when generating AltiVec code.-msecure-pltโ ๐ generates code that letsldandld.sobuild executables and shared libraries with non-executable".plt"and".got"sections. This is a PowerPC 32-bit SYSV ABI option.-mbss-pltโ ๐ง generates code that uses a BSS".plt"section thatld.sofills in. This requires".plt"and".got"sections that are both writable and executable ๐ญ. This is a PowerPC 32-bit SYSV ABI option.-misel,-mno-iselโ ๐ธ enables or disables the generation of ISEL instructions.-mvsx,-mno-vsxโ ๐ generates code that uses (or doesn't use) vector/scalar (VSX) instructions, and also enables the built-in functions that give more direct access to the VSX instruction set โจ.-mcrypto,-mno-cryptoโ ๐ enables (or disables) the built-in functions that give direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA.-mhtm,-mno-htmโ ๐ซถ enables (or disables) the built-in functions that give direct access to the Hardware Transactional Memory (HTM) instructions added in version 2.07 of the PowerPC ISA.-mpower8-fusion,-mno-power8-fusionโ ๐ generates code that keeps some integer operations adjacent, so the instructions can be fused together on POWER8 and later processors. The-mno-power8-fusionform doesn't keep them adjacent.-mpower8-vector,-mno-power8-vectorโ ๐ generates code that uses (or doesn't use) the vector and scalar instructions added in version 2.07 of the PowerPC ISA. It also enables the built-in functions that give more direct access to the vector instructions ๐.-mquad-memory,-mno-quad-memoryโ ๐ generates code that uses (or doesn't use) the non-atomic quad word memory instructions. The-mquad-memoryoption requires use of 64-bit mode โ ๏ธ.
-mquad-memory-atomic -mno-quad-memory-atomic
Okay so these two are a pair, bestie ๐ -mquad-memory-atomic tells GCC to generate code that uses the atomic quad word memory instructions, and -mno-quad-memory-atomic tells it to skip them. ngl the first one needs 64-bit mode to work, so keep that in mind ๐ฆ
-mfloat128 -mno-float128
Okay this one is giving main character energy ๐ -mfloat128 enables the __float128 keyword for IEEE 128-bit floating point, and -mno-float128 turns it off. Depending on your setup, GCC uses either software emulation or hardware instructions for IEEE 128-bit floats ๐ฅ
Heads up: the VSX instruction set (-mvsx) has to be enabled before you can use IEEE 128-bit floating point support, and it's only supported on Linux ๐
The default for -mfloat128 is enabled on PowerPC Linux systems using the VSX instruction set, and disabled everywhere else ๐ธ
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 generation of ISA 3.0 IEEE 128-bit floating point instructions โจ But 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 instead ๐ซถ
-mfloat128-hardware -mno-float128-hardware
Lowkey this pair is about the hardware side ๐ง -mfloat128-hardware lets GCC use ISA 3.0 hardware instructions to support the __float128 data type, and -mno-float128-hardware turns that off ๐
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
These two are the environment switches, iykyk ๐ -m32 and -m64 generate code for 32-bit or 64-bit environments of Darwin and SVR4 targets (including GNU/Linux) โจ
The 32-bit environment sets int, long and pointer to 32 bits, and the code it makes runs on any PowerPC variant ๐ The 64-bit environment sets int to 32 bits, sets long and pointer to 64 bits, and generates code for PowerPC64, same as -mpowerpc64 ๐
-mfull-toc -mno-fp-in-toc -mno-sum-in-toc -mminimal-toc
Okay the TOC (Table Of Contents) era ๐ It's created for every executable file, and these four flags control how it gets generated ๐ฆ
-mfull-toc is selected by default. In that case, GCC allocates at least one TOC entry for each unique non-automatic variable reference in your program. GCC also puts floating-point constants in the TOC ๐ธ The catch? Only 16,384 entries are available in the TOC ๐
If you get a linker error saying you've overflowed the available TOC space, you can shrink the amount of TOC space used 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 putting that sum into the TOC โจ You can use one or both. Each one makes the code very slightly slower and larger, but it saves TOC space ๐ซถ
If you still run out of space even with both of those, try -mminimal-toc instead ๐ญ This one makes only one TOC entry for every file. It produces code that's slower and larger, but it uses extremely little TOC space ๐ฅ Honestly, you might only want to use it on files with less frequently-executed code ๐ง
-maix64 -maix32
Okay this is the 64-bit AIX vibe ๐ -maix64 enables the 64-bit AIX ABI and calling convention: 64-bit pointers, a 64-bit long type, and the infrastructure needed to support them โจ Specifying -maix64 implies -mpowerpc64 ๐ -maix32 disables the 64-bit ABI and implies -mno-powerpc64 ๐
GCC defaults to -maix32 ๐
-mxl-compat -mno-xl-compat
Lowkey this one is about matching IBM XL compilers ๐ฆ -mxl-compat makes code conform more closely to IBM XL compiler semantics when you're using the AIX-compatible ABI ๐
Here's what it changes:
- Floating-point arguments passed to prototyped functions go beyond the register save area (RSA) on the stack, in addition to argument FPRs ๐ธ
- It doesn't assume that the most significant double in a 128-bit
long doublevalue is properly rounded when comparing values and converting to double ๐ - It uses XL symbol names for
long doublesupport routines ๐ง
The AIX calling convention was extended but never initially documented 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 access 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 is inefficient and rarely needed, so this option isn't enabled by default. You only really need it when calling subroutines compiled by IBM XL compilers without optimization ๐ซถ
-mpe
Okay this one is for the IBM RS/6000 SP Parallel Environment (PE) ๐ It links an application written to use message passing with special startup code so the app can run โจ
The system has to have PE installed in the standard location (/usr/lpp/ppe.poe/), or you need to override the specs file with the -specs= option to point at the right directory ๐ Heads up: the Parallel Environment doesn't support threads, so -mpe and the -pthread option are incompatible ๐ญ
-malign-natural -malign-power
Alignment vibes ๐ On AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux, -malign-natural overrides the ABI-defined alignment of larger types, like floating-point doubles, so they sit on their natural size-based boundary ๐ฆ -malign-power tells 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 is not supported ๐
-msoft-float -mhard-float
These two are about the floating-point register set ๐ง -msoft-float generates code that doesn't use the floating-point register set, and -mhard-float generates code that does ๐
Software floating-point emulation is provided if you use -msoft-float, and you have to pass the option to GCC when linking too ๐ฅ
-mmultiple -mno-multiple
Okay the multiple word vibes ๐ -mmultiple generates code that uses the load multiple word and store multiple word instructions, and -mno-multiple generates code that doesn't ๐ธ These are generated by default on POWER systems, and not generated 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 permit these instructions in little-endian mode ๐
-mupdate -mno-update
Okay this is about update instructions ๐ -mupdate generates code that uses the load or store instructions that update the base register to the address of the calculated memory location, and -mno-update generates code that doesn't โจ These instructions are generated by default ๐
If you use -mno-update, there's a small window between the time the stack pointer is updated and the time the address of the previous frame is stored ๐ญ That means code that walks the stack frame across interrupts or signals may get corrupted data ๐
-mavoid-indexed-addresses -mno-avoid-indexed-addresses
Lowkey this one is about avoiding indexed load or store instructions ๐ฆ -mavoid-indexed-addresses generates code that tries to avoid them, and -mno-avoid-indexed-addresses generates code that doesn't ๐ These instructions can take 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
Okay fused multiply-add era ๐ฅ -mfused-madd generates code that uses the floating-point multiply and accumulate instructions, and -mno-fused-madd generates code that doesn't ๐
These are generated by default if hardware floating point is used โจ
The machine-dependent -mfused-madd option is now mapped to the machine-independent -ffp-contract=fast option, and -mno-fused-madd is mapped to -ffp-contract=off ๐ซถ
-mmulhw -mno-mulhw
Okay half-word multiply energy ๐ -mmulhw generates code that uses the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors, and -mno-mulhw generates code that doesn't ๐ These are generated by default when targeting those processors ๐
-mdlmzb -mno-dlmzb
Lowkey this is the string-search era ๐ง -mdlmzb generates code that uses the string-search dlmzb instruction on the IBM 405, 440, 464 and 476 processors, and -mno-dlmzb generates code that doesn't ๐ This instruction is generated by default when targeting those processors ๐
-mno-bit-align -mbit-align
Bit-field alignment check ๐ On System V.4 and embedded PowerPC systems, -mno-bit-align does not force structures and unions that contain bit-fields to be aligned to the base type of the bit-field, and -mbit-align does ๐ฆ
For example, by default a structure containing nothing but 8 "unsigned" bit-fields of length 1 is aligned to a 4-byte boundary and has a size of 4 bytes ๐ธ With -mno-bit-align, the structure is aligned to a 1-byte boundary and is 1 byte in size โจ
-mno-strict-align -mstrict-align
Okay alignment, round two ๐
On System V.4 and embedded PowerPC systems, -mno-strict-align does not assume that unaligned memory references are handled by the system, and -mstrict-align does ๐ซถ
-mrelocatable -mno-relocatable
Relocation energy ๐ฅ -mrelocatable generates code that allows a static executable to be relocated to a different address at run time, and -mno-relocatable generates code that doesn't ๐ A simple embedded PowerPC system loader should relocate the entire contents of ".got2" and 4-byte locations listed in the ".fixup" section, which is a table of 32-bit addresses generated by this option ๐ง
For this to work, all objects linked together must be compiled with -mrelocatable or -mrelocatable-lib ๐ญ -mrelocatable code aligns the stack to an 8-byte boundary ๐
-mrelocatable-lib -mno-relocatable-lib
Okay this is the sibling of -mrelocatable ๐ฆ Like -mrelocatable, -mrelocatable-lib generates a ".fixup" section so static executables can be relocated at run time ๐ The difference is that -mrelocatable-lib does not use the smaller stack alignment of -mrelocatable โจ Objects compiled with -mrelocatable-lib may be linked with objects compiled with any combination of the -mrelocatable options ๐
-mno-toc -mtoc
Lowkey this one is about register 2 ๐ธ On System V.4 and embedded PowerPC systems, -mno-toc does not assume that register 2 contains a pointer to a global area pointing to the addresses used in the program, and -mtoc does ๐
-mlittle -mlittle-endian
Endian era ๐ง On System V.4 and embedded PowerPC systems, these compile code for the processor in little-endian mode ๐ซถ -mlittle-endian is the same as -mlittle ๐
-mbig -mbig-endian
Same energy, other side ๐ On System V.4 and embedded PowerPC systems, these compile code for the processor in big-endian mode ๐ -mbig-endian is the same as -mbig โจ
-mdynamic-no-pic
Last one in this part, bestie ๐ On Darwin and Mac OS X systems, -mdynamic-no-pic compiles code so that it is not relocatable, but its external references are relocatable ๐ฆ The resulting code is suitable for applications, but not shared libraries ๐
-msingle-pic-baseโ okay this one is lowkey chill ๐ง It makes the register used for PIC addressing read-only ๐ instead of loading it in the prologue for every single function. The runtime system is the one in charge of setting this register to an appropriate value before execution begins, so that's on them ๐-mprioritize-restricted-insns=priorityโ this one picks the priority for dispatch-slot restricted instructions during the second scheduling pass ๐๏ธ The priority argument takes0,1, or2, which gives those instructions no priority, highest priority, or second-highest priority (respectively). Main character energy, but make it a choice ๐-msched-costly-dep=dependence_typeโ this decides which dependences the target considers costly during instruction scheduling ๐ธ The dependence_type argument takes one of these:noโ no dependence is costly ๐ โโ๏ธallโ all dependences are costly ๐ญtrue_store_to_loadโ a true dependence from store to load is costlystore_to_loadโ any dependence from store to load is costly- number โ any dependence whose latency is greater than or equal to number is costly
-minsert-sched-nops=schemeโ this picks the NOP insertion scheme used during the second scheduling pass ๐ซง The scheme argument takes one of these:noโ don't insert NOPs at all ๐ซpadโ pad with NOPs any dispatch group that has vacant issue slots, according to the scheduler's groupingregroup_exactโ insert NOPs to force costly dependent insns into separate groups, using exactly as many NOPs as needed to push an insn into a new group, according to the estimated processor grouping- number โ insert NOPs to force costly dependent insns into separate groups, using number NOPs to push an insn into a new group
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code with calling conventions that follow the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement ๐ This is the default unless you configured GCC usingpowerpc-*-eabiaix.-mcall-sysv-eabi,-mcall-eabiโ same as specifying both-mcall-sysvand-meabi๐ค-mcall-sysv-noeabiโ same as specifying both-mcall-sysvand-mno-eabi๐-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐ฅ๏ธ-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐ก-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐ก-mtraceback=traceback_typeโ selects the type of traceback table ๐ Valid values for traceback_type arefull,part, andno.-maix-struct-returnโ returns all structures in memory, as the AIX ABI specifies ๐งฑ-msvr4-struct-returnโ returns structures smaller than 8 bytes in registers, as the SVR4 ABI specifies ๐งบ-mabi=abi-typeโ extends the current ABI with a particular extension, or removes that extension ๐ง Valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1,elfv2, and for AIX:vec-extabi,vec-default.-mabi=ibmlongdoubleโ switches the current ABI to IBM extended-precision long double ๐ซ
This is not likely to work if your system defaults to IEEE extended-precision long double. If you change the long double type from IEEE extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption. Requires-mlong-double-128to be enabled.
-mabi=ieeelongdoubleโ switches the current ABI to IEEE extended-precision long double ๐ซ
This is not likely to work if your system defaults to IBM extended-precision long double. If you change the long double type from IBM extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption. Requires-mlong-double-128to be enabled.
-mabi=elfv1โ switches the current ABI to the ELFv1 ABI ๐ธ This is the default ABI for big-endian PowerPC 64-bit Linux.
Overriding the default ABI requires special system support and is likely to fail in spectacular ways. ๐
-mabi=elfv2โ switches the current ABI to the ELFv2 ABI ๐ธ This is the default ABI for little-endian PowerPC 64-bit Linux.
Overriding the default ABI requires special system support and is likely to fail in spectacular ways. ๐
-mgnu-attribute,-mno-gnu-attributeโ emits.gnu_attributeassembly directives that set tag/value pairs in a.gnu.attributessection ๐ท๏ธ Those pairs specify ABI variations in function parameters or return values.-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems, this assumes that all calls to variable argument functions are properly prototyped โ Otherwise, the compiler has to insert an instruction before every non-prototyped call to set or clear bit 6 of the condition code register ("CR"). That bit 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 the 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 specifies that you're compiling for a VxWorks system ๐ฐ๏ธ-membโ on embedded PowerPC systems, this sets the "PPC_EMB" bit in the ELF flags header to show that eabi extended relocations are used ๐ฆ-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems, this makes the code adhere (or not adhere) to the Embedded Applications Binary Interface (EABI), which is a set of modifications to the System V.4 specifications โจ-meabimeans the stack is aligned to an 8-byte boundary, a function__eabiis called frommainto set up the EABI environment, and the-msdataoption can use bothr2andr13to point to two separate small data areas.-mno-eabimeans the stack is aligned to a 16-byte boundary, no EABI initialization function is called frommain, and the-msdataoption only usesr13to point to a single small data area.- The
-meabioption is on by default if you configured GCC using one of thepowerpc*-*-eabi*options.
-msdata=eabiโ on System V.4 and embedded PowerPC systems, this puts small initializedconstglobal and static data in the.sdata2section, which is pointed to by registerr2๐ Small initialized non-constglobal and static data goes in the.sdatasection, pointed to by registerr13. Small uninitialized global and static data goes in the.sbsssection, which sits right next to.sdata๐๏ธ
The-msdata=eabioption is incompatible with the-mrelocatableoption. It also sets the-memboption.
-msdata=sysvโ on System V.4 and embedded PowerPC systems, this puts small global and static data in the.sdatasection, which is pointed to by registerr13๐ท Small uninitialized global and static data goes in the.sbsssection, which is adjacent to.sdata.
The-msdata=sysvoption is incompatible with the-mrelocatableoption.
-msdata=default,-msdataโ on System V.4 and embedded PowerPC systems, if-meabiis used, this compiles code the same as-msdata=eabi. Otherwise, it compiles code the same as-msdata=sysv๐คทโโ๏ธ-msdata=dataโ on System V.4 and embedded PowerPC systems, this puts small global data in the.sdatasection and small uninitialized global data in the.sbsssection ๐ It does not use registerr13to address small data, though. This is the default behavior unless other-msdataoptions are used.-msdata=none,-mno-sdataโ on embedded PowerPC systems, this puts all initialized global and static data in the.datasection, and all uninitialized data in the.bsssection ๐ซง-mreadonly-in-sdataโ puts read-only objects in the.sdatasection too ๐ This is the default.-mblock-move-inline-limit=numโ inlines all block moves (like calls tomemcpyor structure copies) that are less than or equal to num bytes ๐โโ๏ธ The minimum value for num is 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default value is target-specific.-mblock-compare-inline-limit=numโ generates non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal to num bytes ๐ If num is0, all inline expansion (non-loop and loop) of block compare is disabled. The default value is target-specific.-mblock-compare-inline-loop-limit=numโ generates an inline expansion using loop code for all block compares that are less than or equal to num bytes, but greater than the limit for non-loop inline block compare expansion ๐ If the block length isn't constant, at most num bytes will be compared beforememcmpis called to compare the rest of the block. The default value is target-specific.-mstring-compare-inline-limit=numโ compares at most num string bytes with inline code ๐งต If the difference or end of string isn't found at the end of the inline compare, a call tostrcmporstrncmptakes care of the rest of the comparison. The default is 64 bytes.-G numโ on embedded PowerPC systems, this puts global and static items that are less than or equal to num bytes into the small data or BSS sections, instead of the normal data or BSS section ๐ง By default, num is8. The-G numswitch is also passed to the linker, so all modules should be compiled with the same-G numvalue ๐-mregnames,-mno-regnamesโ okay so on System V.4 and embedded PowerPC systems,-mregnamesmakes GCC do print register names in the assembly output using their symbolic forms ๐ธ, and-mno-regnamesmeans it does not do that ๐ โโ๏ธ-mlongcall,-mno-longcallโ by default GCC assumes every call is super far away ๐ญ, so it uses a longer, more expensive calling sequence. That's needed 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 spot out-of-range calls and generate glue code on the fly ๐ช. On those systems, long calls are unnecessary and just make the code slower ๐. As of this writing, the AIX linker can do this, as can the GNU linker for PowerPC/64. It is planned to add this feature to the GNU linker for 32-bit PowerPC systems as well ๐.
On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see -mpltseq). PowerPC with -mbss-plt and PowerPC64 ELFv1 (big-endian) do not support inline PLT calls ๐
On Darwin/PPC systems, #pragma longcall generates jbsr callee, L42, plus a branch island (glue code) ๐๏ธ. The two target addresses represent the callee and the branch island. The Darwin/PPC linker prefers the first address and generates a bl callee if the PPC bl instruction reaches the callee directly; otherwise, the linker generates bl L42 to call the branch island. The branch island is appended to the body of the calling function; it computes the full 32-bit address of the callee and jumps to it.
On Mach-O (Darwin) systems, this option directs the compiler to emit the glue for every direct call, and the Darwin linker decides whether to use or discard it ๐ง
In the future, GCC may ignore all longcall specifications when the linker is known to generate glue ๐ฎ
-mpltseq,-mno-pltseqโ-mpltseqtells GCC to implement-fno-pltand long calls using an inline PLT call sequence ๐งต. It supports lazy linking and long calls to functions indlopen'dshared libraries.-mno-pltseqsays nope to all that. Inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers ๐งฉ. They're enabled by default if the support is detected when GCC is configured, and, for 32-bit PowerPC, if GCC is configured with--enable-secureplt.-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together ๐-mtls-markers,-mno-tls-markersโ GCC will (or won't) mark calls to__tls_get_addrwith a relocation that specifies the function argument ๐ท๏ธ. That relocation lets the linker reliably connect the function call with its argument setup instructions for TLS optimization, which in turn lets GCC schedule the sequence better ๐-mrecip,-mno-recipโ this option turns on the reciprocal estimate and reciprocal square root estimate instructions, with extra Newton-Raphson steps to bump up precision ๐. It's used instead of doing a divide, or a square root and a divide, for floating-point arguments. You should use-ffast-mathwhen using-mrecip(or at least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math) ๐ . Note that while the throughput of the sequence is generally higher than the throughput of the non-reciprocal instruction, the precision of the sequence can be decreased by up to 2 ulp (i.e. the inverse of 1.0 equals 0.99999994) for reciprocal square roots ๐ญ-mrecip=optโ this one controls which reciprocal estimate instructions are allowed to be used ๐๏ธ.optis a comma-separated list of options, and any of them can be preceded by a!to invert the option: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 the FRSQRTE, XSRSQRTEDP, and XVRSQRTEDP instructions, which handle the double-precision reciprocal square root calculations ๐ง
-mrecip-precision,-mno-recip-precisionโ assume (or don't assume) that the reciprocal estimate instructions give higher-precision estimates than the PowerPC ABI requires ๐ฏ. Selecting-mcpu=power6,-mcpu=power7or-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 provide an estimate that converges 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 using external libraries. 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, andtanhf4when generating code for power7 โก. Both-ftree-vectorizeand-funsafe-math-optimizationsmust also be enabled. The MASS libraries must be specified at link time ๐-mfriz,-mno-frizโ GCC will (or won't) generate thefrizinstruction when-funsafe-math-optimizationsis used to optimize rounding of floating-point values to 64-bit integer and back to floating point ๐. Heads up: thefrizinstruction does not return the same value if the floating-point number is too large to fit in an integer ๐ฌ-mpointers-to-nested-functions,-mno-pointers-to-nested-functionsโ GCC will (or won't) generate code that loads up the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems ๐งญ. That's the case where a function pointer points to a 3-word descriptor giving the function address, the TOC value to be loaded in registerr2, and the static chain value to be loaded in registerr11.-mpointers-to-nested-functionsis on by default. 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 ๐ซ-msave-toc-indirect,-mno-save-toc-indirectโ GCC will (or won't) save the TOC value in the reserved stack location in the function prologue, if the function calls through a pointer on AIX and 64-bit Linux systems ๐พ. If the TOC value isn't saved in the prologue, it gets saved just before the call through the pointer. The-mno-save-toc-indirectoption is the default โจ-mcompat-align-parm,-mno-compat-align-parmโ GCC will (or won't) generate code that passes structure parameters with a maximum alignment of 64 bits, for compatibility with older versions of GCC ๐ค
Older versions of GCC (prior to 4.9.0) incorrectly did not align a structure parameter on a 128-bit boundary when that structure contained a member requiring 128-bit alignment. This is corrected in more recent versions of GCC. This option may be used to generate code that is compatible with functions compiled with older versions of GCC ๐ฐ๏ธ
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โ these generate 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 with GNU libc version 2.4 or later) ๐ก๏ธ
With the latter choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset furthermore specify which register to use as the base register for reading the canary, and from what offset from that base register. The default for those is as specified in the relevant ABI. -mstack-protector-guard-symbol=symbol overrides the offset with a symbol reference to a canary in the TLS block ๐
-mpcrel,-mno-pcrelโ GCC will (or won't) generate pc-relative addressing ๐. The-mpcreloption requires that the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) options are enabled.-mprefixed,-mno-prefixedโ GCC will (or won't) generate addressing modes using prefixed load and store instructions ๐งฉ. The-mprefixedoption requires that the option-mcpu=power10(or later) is enabled.-mmma,-mno-mmaโ GCC will (or won't) generate the MMA instructions ๐งฎ. The-mmaoption requires that the option-mcpu=power10(or later) is enabled.-mrop-protect,-mno-rop-protectโ GCC will (or won't) generate ROP protection instructions when the target processor supports them ๐. Currently this option disables the shrink-wrap optimization (-fshrink-wrap).-mprivileged,-mno-privilegedโ GCC will (or won't) generate code that runs in privileged state ๐-mblock-ops-unaligned-vsx,-mno-block-ops-unaligned-vsxโ GCC will (or won't) generate unaligned vsx loads and stores for inline expansion ofmemcpyandmemmove๐ฆ
โจ RX Options โจ
These command-line options are defined for RX targets:
โจ RX Options โจ (continued)
-m64bit-doubles,-m32bit-doublesโ okay so these decide how big thedoubletype is ๐ฆ.-m64bit-doublesmakes it 64 bits and-m32bit-doublesmakes it 32 bits. The default is-m32bit-doubles, and that's not random: RX floating-point hardware only works on 32-bit values ๐ .-fpu,-nofpuโ this one turns the RX floating-point hardware on (-fpu) or off (-nofpu) ๐ธ. It's on by default for the RX600 series and off by default for the RX200 series.
Floating-point instructions only get generated for 32-bit floating-point values, so the FPU hardware isn't used for doubles if -m64bit-doubles is in play ๐.
Note: If-fpuis enabled,-funsafe-math-optimizationsgets turned on automatically too. The RX FPU instructions are themselves unsafe, so it's not optional ๐.
-mcpu=nameโ picks which RX CPU you're targeting ๐. There are three options: the generic RX600 series, the RX200 series, and the specific RX610 CPU. The default is RX600.
The only difference between RX600 and RX610 is that the RX610 doesn't support the "MVTIPL" instruction ๐ง.
The RX200 series doesn't have a hardware floating-point unit, so -nofpu is turned on by default whenever this type is selected โจ.
-mbig-endian-data,-mlittle-endian-dataโ controls how data (but not code) gets stored ๐.-mbig-endian-datastores it in big-endian format. The default is-mlittle-endian-data, so data is stored in little-endian format.-msmall-data-limit=Nโ sets the maximum size in bytes of global and static variables that can be placed into the small data area ๐. Using that area can make code smaller and faster, but the area is limited, and it's up to you 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 at that area. That means the compiler can't use it anymore, which can lead to slower and/or larger code if variables get pushed onto the stack instead of living in that register ๐.
Note, common variables (variables that haven't been initialized) and constants are not 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 at higher optimization levels (-O2 etc) because reserving a register can be detrimental. It's up to you to experiment and see whether it helps your program ๐ฌ. For how the actual register holding the small data area pointer is chosen, check the description of the -mpid option.
-msim,-mno-simโ-msimuses the simulator runtime ๐ฎ. The default is to use thelibglossboard-specific runtime.-mas100-syntax,-mno-as100-syntaxโ when generating assembler output,-mas100-syntaxuses a syntax compatible with Renesas's AS100 assembler ๐. The GAS assembler can handle this syntax too, but it has some restrictions, so it isn't generated by default.-mmax-constant-size=Nโ sets 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, but a longer value means a longer instruction. So sometimes it's actually beneficial to limit how big the constants are.
Constants that are too big get placed into a constant pool instead and referenced via register indirection ๐ฆ.
The value N can be between 0 and 4. A value of 0 (the default) or 4 means constants of any size are allowed ๐.
-mrelaxโ enables linker relaxation ๐ง. This is when the linker tries to shrink your program by finding shorter versions of various instructions. It's disabled by default.-mint-register=Nโ reserves a number of registers for fast interrupt handler functions โก. The valueNcan be between 0 and 4. Here's how the reserving goes:- A value of 1 reserves
"r13"for the exclusive use of fast interrupt handlers. - A value of 2 reserves
"r13"and"r12". - A value of 3 reserves
"r13","r12"and"r11". - A value of 4 reserves
"r13"through"r10". - A value of 0, the default, doesn't reserve any registers.
-msave-acc-in-interruptsโ tells interrupt handler functions to preserve the accumulator register ๐งฒ. This is only necessary if normal code might use the accumulator, for example because it does 64-bit multiplications. The default is to ignore the accumulator, since that makes the interrupt handlers faster ๐๏ธ.-mpid,-mno-pidโ-mpidenables the generation of position independent data ๐บ๏ธ. When it's on, any access to constant data is done via an offset from a base address held in a register. This lets the location of constant data 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.
Heads up, using this feature reserves a register (usually "r13") for the constant data base address. That can make code slower and/or larger, especially in complicated functions ๐ฌ.
Which register actually gets chosen for the constant data base address depends on whether -msmall-data-limit and/or -mint-register are enabled. Starting with "r13" and moving downwards, registers get allocated first to satisfy the requirements of -mint-register, then -mpid, and finally -msmall-data-limit. So it's possible for the small data area register to end up as "r8" if both -mint-register=4 and -mpid are specified on the command line ๐งฉ.
By default this feature is not enabled. The default can be restored with the -mno-pid command-line option ๐.
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interruptsโ-mno-warn-multiple-fast-interruptsstops GCC from warning you 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, since the RX only supports one such interrupt.-mallow-string-insns,-mno-allow-string-insnsโ these enable or disable the string manipulation instructions"SMOVF","SCMPU","SMOVB","SMOVU","SUNTIL""SWHILE"and also the"RMPA"instruction ๐งต. These instructions may prefetch data, which is not safe to do when you're accessing an I/O register โ ๏ธ. (See section 12.2.7 of the RX62N Group User's Manual for more info.)
Warning: The default is to allow these instructions, but GCC can't reliably detect every circumstance where a string instruction might be used to access an I/O register. So their use can't be disabled automatically. It's on you to use -mno-allow-string-insns if your program accesses I/O space ๐จ.
When the instructions are enabled, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. Otherwise, it defines __RX_DISALLOW_STRING_INSNS__ ๐ท๏ธ.
-mjsr,-mno-jsrโ-mjsruses only (or not only)"JSR"instructions to access functions ๐. This option can help when code size exceeds the range of"BSR"instructions. Heads up:-mno-jsrdoesn't mean "don't useJSR". It means any type of branch may be used ๐.
Note: The generic GCC command-line option -ffixed-reg has special significance to the RX port when it's used with the "interrupt" function attribute ๐ซ. That attribute marks a function meant to process fast interrupts. GCC makes sure it only uses the registers "r10", "r11", "r12" and/or "r13", and only when the normal use of the corresponding registers has been restricted through the -ffixed-reg or -mint-register command-line options ๐.
โจ S/390 and zSeries Options โจ
Here are the -m options defined for the S/390 and zSeries architecture ๐.
-mhard-float,-msoft-floatโ-mhard-floatuses the hardware floating-point instructions and registers for floating-point operations ๐ง.-msoft-floatdoes not, so the functions inlibgcc.ado the floating-point work instead. When-mhard-floatis specified, the compiler generates IEEE floating-point instructions. This is the default.-mhard-dfp,-mno-hard-dfpโ-mhard-dfpuses the hardware decimal-floating-point instructions for decimal-floating-point operations ๐ข. When-mno-hard-dfpis specified, the functions inlibgcc.ahandle decimal-floating-point operations instead. When-mhard-dfpis specified, the compiler generates decimal-floating-point hardware instructions. This is the default for-march=z9-ecor higher.-mlong-double-64,-mlong-double-128โ these switches control the size of the"long double"type ๐. A size of 64 bits makes"long double"equivalent to the"double"type. This is the default.-mbackchain,-mno-backchainโ-mbackchainstores the address of the caller's frame as a backchain pointer in the callee's stack frame ๐. A backchain may be needed to allow debugging with tools that don't understand DWARF call frame information. When-mno-packed-stackis in effect, the backchain pointer is stored at the bottom of the stack frame. When-mpacked-stackis in effect, the backchain is placed into the topmost word of the 96/160 byte register save area ๐ช.
In general, code compiled with -mbackchain is call-compatible with code compiled with -mno-backchain. However, using the backchain for debugging purposes usually requires that the whole binary is built with -mbackchain ๐งธ. Also, the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported ๐
. To build a Linux kernel, use -msoft-float.
The default is to not maintain the backchain.
-mpacked-stack,-mno-packed-stackโ Okay so this one is about 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 job, which means unused fields still take up stack space ๐ With-mpacked-stack, the register save slots get densely packed at the top of the save area, and the leftover space gets reused for other stuff, so the stack is used way more efficiently โจ 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-stackis call-compatible with code made with-mno-packed-stack. 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), and that code is NOT call-compatible with-mpacked-stackcode. The default is to not use the packed stack layout.
Not meโฆ the combination of-mbackchain,-mpacked-stackand-mhard-floatis NOT supported ๐ญ If you're building a linux kernel, use-msoft-floatinstead.
-msmall-exec,-mno-small-execโ Generate (or don't generate) code that makes subroutine calls with the"bras"instruction. This only works reliably if the total executable size stays under 64k, so be careful, bestie ๐ The default is the"basr"instruction instead, which doesn't have that limit ๐ธ-m64,-m31โ With-m31, code gets generated to be compliant with the GNU/Linux for S/390 ABI. With-m64, it's compliant with the GNU/Linux for zSeries ABI, which lets GCC generate 64-bit instructions ๐ฅ For the s390 targets the default is-m31, while the s390x targets default to-m64๐-mzarch,-mesaโ-mzarchgenerates code using the instructions available on z/Architecture, and-mesagenerates code using the instructions available on ESA/390 ๐ฆ-mesais not possible with-m64, so don't even try ๐ When generating code compliant with the GNU/Linux for S/390 ABI, the default is-mesa. For the GNU/Linux for zSeries ABI, the default is-mzarch๐-mhtm,-mno-htmโ-mhtmenables a set of builtins that make use of instructions from the transactional execution facility, which was introduced with the IBM zEnterprise EC12 machine generation (S/390 System z Built-in Functions) ๐-mhtmis enabled by default when using-march=zEC12โจ-mvx,-mno-vxโ-mvxgenerates 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 used ๐-mvxis enabled by default when using-march=z13๐-mzvector,-mno-zvectorโ-mzvectorturns on vector language extensions and builtins using the vector extension facility instructions from the IBM z13 generation ๐ It adds support forvectoras a keyword to define vector type variables and arguments.vectoris only available when GNU extensions are enabled, and it won't be expanded if you ask for strict standard compliance, e.g. with-std=c99๐ On top of the GCC low-level builtins,-mzvectorenables 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 the"mvcle"instruction for block moves ๐ง With-mno-mvcle, a"mvc"loop is used instead. This is the default unless you're optimizing for size ๐ธ-mdebug,-mno-debugโ Print (or don't print) additional 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 ๐ Possible values forcpu-typearez900/arch5, z990/arch6, z9-109, z9-ec/arch7, z10/arch8, z196/arch9, zEC12, z13/arch11, z14/arch12, z15/arch13, z16/arch14, andnative. The default is-march=z900โจ
Picking native as the cpu type selects the best architecture option for the host processor ๐ฆ -march=native has no effect if GCC doesn't recognize the processor, so it just sits there looking cute ๐ฅบ
-mtune=cpu-typeโ Tune everything applicable about the generated code tocpu-type, EXCEPT the ABI and the set of available instructions ๐ The list ofcpu-typevalues is the same as for-march. The default is whatever value is 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. These 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 when you specify-mtpf-trace๐ญ-mfused-madd,-mno-fused-maddโ Generate code that uses (or doesn't use) the floating-point multiply and accumulate instructions ๐ฅ These get generated by default if hardware floating point is used ๐-mwarn-framesize=framesizeโ Emit a warning if the current function exceeds the given frame size โ ๏ธ Since this is a compile-time check, it doesn't need to be a real problem when the program runs ๐ It's meant to spot functions that will most probably cause a stack overflow, so 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 with a limited stack size, so keep an eye out, bestie ๐-mstack-guard=stack-guard,-mstack-size=stack-sizeโ If you provide these options, the S/390 back end emits extra instructions in the function prologue that trigger a trap if the stack size isstack-guardbytes above thestack-size(remember the stack on S/390 grows downward โฌ๏ธ). If you leave outstack-guard, the smallest power of 2 larger than the frame size of the compiled function gets chosen ๐ง These are meant to help you debug stack overflow problems. The extra code causes only little overhead, so it can also be used in production-like systems without much performance hit ๐ The given values have to be exact powers of 2, andstack-sizehas to be greater thanstack-guardwithout exceeding 64k ๐ To be efficient, the extra code assumes the stack starts at an address aligned to the value given bystack-size๐ฆ Thestack-guardoption can only be used in conjunction withstack-size๐-mhotpatch=pre-halfwords,post-halfwordsโ If the hotpatch option is enabled, a "hot-patching" function prologue is generated for ALL functions in the compilation unit ๐ฅ The function label gets prepended with the given number of two-byte NOP instructions (pre-halfwords, maximum 1000000). After the label, 2 *post-halfwordsbytes are appended, using the largest NOP-like instructions the architecture allows (maximum 1000000) ๐ธ
If both arguments are zero, hotpatching is disabled ๐
You can override this option for individual functions with the "hotpatch" attribute ๐
๐ Score Options
These options are defined for Score implementations ๐
-mebโ Compile code for big-endian mode. This is the default ๐-melโ Compile code for little-endian mode ๐ซถ-mnhwloopโ Disable generation ofbcnzinstructions ๐-mulsโ Enable generation of unaligned load and store instructions โจ-mmacโ Enable the use of multiply-accumulate instructions. Disabled by default ๐ฅ-mscore5โ Specify the SCORE5 as the target architecture ๐ฆ-mscore5uโ Specify the SCORE5U of the target architecture ๐ง-mscore7โ Specify the SCORE7 as the target architecture. This is the default ๐-mscore7dโ Specify the SCORE7D as the target architecture ๐
๐ SH Options
These -m options are defined for the SH implementations ๐
-m1โ Generate code for the SH1 ๐ธ-m2โ Generate code for the SH2 ๐ธ-m2eโ Generate code for the SH2e ๐-m2a-nofpuโ Generate code for the SH2a without FPU, or for a SH2a-FPU in such a way that the floating-point unit is not used ๐-m2a-single-onlyโ Generate code for the SH2a-FPU in such a way 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 such 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 in such a way that no double-precision floating-point operations are used ๐-m4-200โ Generate code for SH4-200 โญ-m4-200-nofpuโ okay so this one generates code for SH4-200 in a way that the floating-point unit never gets used ๐ ๐ธ-m4-200-singleโ SH4-200 code, assuming the FPU is in single-precision mode by default ๐-m4-200-single-onlyโ SH4-200 code with no double-precision floating-point operations, bestie ๐ฆ-m4-300โ generates code for SH4-300 โจ-m4-300-nofpuโ SH4-300 code that doesn't use the FPU at all ๐ง-m4-300-singleโ SH4-300 code with no double-precision floating-point operations ๐-m4-300-single-onlyโ SH4-300 code with no double-precision floating-point operations. Yes, this is the same description as-m4-300-single, and the original page is giving us a little repeat moment ๐-m4-340โ SH4-340 code, with no MMU and no FPU ๐-m4-500โ SH4-500 code with no FPU. This one also passes-isa=sh4-nofputo the assembler, so it's doing extra work for you ๐ฅ-m4a-nofpuโ this is for the SH4al-dsp, or for an SH4a in a way where the floating-point unit isn't used ๐-m4a-single-onlyโ SH4a code with no double-precision floating-point operations ๐-m4a-singleโ SH4a code, assuming the FPU is in single-precision mode by default โญ-m4aโ generates code for the SH4a ๐-m4alโ same as-m4a-nofpu, except it also implicitly passes-dspto the assembler. Lowkey iconic, but GCC doesn't generate any DSP instructions at the moment, so don't expect them yet ๐ซถ-mbโ compiles code for the processor in big-endian mode ๐ธ-mlโ compiles code for the processor in little-endian mode ๐ฆ-mdalignโ aligns doubles at 64-bit boundaries. Heads up, this changes the calling conventions, so some functions from the standard C library won't work unless you recompile them first with-mdalignโ ๏ธ It's giving "read the fine print or else" ๐
Careful, bestie:-mdalignchanges the calling conventions, so standard C library functions can break unless you recompile the library with-mdalignfirst ๐ญ
-mrelaxโ shortens some address references at link time, when it's possible. It does this by using the linker option-relaxโจ-mbigtableโ uses 32-bit offsets in"switch"tables. The default is 16-bit offsets, so this one is the upgrade ๐-mbitopsโ enables bit manipulation instructions on SH2A ๐-mfmovdโ enables thefmovdinstruction. Make sure you check-mdalignfor alignment constraints ๐ง-mrenesasโ makes your code follow the calling conventions defined by Renesas ๐-mno-renesasโ makes your code follow the calling conventions GCC used before the Renesas conventions existed. This is the default for all targets of the SH toolchain, so it's the main character by default ๐-mnomacsaveโ marks the"MAC"register as call-clobbered, even if-mrenesasis given ๐ฅ-mieee,-mno-ieeeโ these control IEEE compliance for floating-point comparisons, which affects how cases with unordered comparison results get handled. By default-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled,-mno-ieeegets implicitly set, which makes floating-point greater-equal and less-equal comparisons faster. You can override the implicit settings by specifying either-mieeeor-mno-ieee๐ โจ-minline-ic_invalidateโ inlines code that invalidates instruction cache entries after setting up nested function trampolines ๐ฆ Ngl this one has a lot of conditions:- It has no effect if
-musermodeis in effect and the selected code generation option (e.g.-m4) doesn't allow the use of the"icbi"instruction. - If the selected code generation option doesn't allow
"icbi", and-musermodeisn't in effect, the inlined code manipulates the instruction cache address array directly with an associative write. This not only requires privileged mode at run time, it also fails if the cache line had been mapped via the TLB and has become unmapped ๐
- It has no effect if
-misizeโ dumps instruction size and location in the assembly code ๐-mpadstructโ this one is deprecated ๐ฅ It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI, so let it go ๐-matomic-model=modelโ sets the model of atomic operations, plus additional parameters, as a comma separated list. For the full scoop on atomic built-in functions, check out __atomic Builtins ๐ These are the models and parameters that are supported:noneโ disables compiler generated atomic sequences and emits library calls for atomic operations instead. This is the default if the target is not"sh*-*-linux*".soft-gusaโ generates GNU/Linux compatible gUSA software atomic sequences for the atomic built-in functions. The generated sequences need extra support from the interrupt/exception handling code of the system, and they're only suitable for SH3* and SH4* single-core systems. This option is enabled by default when the target is"sh*-*-linux*"and the chip is SH3* or SH4*. When the target is SH4A, this option also partially uses the hardware atomic instructions"movli.l"and"movco.l"to make more efficient code, unlessstrictis specified โจsoft-tcbโ generates 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. The generated sequences need extra support from the interrupt/exception handling code and are only suitable for single-core systems. When you use this model, thegbr-offset=parameter has to be specified as well ๐soft-imaskโ generates software atomic sequences that temporarily disable interrupts by setting"SR.IMASK = 1111". This model only works when the program runs in privileged mode, and it's only suitable for single-core systems. It doesn't need additional support from the interrupt/exception handling code. This model is enabled by default when the target is"sh*-*-linux*"and the chip is SH1* or SH2* ๐งhard-llcsโ generates hardware atomic sequences using only the"movli.l"and"movco.l"instructions. 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 get 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 need additional support from the interrupt/exception handling code ๐ฆgbr-offset=โ specifies the offset in bytes of the variable in the thread control block structure that the generated atomic sequences should use when thesoft-tcbmodel is selected. For other models this parameter is ignored. The value must be an integer multiple of four and in the range0-1020๐strictโ prevents mixing multiple atomic models, even if they're compatible, and makes the compiler generate atomic sequences of the specified model only ๐
-mtasโ generates the"tas.b"opcode for"__atomic_test_and_set". Notice that depending on your particular hardware and software configuration, this can hurt overall performance because of the operand cache line flushes that the"tas.b"instruction implies. On multi-core SH4A processors, the"tas.b"instruction must be used with caution, since it can cause data corruption for certain cache configurations ๐-mprefergotโ when generating position-independent code, emits function calls using the Global Offset Table instead of the Procedure Linkage Table ๐ธ-musermode,-mno-usermodeโ "Don't allow (allow)" the compiler to generate privileged mode code. Specifying-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode.-musermodeis the default when the target is"sh*-*-linux*". If the target is SH1* or SH2*,-musermodehas no effect, since there's no user mode on those chips ๐-multcost=numberโ sets the cost to assume for a multiply insn ๐ข-mdiv=strategyโ sets the division strategy used for integer division operations.strategycan be one of these:call-div1โ calls a library function that uses the single-step division instruction"div1"to perform the operation. Division by zero calculates an unspecified result and does not trap. This is the default except for SH4, SH2A and SHcompact ๐call-fpโ calls a library function that performs the operation in double precision floating point. Division by zero causes a floating-point exception. This is the default for SHcompact with FPU. Specifying this for targets that don't have a double precision FPU defaults to"call-div1"๐ฅcall-tableโ calls a library function that uses a lookup table for small divisors, and the"div1"instruction with case distinction for larger divisors. Division by zero calculates an unspecified result and does not trap. This is the default for SH4. Specifying this for targets that don't have dynamic shift instructions defaults to"call-div1"๐ง
When a division strategy hasn't been specified, the default strategy gets selected based on the current target. For SH2A, the default strategy is to use the "divs" and "divu" instructions instead of library function calls โจ
-maccumulate-outgoing-argsโ reserves space once for outgoing arguments in the function prologue, rather than around each call. This is generally beneficial for performance and size. It's also needed for unwinding, so the stack frame doesn't change around conditional code ๐ฆ-mdivsi3_libfunc=nameโ sets the name of the library function used for 32-bit signed division toname. This only affects the name used in the call division strategies. The compiler still expects the same sets of input/output/clobbered registers as if this option weren't present ๐-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers. A fixed register is one that the register allocator cannot use. This is super useful when compiling kernel code ๐ A register range is specified as two registers separated by a dash, and you can specify multiple register ranges separated by a comma ๐
okay so the branch stuff is next, and it's giving performance ๐
-mbranch-cost=numโ โจ Tells the compiler to treat num as the cost of a branch instruction. Higher numbers push it to try harder for branch-free code when that's possible ๐ฆ. If you don't set it, the value gets picked based on the processor you're compiling for ๐ง.-mzdcbranch,-mno-zdcbranchโ ๐-mzdcbranchsays the zero displacement conditional branchesbtandbfare fast, so the compiler prefers those branch sequences. It's on by default for SH4 and SH4A ๐. You can turn it off with-mno-zdcbranch.-mcbranch-force-delay-slotโ ๐ Forces the delay slot to be used for conditional branches. If there's no suitable instruction, it fills the slot with anop๐. It's off by default, but you can flip it on to work around the hardware bugs found in the original SH7055.-mfused-madd,-mno-fused-maddโ ๐ฅ Makes the code use (or not use) the floating-point multiply and accumulate instructions. These are generated by default when hardware floating point is in use ๐. Heads up:-mfused-maddis now mapped to the machine-independent-ffp-contract=fast, and-mno-fused-maddis mapped to-ffp-contract=off๐ซถ.-mfsca,-mno-fscaโ ๐ฆ Lets the compiler emit thefscainstruction for sine and cosine approximations, or not.-mfscahas to go together with-funsafe-math-optimizations๐. It's on by default for SH4A.-mno-fscaturns off the sine and cosine approximations even if-funsafe-math-optimizationsis in effect ๐ญ.-mfsrra,-mno-fsrraโ ๐ Same vibe, but for thefsrrainstruction used in reciprocal square root approximations.-mfsrrahas to be paired with-funsafe-math-optimizationsand-ffinite-math-onlyโจ. It's enabled by default for SH4A.-mno-fsrradisables the reciprocal square root approximations even when both of those flags are in effect ๐ .-mpretend-cmoveโ ๐ธ Prefers zero-displacement conditional branches for conditional move instruction patterns. This can lead to 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 that the Solaris assembler generates. This is only needed when object files use ISA extensions the current machine doesn't support, but the code checks at runtime whether or not to use them ๐.-mimpure-textโ ๐ Used alongside-shared, this tells the compiler not to pass-z textto the linker when it's linking a shared object. With it, you can link position-dependent code into a shared object ๐.
โ ๏ธ-mimpure-textsilences the "relocations remain against allocatable but non-writable sections" linker error message. BUT the necessary relocations trigger copy-on-write, so the shared object is not actually shared across processes ๐ญ. Instead of reaching for-mimpure-text, compile all your source code with-fpicor-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โ ๐-mapp-regsmakes the output use global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications. Just like global register 1, each of global registers 2 through 4 is then treated as an allocable register that gets clobbered by function calls. This is the default โจ.
If you want to be fully SVR4 ABI-compliant (with a bit of a performance hit), specify -mno-app-regs ๐
. You should compile libraries and system software with this option ๐ง.
-mflat,-mno-flatโ ๐ With-mflat, the compiler skips the save/restore instructions and uses a "flat" or single register window model. This model is compatible with the regular register window model ๐ซง. The local registers and the input registers (0--5) are still treated as "call-saved" registers and get saved on the stack as needed.
With -mno-flat (the default), the compiler generates save/restore instructions, except for leaf functions. This is the normal operating mode ๐.
-mfpu,-mhard-floatโ ๐ฅ Generates output containing floating-point instructions. This is the default ๐ .-mno-fpu,-msoft-floatโ ๐ Generates output containing library calls for floating point instead.
โ ๏ธ Warning, bestie: the requisite libraries are not available for all SPARC targets ๐ญ. Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation ๐ ๏ธ. 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 the whole program with this option ๐. You also 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 ๐ข. So -msoft-quad-float is the default, periodt ๐
.
-mno-unaligned-doubles,-munaligned-doublesโ ๐-mno-unaligned-doublesassumes that doubles have 8-byte alignment. This is the default โจ.
With -munaligned-doubles, GCC only assumes doubles have 8-byte alignment if they're contained in another type or if they have an absolute address. Otherwise it assumes they have 4-byte alignment ๐ฆ. Specifying this option avoids some rare compatibility problems with code generated by other compilers. It isn't the default because it results in a performance loss, especially for floating-point code ๐.
-muser-mode,-mno-user-modeโ ๐ก๏ธ-mno-user-modemeans don't generate code that can only run in supervisor mode. This is only relevant for thecasainstruction emitted for the LEON3 processor ๐ง.-mno-user-modeis the default.-mfaster-structs,-mno-faster-structsโ ๐๏ธ With-mfaster-structs, the compiler assumes structures should have 8-byte alignment. This enables the use of pairs oflddandstdinstructions for copies in structure assignment, instead of twice as manyldandstpairs ๐ธ. But this changed alignment directly violates the SPARC ABI, so it's only meant for targets where the developer acknowledges their resulting code isn't directly in line with the ABI rules ๐.-mstd-struct-return,-mno-std-struct-returnโ ๐ With-mstd-struct-return, the compiler generates checking code in functions returning structures or unions. That checking detects size mismatches between the two sides of function calls, as per the 32-bit ABI ๐.
The default is -mno-std-struct-return. This option has no effect in 64-bit mode ๐
.
-mlra,-mno-lraโ ๐งฉ Enables Local Register Allocation. This has been the default for SPARC since GCC 7, so you need to pass-mno-lraif you want the old Reload ๐ฐ๏ธ.-mcpu=cpu_typeโ ๐ง Sets the instruction set, register set, and instruction scheduling parameters for machine type cpu_type. 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 selects the best architecture option for the host processor ๐ซถ. -mcpu=native has no effect if GCC doesn't recognize the processor ๐.
The default instruction scheduling parameters get used for the values that select an architecture and not an implementation. Those are v7, v8, sparclite, sparclet, and v9 ๐.
Here's the lowdown on each supported architecture and its supported implementations ๐:
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3,leon5sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of the SPARC architecture ๐ฆ. With -mcpu=cypress, the compiler additionally optimizes it for the Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series. This is also appropriate for the older SPARCStation 1, 2, IPX etc. ๐ฅ๏ธ
With -mcpu=v8, GCC generates code for the V8 variant 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 additionally optimizes it 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, which exist in SPARClite but not in SPARC-V7. With -mcpu=f930, the compiler additionally optimizes it for the Fujitsu MB86930 chip, which is the original SPARClite, with no FPU ๐ธ. With -mcpu=f934, the compiler additionally optimizes it for the Fujitsu MB86934 chip, which is the more recent SPARClite with FPU ๐.
With -mcpu=sparclet, GCC generates code for the SPARClet variant of the SPARC architecture ๐ฆ. That adds the integer multiply, multiply/accumulate, integer divide step, and scan ("ffs") instructions, which 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 โจ That adds 64-bit integer and floating-point move instructions, 3 extra floating-point condition code registers, and conditional move instructions. The -mcpu values below each add an extra layer of optimization for a specific chip ๐ฅ
-mcpu=ultrasparcโ optimizes for the Sun UltraSPARC I/II/IIi chips ๐ธ-mcpu=ultrasparc3โ optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips ๐ธ-mcpu=niagaraโ optimizes for Sun UltraSPARC T1 chips ๐-mcpu=niagara2โ optimizes for Sun UltraSPARC T2 chips ๐-mcpu=niagara3โ optimizes for Sun UltraSPARC T3 chips ๐-mcpu=niagara4โ optimizes for Sun UltraSPARC T4 chips ๐-mcpu=niagara7โ optimizes for Oracle SPARC M7 chips ๐-mcpu=m8โ optimizes for Oracle M8 chips ๐-mtune=cpu_typeโ sets the instruction scheduling parameters for the machine typecpu_type, but unlike-mcpu=cpu_type, it does not change the instruction set or register set ๐ง
The same values that work for -mcpu=cpu_type also work for -mtune=cpu_type, but the only really useful ones are the values that pick a specific CPU implementation: 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, you can also use native ๐ซถ
-mv8plus,-mno-v8plusโ with-mv8plus, GCC generates code for the SPARC-V8+ ABI ๐ The big difference from V8 is that the global and out registers count as 64 bits wide. This is on by default on Solaris in 32-bit mode for all SPARC-V9 processors โจ-mvis,-mno-visโ with-mvis, GCC uses the UltraSPARC Visual Instruction Set extensions ๐ฆ The default is-mno-vis.-mvis2,-mno-vis2โ with-mvis2, GCC uses version 2.0 of the UltraSPARC Visual Instruction Set extensions. The default is-mvis2when you target a CPU that supports those instructions, like UltraSPARC-III and later. Setting-mvis2also sets-mvis๐-mvis3,-mno-vis3โ with-mvis3, GCC uses version 3.0 of the UltraSPARC Visual Instruction Set extensions. The default is-mvis3when you target a CPU that supports those instructions, like niagara-3 and later. Setting-mvis3also sets-mvis2and-mvis๐-mvis4,-mno-vis4โ with-mvis4, GCC uses version 4.0 of the UltraSPARC Visual Instruction Set extensions. The default is-mvis4when you target a CPU that supports those instructions, like niagara-7 and later. Setting-mvis4also sets-mvis3,-mvis2, and-mvis๐ฅ-mvis4b,-mno-vis4bโ with-mvis4b, GCC uses 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 you target a CPU that supports those instructions, like m8 and later. Setting-mvis4balso sets-mvis4,-mvis3,-mvis2, and-mvis๐ญ-mcbcond,-mno-cbcondโ with-mcbcond, GCC uses the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ The default is-mcbcondwhen you target a CPU that supports them, like Niagara-4 and later.-mfmaf,-mno-fmafโ with-mfmaf, GCC uses the UltraSPARC Fused Multiply-Add Floating-point instructions ๐ธ The default is-mfmafwhen you target a CPU that supports them, like Niagara-3 and later.-mfsmuld,-mno-fsmuldโ with-mfsmuld, GCC uses the Floating-point Multiply Single to Double (FsMULd) instruction ๐ง The default is-mfsmuldwhen you target a CPU that supports the V8 or V9 architecture versions with an FPU, except-mcpu=leon.-mpopc,-mno-popcโ with-mpopc, GCC uses the UltraSPARC Population Count instruction ๐ The default is-mpopcwhen you target a CPU that supports it, like Niagara-2 and later.-msubxc,-mno-subxcโ with-msubxc, GCC uses the UltraSPARC Subtract-Extended-with-Carry instruction ๐ The default is-msubxcwhen you target a CPU that supports it, like Niagara-7 and later.-mfix-at697fโ turns on the documented workaround for the single erratum of the Atmel AT697F processor (which is erratum #13 of the AT697E processor) ๐ ๏ธ-mfix-ut699โ turns on the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor ๐ ๏ธ-mfix-ut700โ turns on the documented workaround for the back-to-back store errata of the UT699E/UT700 processor ๐ ๏ธ-mfix-gr712rcโ turns on the documented workaround for the back-to-back store errata of the GR712RC processor ๐ ๏ธ
These -m options are also supported on SPARC-V9 processors in 64-bit environments ๐
-m32,-m64โ generates code for a 32-bit or 64-bit environment. The 32-bit environment setsint,long, and 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 each be less than 2GB in size, and the data segment must be located within 2GB of the text segment ๐medanyโ the Medium/Anywhere code model: 64-bit addresses, and programs can be linked anywhere in memory. The text and data segments must each be less than 2GB in size, and the data segment must be located within 2GB of the text segment โจembmedanyโ the Medium/Anywhere code model for embedded systems: 64-bit addresses, and the text and data segments must each be less than 2GB in size, both starting anywhere in memory (determined at link time). The global register%g4points to the base of the data segment. Programs are statically linked, and PIC is not supported ๐ค
-mmemory-model=mem-modelโ sets the memory model the processor uses to one of these:defaultโ the default memory model for the processor and operating system ๐rmoโ Relaxed Memory Order ๐psoโ Partial Store Order ๐tsoโ Total Store Order ๐scโ Sequential Consistency ๐
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, and they get set in the processor's "PSTATE.MM" field ๐
-mstack-bias,-mno-stack-biasโ with-mstack-bias, GCC assumes the stack pointer (and the frame pointer, if there is one) is offset by-2047, which must be added back when making stack frame references. This is the default in 64-bit mode. Otherwise, GCC assumes there's no such offset ๐ญ
Options for System V
These extra options are available on System V Release 4 so they match other compilers on those systems ๐ง
-Gโ creates a shared object. It's recommended to use-symbolicor-sharedinstead ๐-Qyโ identifies the version of each tool the compiler used, and puts that info in a".ident"assembler directive in the output ๐ซถ-Qnโ stops adding".ident"directives to the output file (this is the default) ๐ซถ-YP,dirsโ searches the directoriesdirs, and no others, for libraries specified with-l๐-Ym,dirโ looks in the directorydirto find the M4 preprocessor. The assembler uses this option ๐
TILE-Gx Options
These -m options are supported on the TILE-Gx โจ
-mcmodel=smallโ generates code for the small model. The distance for direct calls is limited to 500M in either direction. PC-relative addresses are 32 bits, and absolute addresses support the full address range ๐ฆ-mcmodel=largeโ generates code for the large model. There's no limitation on call distance, PC-relative addresses, or absolute addresses ๐-mcpu=nameโ selects the type of CPU 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 to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits ๐-mbig-endian,-mlittle-endianโ generates code in big-endian or little-endian mode, respectively ๐
TILEPro Options
These -m options are supported on the TILEPro ๐ธ
-mcpu=nameโ selects the type of CPU to target. Right now, the only supported type istilepro๐-m32โ generates code for a 32-bit environment, which setsint,long, and pointer to 32 bits. This is the only supported behavior, so the flag is basically ignored ๐
V850 Options
These -m options are defined for V850 implementations ๐
-mlong-calls,-mno-long-callsโ treats all calls as being far away (or near). If calls are assumed to be far away, the compiler always loads the function's address into a register and calls indirectly through the pointer ๐ฅ-mno-ep,-mepโ-mno-epstops optimizing basic blocks that use the same index pointer 4 or more times to copy the pointer into the"ep"register, and-mepdoes that optimization. That optimization also lets the compiler use the shorter"sld"and"sst"instructions. The-mepoption is on by default if you optimize ๐ง-mno-prolog-function,-mprolog-functionโ ๐ Okay so-mno-prolog-functiontells GCC to not call external helper functions for saving and restoring registers in the prologue and epilogue of a function, while-mprolog-functiontells it to use them โจ. The helpers are slower, but they take up less code space when more than one function saves the same number of registers.-mprolog-functionis on by default if you optimize ๐ฅ.-mspaceโ ๐ง Tries to make the code as small as possible. Right now that just turns on-mepand-mprolog-function๐ธ.-mtda=nโ ๐ Puts static or global variables that arenbytes or less into the tiny data area that theepregister points to. The tiny data area holds up to 256 bytes total (128 bytes for byte references) ๐ค.-msda=nโ ๐ Puts static or global variables that arenbytes or less into the small data area that thegpregister points to. That small data area can hold up to 64 kilobytes โจ.-mzda=nโ ๐ฆ Puts static or global variables that arenbytes or less into the first 32 kilobytes of memory.-mv850โ ๐ Says the target processor is the V850.-mv850e3v5โ ๐ฅ Says the target processor is the V850E3V5. The preprocessor constant__v850e3v5__gets defined if you use this one.-mv850e2v4โ ๐ Says the target processor is the V850E3V5 (yep, that's what it says). It's an alias for-mv850e3v5.-mv850e2v3โ ๐ซถ Says the target processor is the V850E2V3. The preprocessor constant__v850e2v3__gets defined if you use this one.-mv850e2โ ๐ Says the target processor is the V850E2. The preprocessor constant__v850e2__gets defined if you use this one.-mv850e1โ ๐ Says the target processor is the V850E1. The preprocessor constants__v850e1__and__v850e__both get defined if you use this one.-mv850esโ ๐ธ Says the target processor is the V850ES. It's an alias for-mv850e1.-mv850eโ โจ Says the target processor is the V850E. The preprocessor constant__v850e__gets defined if you use this one.
If none of -mv850, -mv850e, -mv850e1, -mv850e2, -mv850e2v3 or -mv850e3v5 are set, GCC just picks a default target processor for you and defines the matching __v850*__ preprocessor constant ๐ง.
The preprocessor constants __v850 and __v851__ are always defined, no matter which processor variant you're targeting ๐
.
-mdisable-callt,-mno-disable-calltโ ๐ This one suppresses generation of theCALLTinstruction for the v850e, v850e1, v850e2, v850e2v3 and v850e3v5 flavors of the v850 architecture. It's 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, the C preprocessor symbol__V850_CALLT__gets 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 only matters when the target architecture is V850E2V3 or higher. If hardware floating point instructions are being generated, the C preprocessor symbol__FPU_OK__gets defined. Otherwise the symbol__NO_FPU__gets defined.-mloopโ ๐ง Enables the use of the e3v5LOOPinstruction. It's not enabled by default when the e3v5 architecture is selected, because its use is still experimental ๐.-mrh850-abi,-mghsโ ๐ Enables support for the RH850 version of the V850 ABI. This is the default. With this version of the ABI, the following rules apply:- Integer sized structures and unions are returned via a memory pointer rather than a register.
- Large structures and unions (more than 8 bytes in size) are passed by value.
- Functions are aligned to 16-bit boundaries.
- The
-m8byte-aligncommand-line option is supported. - The
-mdisable-calltcommand-line option is enabled by default. The-mno-disable-calltcommand-line option is not supported.
When this version of the ABI is enabled, the C preprocessor symbol __V850_RH850_ABI__ gets defined ๐.
-mgcc-abiโ ๐ธ Enables support for the old GCC version of the V850 ABI. With this version of the ABI, the following rules apply:- Integer sized structures and unions are returned in register
r10. - Large structures and unions (more than 8 bytes in size) are passed by reference.
- Functions are aligned to 32-bit boundaries, unless optimizing for size.
- The
-m8byte-aligncommand-line option is not supported. - The
-mdisable-calltcommand-line option is supported but not enabled by default.
- Integer sized structures and unions are returned in register
When this version of the ABI is enabled, the C preprocessor symbol __V850_GCC_ABI__ gets defined ๐.
-m8byte-align,-mno-8byte-alignโ ๐ Enables support fordoubleandlong longtypes to be aligned on 8-byte boundaries. By default, the alignment of all objects is restricted to at most 4 bytes. When-m8byte-alignis in effect, the C preprocessor symbol__V850_8BYTE_ALIGN__gets defined โจ.-mbig-switchโ ๐ซถ Generates code suitable for big switch tables. Only use this if the assembler or linker complains about out of range branches within a switch table ๐ญ.-mapp-regsโ ๐ Makes the compiler user2andr5in the code it generates. This is the default.-mno-app-regsโ ๐ Makesr2andr5get treated as fixed registers.
๐ฆ VAX Options ๐ฆ
These -m options are defined for the VAX:
-munixโ ๐ธ Doesn't output certain jump instructions (aobleqand so on) that the Unix assembler for the VAX can't handle across long ranges.-mgnuโ ๐ง Does output those jump instructions, on the assumption that the GNU assembler is being used.-mgโ ๐ Outputs code for G-format floating-point numbers instead of D-format.
๐ Visium Options ๐
-mdebugโ ๐ฅ A program that does file I/O and is destined to run on an MCM target should be linked with this option. It causes the librarieslibc.aandlibdebug.ato be linked. The program should be run on the target under the control of the GDB remote debugging stub ๐.-msimโ ๐ฆ A program that does file I/O and is destined to run on the simulator should be linked with the option. This causes the librarieslibc.aandlibsim.ato be linked.-mfpu,-mhard-floatโ โญ Generates code containing floating-point instructions. This is the default.-mno-fpu,-msoft-floatโ ๐ Generates code containing library calls for floating-point.
โ ๏ธ-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile all of a program with this option. In particular, you need to compilelibgcc.a, the library that comes with GCC, with-msoft-floatfor this to work ๐.
-mcpu=cpu_typeโ ๐ Sets the instruction set, register set, and instruction scheduling parameters for machine typecpu_type. Supported values forcpu_typearemcm,gr5andgr6.mcmis a synonym ofgr5, kept around for backward compatibility ๐ธ.- By default (unless configured otherwise), GCC generates code for the GR5 variant of the Visium architecture โจ.
- With
-mcpu=gr6, GCC generates code for the GR6 variant of the Visium architecture. The only difference from GR5 code is that the compiler will generate block move instructions ๐ง.
-mtune=cpu_typeโ ๐ Sets the instruction scheduling parameters for machine typecpu_type, but doesn't set the instruction set or register set that-mcpu=cpu_typewould.-msv-modeโ ๐ซถ Generates code for supervisor mode, where there are no restrictions on access to general registers. This is the default.-muser-modeโ ๐ Generates code for user mode, where access to some general registers is forbidden. On the GR5, registersr24tor31can't be accessed in this mode. On the GR6, only registersr29tor31are affected.
๐ธ VMS Options ๐ธ
These -m options are defined for the VMS implementations:
-mvms-return-codesโ ๐ Returns VMS condition codes frommain. The default is to return POSIX-style condition (e.g. error) codes.-mdebug-main=prefixโ ๐ฅ Flags the first routine whose name starts withprefixas the main routine for the debugger.-mmalloc64โ ๐ Defaults to 64-bit memory allocation routines.-mpointer-size=sizeโ ๐ฆ Sets the default size of pointers. Possible options forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers. Thenooption disablespragma pointer_size๐.
๐ VxWorks Options ๐
The options in this section are defined for all VxWorks targets. Options specific to the target hardware are listed with the other options for that target ๐ง.
-mrtpโ ๐ 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 rather than static libraries. The options-staticand-sharedcan also be used for RTPs, and-staticis the default ๐ซถ.-Bstatic,-Bdynamicโ ๐ These options are passed down to the linker. They're defined for compatibility with Diab ๐.-Xbind-lazyโ โญ Enables lazy binding of function calls. This option is equivalent to-Wl,-z,nowand is defined for compatibility with Diab ๐ฅ.-Xbind-nowโ ๐ธ Disables lazy binding of function calls. This option is the default and is defined for compatibility with Diab ๐ .
๐ฆ x86 Options ๐ฆ
These -m options are defined for the x86 family of computers.
-march=cpu-typeโ ๐ Generates instructions for the machine 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 indicated. Specifying-march=cpu-typeimplies-mtune=cpu-type, except where noted otherwise ๐ง.
๐ Real talk, bestie: with -march=cpu-type, the code may not run at all on processors other than the one you named ๐ญ.
The choices for cpu-type are:
native: Okay bestie, this is the "just use whatever my laptop has" option ๐ปโจ GCC checks the processor of the machine doing the compiling and generates code for that CPU.-march=nativeturns on every instruction subset the local machine supports, so the result might not run on other machines ๐ญ-mtune=nativeoptimizes the code for the local machine, but it still stays within the limits of the selected instruction set ๐x86-64: A generic CPU with 64-bit extensions ๐ธx86-64-v2,x86-64-v3,x86-64-v4: These pick the matching micro-architecture level from the x86-64 psABI, so they're giving standardized feature sets ๐ฆ 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 values don't have a matching -mtune setting, using -march with them turns on 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, the OG ๐i486: Intel i486 CPU. (No scheduling is implemented for this chip ๐)i586,pentium: Intel Pentium CPU with no MMX support ๐lakemont: Intel Lakemont MCU, based on the Intel Pentium CPU ๐คpentium-mmx: Intel Pentium MMX CPU, based on the Pentium core with MMX instruction set support โจpentiumpro: Intel Pentium Pro CPU ๐ฅi686: When used with-march, this uses the Pentium Pro instruction set, so the code runs on all i686 family chips ๐ When used with-mtune, it means the same thing asgeneric.pentium2: Intel Pentium II CPU, based on the Pentium Pro core with MMX instruction set support ๐pentium3,pentium3m: Intel Pentium III CPU, based on the Pentium Pro core with MMX and SSE instruction set support ๐pentium-m: Intel Pentium M, the low-power version of the Intel Pentium III CPU with MMX, SSE and SSE2 instruction set support. This is what Centrino notebooks used ๐ปpentium4,pentium4m: 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: Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support โญnehalem: Intel Nehalem CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and POPCNT instruction set support ๐ซถwestmere: Intel Westmere CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES and PCLMUL instruction set support ๐งsandybridge: 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: 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: 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: 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: 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: Intel Bonnell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support ๐ธsilvermont: 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: 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: 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: 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: 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: 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: 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: 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: Intel Icelake Client 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, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES instruction set support ๐ซถicelake-server: Intel Icelake 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, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES, PCONFIG and WBNOINVD instruction set support ๐cascadelake: 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: Intel cooperlake 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 and AVX512BF16 instruction set support ๐tigerlake: Intel Tigerlake 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, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT and KEYLOCKER instruction set support โจsapphirerapids: Intel sapphirerapids CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW, AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2 VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI and AVX512BF16 instruction set support ๐ฅalderlake: Intel Alderlake 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, 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, rocking 64-bit extensions plus a full buffet: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,VPCLMULQDQandVAESinstruction set support. ๐งk6โ ๐ธ AMD K6 withMMXsupport. Classic. ๐ฆk6-2,k6-3โ ๐ Upgraded AMD K6 chips withMMXand3DNow!support. Glow-up energy. โจathlon,athlon-tbirdโ ๐ฅ AMD Athlon withMMX,3dNOW!, enhanced3DNow!and SSE prefetch instructions. Lowkey iconic. ๐athlon-4,athlon-xp,athlon-mpโ ๐ Improved AMD Athlon withMMX,3DNow!, enhanced3DNow!and full SSE instruction set support. The sequel that ate. ๐ฅk8,opteron,athlon64,athlon-fxโ ๐ Processors built on the AMD K8 core with x86-64 instruction set support, covering the AMD Opteron, Athlon 64 and Athlon 64 FX chips. Ngl this one supersets (aka includes all of)MMX,SSE,SSE2,3DNow!, enhanced3DNow!and 64-bit instruction set extensions. ๐k8-sse3,opteron-sse3,athlon64-sse3โ โญ Upgraded AMD K8 cores withSSE3support. ๐ซถamdfam10,barcelonaโ ๐ฆ CPUs built on AMD Family 10h cores with x86-64 instruction set support. This one supersetsMMX,SSE,SSE2,SSE3,SSE4A,3DNow!, enhanced3DNow!,ABMand 64-bit instruction set extensions. ๐bdver1โ ๐ฅ AMD Family 15h cores with x86-64 instruction set support. It supersetsFMA4,AVX,XOP,LWP,AES,PCLMUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions. ๐bdver2โ ๐ธ AMD Family 15h core based CPUs with x86-64 instruction set support. It supersetsBMI,TBM,F16C,FMA,FMA4,AVX,XOP,LWP,AES,PCLMUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions. ๐ฆbdver3โ ๐ AMD Family 15h core based CPUs with x86-64 instruction set support. It supersetsBMI,TBM,F16C,FMA,FMA4,FSGSBASE,AVX,XOP,LWP,AES,PCLMUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions. ๐bdver4โ ๐ฅ AMD Family 15h core based CPUs with x86-64 instruction set support. It supersetsBMI,BMI2,TBM,F16C,FMA,FMA4,FSGSBASE,AVX,AVX2,XOP,LWP,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions. ๐znver1โ ๐ง AMD Family 17h core based CPUs with x86-64 instruction set support. It supersetsBMI,BMI2,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT, and 64-bit instruction set extensions. ๐znver2โ ๐ AMD Family 17h core based CPUs with x86-64 instruction set support. It supersetsBMI,BMI2,CLWB,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT,RDPID,WBNOINVD, and 64-bit instruction set extensions. โจznver3โ ๐ฆ AMD Family 19h core based CPUs with x86-64 instruction set support. It supersetsBMI,BMI2,CLWB,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT,RDPID,WBNOINVD,PKU,VPCLMULQDQ,VAES, and 64-bit instruction set extensions. ๐ธznver4โ ๐ AMD Family 19h core based CPUs with x86-64 instruction set support. It supersetsBMI,BMI2,CLWB,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT,RDPID,WBNOINVD,PKU,VPCLMULQDQ,VAES,AVX512F,AVX512DQ,AVX512IFMA,AVX512CD,AVX512BW,AVX512VL,AVX512BF16,AVX512VBMI,AVX512VBMI2,AVX512VNNI,AVX512BITALG,AVX512VPOPCNTDQ,GFNIand 64-bit instruction set extensions. ๐ฅbtver1โ ๐ซถ CPUs built on AMD Family 14h cores with x86-64 instruction set support. It supersetsMMX,SSE,SSE2,SSE3,SSSE3,SSE4A,CX16,ABMand 64-bit instruction set extensions. ๐btver2โ ๐ CPUs built on AMD Family 16h cores with x86-64 instruction set support. This includesMOVBE,F16C,BMI,AVX,PCLMUL,AES,SSE4.2,SSE4.1,CX16,ABM,SSE4A,SSSE3,SSE3,SSE2,SSE,MMXand 64-bit instruction set extensions. ๐winchip-c6โ ๐ง IDT WinChip C6 CPU, handled the same way as i486, plus extraMMXinstruction set support. ๐ธwinchip2โ ๐ธ IDT WinChip 2 CPU, handled the same way as i486, plus extraMMXand3DNow!instruction set support. ๐ฆc3โ ๐ VIA C3 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.) ๐c3-2โ ๐ VIA C3-2 (Nehemiah/C5XL) CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.) ๐c7โ ๐ VIA C7 (Esther) CPU withMMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) ๐samuel-2โ ๐ VIA Eden Samuel 2 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.) ๐nehemiahโ ๐ VIA Eden Nehemiah CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.) ๐estherโ ๐ VIA Eden Esther CPU withMMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) ๐eden-x2โ ๐ VIA Eden X2 CPU with x86-64,MMX,SSE,SSE2andSSE3instruction 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,AVXandAVX2instruction set support. (No scheduling is implemented for this chip.) ๐nanoโ ๐ Generic VIA Nano CPU with x86-64,MMX,SSE,SSE2,SSE3andSSSE3instruction set support. (No scheduling is implemented for this chip.) ๐nano-1000โ ๐ VIA Nano 1xxx CPU with x86-64,MMX,SSE,SSE2,SSE3andSSSE3instruction set support. (No scheduling is implemented for this chip.) ๐nano-2000โ ๐ VIA Nano 2xxx CPU with x86-64,MMX,SSE,SSE2,SSE3andSSSE3instruction set support. (No scheduling is implemented for this chip.) ๐nano-3000โ ๐ VIA Nano 3xxx CPU with x86-64,MMX,SSE,SSE2,SSE3,SSSE3andSSE4.1instruction set support. (No scheduling is implemented for this chip.) ๐nano-x2โ ๐ VIA Nano Dual Core CPU with x86-64,MMX,SSE,SSE2,SSE3,SSSE3andSSE4.1instruction set support. (No scheduling is implemented for this chip.) ๐nano-x4โ ๐ VIA Nano Quad Core CPU with x86-64,MMX,SSE,SSE2,SSE3,SSSE3andSSE4.1instruction set support. (No scheduling is implemented for this chip.) ๐geodeโ ๐ง AMD Geode embedded processor withMMXand3DNow!instruction set support. ๐
โจ -mtune=cpu-type โจ
Tune cpu-type everything applicable about the generated code, except for the ABI and the set of available instructions. Picking a specific cpu-type schedules things perfectly for that chip, but the compiler won't generate any code that can't run on the default machine type unless you use a -march=cpu-type option. ๐ซถ For example, if GCC is configured for i686-pc-linux-gnu, then -mtune=pentium4 generates code tuned for Pentium 4 that still runs on i686 machines. ๐
The choices for cpu-type are the same as for -march. On top of that, -mtune supports 2 extra choices for cpu-type:
๐ generic
Produce code optimized for the most common IA32/AMD64/EM64T processors. If you know the CPU your code will run on, use the matching -mtune or -march option instead of -mtune=generic. But if you don't know exactly what CPU your users will have, this is the one to use. ๐ฆ
As new processors hit the market, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generated by this option will shift to match whatever processors are most common when that version of GCC is released. ๐ฅ
There is no -march=generic option, because -march is about the instruction set the compiler can use, and there's no generic instruction set that works on every processor. -mtune, on the other hand, is about the processor (or, in this case, the collection of processors) the code is optimized for. ๐
๐ intel
Produce code optimized for the most current Intel processors, which are Haswell and Silvermont for this version of GCC. If you know the CPU your code will run on, use the matching -mtune or -march option instead of -mtune=intel. But if you want your application to perform better on both Haswell and Silvermont, this is your option. ๐
As new Intel processors get deployed, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generated by this option will shift to reflect the most current Intel processors at the time that version of GCC 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 on every processor. -mtune, on the other hand, is about the processor (or, in this case, the collection of processors) the code is optimized for. ๐ซถ
-mcpu=cpu-typeโ okay so this one is just a synonym for-mtune, but it's deprecated ๐ it's on its way out, bestie ๐ฅ-mfpmath=unitโ this decides how the floating-point math gets done ๐งฎโจ Theunityou pick can be one of these:387โ uses the standard 387 floating-point coprocessor that's on most chips, and gets emulated if it's missing ๐ฆ Code built with this runs basically everywhere, but the temporary results are computed in 80-bit precision instead of the precision the type asks for, so your numbers can come out a little different from most other chips. Check out-ffloat-storefor the full tea on that ๐ต This is the default choice for non-Darwin x86-32 targets.sseโ uses the scalar floating-point instructions from the SSE instruction set ๐ It's on Pentium III and newer chips, plus the AMD Athlon-4, Athlon XP, and Athlon MP chips. The earlier SSE version only handles single-precision math, so double and extended-precision math still go through 387 ๐ A later version, found only on Pentium 4 and AMD x86-64 chips, can do double-precision math too. For the x86-32 compiler, you have to use-march=cpu-type,-msse, or-msse2to turn on the SSE extensions and make this option actually work ๐ซ For the x86-64 compiler, those extensions are on by default. The result should be way faster in most cases and dodge the numerical instability problems of 387 code ๐ but it might break existing code that expects temporaries to be 80 bits. This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and for x86-32 targets with the SSE2 instruction set when-ffast-mathis enabled ๐sse,387,sse+387,bothโ tries to use both instruction sets at the same time ๐คน This effectively doubles the number of available registers, and on chips with separate execution units for 387 and SSE, it doubles those execution resources too. Use it with care ๐ฅบ It's still experimental, because the GCC register allocator doesn't model separate functional units very well, which means the performance can be unstable ๐ข
-masm=dialectโ picks the assembly dialect for the assembly instructions GCC outputs ๐ It also affects which dialect is used for basicasmand extendedasm. The supported choices, in dialect order, areattorintel. The default isatt. Darwin does not supportintel๐๐ซ-mieee-fp,-mno-ieee-fpโ controls whether the compiler uses IEEE floating-point comparisons ๐ These ones correctly handle the case where the result of a comparison is unordered ๐ง-m80387,-mhard-floatโ generates output that contains 80387 instructions for floating point ๐ฅ-mno-80387,-msoft-floatโ generates output that contains library calls for floating point instead ๐
Warning: the requisite libraries are NOT part of GCC ๐ญ Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation ๐ ๏ธ
On machines where a function returns floating-point results in the 80387 register stack, some floating-point opcodes may still get emitted even if -msoft-float is used ๐
-mno-fp-ret-in-387โ doesn't use the FPU registers for function return values ๐ โโ๏ธ The usual calling convention has functions returnfloatanddoublevalues in an FPU register, even if there's no FPU at all. The idea is that the operating system should emulate an FPU ๐ง Using-mno-fp-ret-in-387makes those values come back in ordinary CPU registers instead.-mno-fancy-math-387โ some 387 emulators don't support thesin,cos, andsqrtinstructions for the 387 ๐ Use this to avoid generating those instructions. It gets overridden when-marchsays the target CPU always has an FPU, because then the instruction doesn't need emulating ๐ Also, these instructions aren't generated unless you use the-funsafe-math-optimizationsswitch too.-malign-double,-mno-align-doubleโ controls whether GCC alignsdouble,long double, andlong longvariables on a two-word boundary or a one-word boundary ๐ Aligningdoublevariables on a two-word boundary gives code that runs somewhat faster on a Pentium, but it costs more memory ๐พ On x86-64,-malign-doubleis enabled by default.
Warning: if you use -malign-double, structures containing the types above get aligned differently than the published x86-32 application binary interface specs say ๐ฑ They won't be binary compatible with structures in code compiled without that switch.
-m96bit-long-double,-m128bit-long-doubleโ these control the size of thelong doubletype ๐ The x86-32 application binary interface says the size is 96 bits, so-m96bit-long-doubleis the default in 32-bit mode. Modern architectures (Pentium and newer) preferlong doubleto be aligned to an 8- or 16-byte boundary, but inside arrays or structures that follow the ABI, that isn't possible ๐ So-m128bit-long-doublealignslong doubleto a 16-byte boundary by padding it with an extra 32-bit zero ๐ธ In the x86-64 compiler,-m128bit-long-doubleis the default, since its ABI sayslong doubleis aligned on a 16-byte boundary. Heads up that neither of these options gives any extra precision over the x87 standard of 80 bits for along doubleโจ
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, and it also modifies the function calling convention for functions that takelong double. So they're not binary-compatible with code compiled without that switch ๐จ
-mlong-double-64,-mlong-double-80,-mlong-double-128โ these control the size of thelong doubletype too ๐ A size of 64 bits makeslong doubleequivalent todouble, and that's the default for the 32-bit Bionic C library. A size of 128 bits makeslong doubleequivalent 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, and it also modifies the function calling convention for functions that takelong double. So they're not binary-compatible with code compiled without that switch ๐จ
-malign-data=typeโ controls how GCC aligns variables ๐ฆ The supported values fortypeare:compatโ uses an increased alignment value that's compatible with GCC 4.8 and earlier. This is the default ๐ซถabiโ uses the alignment value specified by the psABI ๐cachelineโ uses an increased alignment value to match the cache line size ๐ง
-mlarge-data-threshold=thresholdโ when-mcmodel=mediumis specified, data objects bigger thanthresholdget placed in the large data section ๐ This value has to be the same across all objects linked into the binary, and it defaults to65535๐ข-mrtdโ switches to a different function-calling convention ๐ In this one, functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments as they return. That saves one instruction in the caller, since the caller doesn't need to pop the arguments anymore ๐งน You can give a single function this calling sequence with the function attributestdcall, and you can override-mrtdfor a function with the function attributecdecl.
Warning: this calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler ๐ โโ๏ธ
Warning: you must provide function prototypes for all functions that take a variable number of arguments (including printf), or incorrect code gets generated for calls to those functions ๐ซ
Warning: seriously incorrect code results if you call a function with too many arguments. Normally extra arguments are harmlessly ignored, but not with this one ๐
-mregparm=numโ controls how many registers get used to pass integer arguments ๐ฏ By default, no registers are used to pass arguments, and at most 3 registers can be used. You can control this for a specific function with the function attributeregparm.
Warning: if you use this switch and num is nonzero, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐งฑ
-msseregparmโ uses SSE register passing conventions forfloatanddoublearguments and return values โก You can control this for a specific function with the function attributesseregparm.
Warning: if you use this switch, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐งฑ
-mvect8-ret-in-memโ returns 8-byte vectors in memory instead of MMX registers ๐ง This is the default on VxWorks, so it matches the ABI of the Sun Studio compilers up until version 12. Only use this option if you need to stay compatible with existing code made by those older compiler versions or older versions of GCC ๐ฐ๏ธ-mpc32,-mpc64,-mpc80โ set the 80387 floating-point precision to 32, 64, or 80 bits ๐๏ธ-mpc32โ rounds the significands of floating-point results to 24 bits (single precision) ๐ฑ-mpc64โ rounds them to 53 bits (double precision) ๐ท-mpc80โ rounds them to 64 bits (extended double precision), and this one's the default ๐
When you use this option, floating-point operations in higher precisions aren't available to the programmer unless you set the FPU control word explicitly ๐ซถ
Okay so, this next chunk is where we get into the x86 stack and instruction-set switches, and bestie, the stack ones are serious ๐ซถ Pick the wrong alignment and your program can crash in ways that are super hard to trace ๐
Setting the rounding of floating-point operations below the default 80 bits can speed some programs up by 2% or more ๐ But ngl, some math libraries assume extended-precision (80-bit) floating-point operations are on by default. If you use this option to drop precision below extended, those routines could lose a ton of accuracy through so-called "catastrophic cancellation" ๐ญ Not it.
-mdaz-ftzโ This one flips the FTZ (flush-to-zero) and DAZ (denormals-are-zero) flags in the MXCSR register, which control floating-point calculations ๐ฆ SSE and AVX instructions, scalar and vector ones included, can get a speed boost when you turn these on with-mdaz-ftz. And if you say-mno-daz-ftz, GCC won't set the FTZ/DAZ flags at all ๐ โโ๏ธ-mstackrealignโ Realigns the stack at entry โจ On x86, this generates an alternate prologue and epilogue that realigns the run-time stack when it needs to. It's the glue for mixing legacy code that keeps 4-byte stack alignment with modern code that keeps 16-byte alignment for SSE compatibility ๐ You can also look at the attributeforce_align_arg_pointer, which works on individual functions.-mpreferred-stack-boundary=numโ Tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐ธ If you don't specify-mpreferred-stack-boundary, the default is4(16 bytes or 128 bits), so no stress there.
๐ Warning, bestie, this one is dangerous. When you're generating code for the x86-64 architecture with SSE extensions disabled,-mpreferred-stack-boundary=3can keep the stack boundary aligned to an 8-byte boundary. But the x86-64 ABI requires 16-byte stack alignment, so this is ABI incompatible ๐ It's only meant for a controlled environment where stack space is a seriously tight limit. It leads to wrong code when functions compiled with 16-byte stack alignment (like functions from a standard library) get called with a misaligned stack. SSE instructions may then cause misaligned memory access traps. On top of that, variable arguments get handled incorrectly for 16-byte aligned objects (including x87long doubleand__int128), which gives wrong results. You must build all modules with-mpreferred-stack-boundary=3, including any libraries, system libraries and startup modules too. No skipping!
-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, GCC uses whatever-mpreferred-stack-boundarysays.
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double) or you'll eat significant run-time performance penalties ๐ On Pentium III, the SSE data type __m128 may not work properly if it isn't 16-byte aligned ๐ฌ
To keep values properly aligned on the stack, the stack boundary has to be at least as aligned as whatever any value stored on the stack needs. Every function also has to be generated so it keeps the stack aligned. So if a function compiled with a higher preferred stack boundary calls from a function compiled with a lower one, the stack will most likely end up misaligned ๐ Libraries that use callbacks should always stick with the default setting, periodt.
This extra alignment eats extra stack space and generally makes your code bigger ๐ If you're working on something sensitive to stack usage, like embedded systems or operating system kernels, you may want to drop the preferred alignment to -mpreferred-stack-boundary=2.
- Instruction set switches โ This whole family of switches turns on the use of instructions from 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 or CLDEMOTE extended instruction sets ๐ Every one of them has a matching
-mno-option to turn that instruction use off ๐ โโ๏ธ The flags are:
-mmmx
-msse
-msse2
-msse3
-mssse3
-msse4
-msse4a
-msse4.1
-msse4.2
-mavx
-mavx2
-mavx512f
-mavx512pf
-mavx512er
-mavx512cd
-mavx512vl
-mavx512bw
-mavx512dq
-mavx512ifma
-mavx512vbmi
-msha
-maes
-mpclmul
-mclflushopt
-mclwb
-mfsgsbase
-mptwrite
-mrdrnd
-mf16c
-mfma
-mpconfig
-mwbnoinvd
-mfma4
-mprfchw
-mrdpid
-mprefetchwt1
-mrdseed
-msgx
-mxop
-mlwp
-m3dnow
-m3dnowa
-mpopcnt
-mabm
-madx
-mbmi
-mbmi2
-mlzcnt
-mfxsr
-mxsave
-mxsaveopt
-mxsavec
-mxsaves
-mrtm
-mhle
-mtbm
-mmwaitx
-mclzero
-mpku
-mavx512vbmi2
-mavx512bf16
-mgfni
-mvaes
-mwaitpkg
-mvpclmulqdq
-mavx512bitalg
-mmovdiri
-mmovdir64b
-menqcmd
-muintr
-mtsxldtrk
-mavx512vpopcntdq
-mavx512vp2intersect
-mavx5124fmaps
-mavx512vnni
-mavxvnni
-mavx5124vnniw
-mcldemote
-mserialize
-mamx-tile
-mamx-int8
-mamx-bf16
-mhreset
-mkl
-mwidekl
These extensions are also available as built-in functions, so check out x86 Built-in Functions for the details of which functions get enabled and disabled by these switches ๐ง If you want GCC to generate SSE/SSE2 instructions automatically from floating-point code (instead of 387 instructions), that's -mfpmath=sse ๐
Heads up: GCC suppresses SSEx instructions when -mavx is used. Instead, it generates new AVX instructions, or AVX equivalents for all SSEx instructions, when needed ๐ฆ
These options let GCC use those extended instructions in generated code, even without -mfpmath=sse. If your app does run-time CPU detection, you need to compile separate files for each supported architecture, using the appropriate flags ๐ซถ Specifically, the file with the CPU detection code should be compiled without these options, bestie, it's giving "keep the detector clean" energy.
-mdump-tune-featuresโ Tells GCC to dump the names of the x86 performance tuning features and their default settings ๐ You can use those names in-mtune-ctrl=feature-list.-mtune-ctrl=feature-listโ Fine-grained control over x86 code generation features ๐๏ธ The feature-list is a comma-separated list of feature names. See also-mdump-tune-features. A feature gets turned on when it's not preceded by^, and turned off when it is. This one is meant for GCC developers, so be warned: using it may lead to code paths that testing never covered, and it can potentially cause compiler ICEs or runtime errors ๐-mno-defaultโ Turns off all tunable features ๐ โโ๏ธ See also-mtune-ctrl=feature-listand-mdump-tune-features.-mcldโ Makes GCC emit acldinstruction in the prologue of functions that use string instructions ๐งต String instructions depend on the DF flag to pick between autoincrement or autodecrement mode. The ABI says DF should be cleared on function entry, but some operating systems violate that by not clearing DF in their exception dispatchers. So the exception handler can run with DF set, which means string instructions go the wrong direction ๐ญ This option can be enabled by default on 32-bit x86 targets when you configure GCC with the--enable-cldconfigure option. If you want to suppresscldgeneration in that case, use the-mno-cldcompiler option.-mvzeroupperโ Makes GCC emit avzeroupperinstruction before control flow leaves the function, which minimizes the AVX to SSE transition penalty and removes unnecessaryzeroupperintrinsics ๐งน-mprefer-avx128โ Tells GCC to use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer ๐ธ-mprefer-vector-width=optโ Tells GCC to use opt-bit vector width in instructions instead of the default on the selected platform ๐ The options are:noneโ No extra limitations are applied to GCC beyond what the selected platform defines.128โ Prefers 128-bit vector width for instructions.256โ Prefers 256-bit vector width for instructions.512โ Prefers 512-bit vector width for instructions.
-mcx16โ Lets GCC generateCMPXCHG16Binstructions in 64-bit code to do compare-and-exchange operations on 16-byte aligned 128-bit objects ๐ This is handy for atomic updates of data structures bigger than one machine word. The compiler uses this instruction to implement__syncbuiltins. However, for__atomicbuiltins operating on 128-bit integers, a library call is always used, so don't expect magic there ๐-msahfโ Enables generation ofSAHFinstructions in 64-bit code ๐ฐ Early Intel Pentium 4 CPUs with Intel 64 support, from before the Pentium 4 G1 step in December 2005, didn't have theLAHFandSAHFinstructions that AMD64 supports. These are load and store instructions, respectively, for certain status flags. In 64-bit mode, theSAHFinstruction is used to optimize thefmod,drem, andremainderbuilt-in functions. See Other Builtins for details โจ-mmovbeโ Enables use of themovbeinstruction to implement__builtin_bswap32and__builtin_bswap64๐-mshstkโ Enables the shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ก๏ธ-mcrc32โ Enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32si, and__builtin_ia32_crc32dito generate thecrc32machine instruction ๐ฆ-mmwaitโ okay so this one is the key ๐ It makes the built-in functions__builtin_ia32_monitorand__builtin_ia32_mwaitactually generate themonitorandmwaitmachine instructions โจ-mrecipโ this one is giving speed ๐จ It lets GCC useRCPSSandRSQRTSS(plus their vectorized bestiesRCPPSandRSQRTPS) with an extra Newton-Raphson step for precision, 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 bestie: the sequence has higher throughput than the non-reciprocal instruction, but its precision can drop by up to 2 ulp (i.e. the inverse of1.0equals0.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, GCC emits the sequence above with the extra Newton-Raphson step for vectorized single-float division and vectorized sqrtf(x) already with -ffast-math (or the option combination above), so -mrecip isn't needed there either ๐ซถ
-mrecip=optโ this one lets you pick exactly which reciprocal estimate instructions are allowed ๐optis a comma-separated list, and any option can be flipped by putting a!in front of it:allโ enables all estimate instructions ๐defaultโ enables the default instructions, equivalent to-mrecipnoneโ disables all estimate instructions, equivalent to-mno-recip๐divโ enables the approximation for scalar divisionvec-divโ enables the approximation for vectorized divisionsqrtโ enables the approximation for scalar square rootvec-sqrtโ enables the approximation for vectorized square root
So, for example, -mrecip=all,!sqrt enables all of the reciprocal approximations except for square root ๐ฆ
-mveclibabi=typeโ this sets the ABI type for vectorizing intrinsics using an external library ๐ Picksvmlfor the Intel short vector math library, oracmlfor the AMD math core library. To use it, both-ftree-vectorizeand-funsafe-math-optimizationshave to be enabled, and an SVML or ACML ABI-compatible library has to be specified at link time ๐
GCC currently emits calls to vmldExp2, vmldLn2, vmldLog102, vmldPow2, vmldTanh2, vmldTan2, vmldAtan2, vmldAtanh2, vmldCbrt2, vmldSinh2, vmldSin2, vmldAsinh2, vmldAsin2, vmldCosh2, vmldCos2, vmldAcosh2, vmldAcos2, vmlsExp4, vmlsLn4, vmlsLog104, vmlsPow4, vmlsTanh4, vmlsTan4, vmlsAtan4, vmlsAtanh4, vmlsCbrt4, vmlsSinh4, vmlsSin4, vmlsAsinh4, vmlsAsin4, vmlsCosh4, vmlsCos4, vmlsAcosh4 and vmlsAcos4 for the corresponding function type when -mveclibabi=svml is used, and __vrd2_sin, __vrd2_cos, __vrd2_exp, __vrd2_log, __vrd2_log2, __vrd2_log10, __vrs4_sinf, __vrs4_cosf, __vrs4_expf, __vrs4_logf, __vrs4_log2f, __vrs4_log10f and __vrs4_powf for the corresponding function type when -mveclibabi=acml is used.
-mabi=nameโ picks which calling convention to generate code for ๐ธsysvis the ABI used on GNU/Linux and other systems, andmsis 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 thems_abiandsysv_abifunction attributes ๐-mforce-indirect-callโ forces all calls to functions to be indirect ๐ง This is useful when using Intel Processor Trace, where it generates more precise timing information for function calls โฑ๏ธ-mmanual-endbrโ ENDBR gets inserted at function entry only via thecf_checkfunction attribute ๐ This is useful when used with the option-fcf-protection=branchto control ENDBR insertion at the function entry ๐ซถ-mcall-ms2sysv-xloguesโ okay this one's a bit of a lore dump ๐ Because of differences in 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function has to considerRSI,RDIandXMM6-15as clobbered. By default the code for saving and restoring 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 instead, which shrinks the 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, whilegnu2is 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 because of improved scheduling and reduced dependencies ๐ฆ-maccumulate-outgoing-argsโ if enabled, the maximum amount of space required for outgoing arguments gets computed in the function prologue ๐ง This is faster on most modern CPUs because of reduced dependencies, improved scheduling, and reduced stack usage when the preferred stack boundary is not equal to 2. The 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 it must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT; when linking, it links in a special thread helper library-lmingwthrdwhich cleans up per-thread exception-handling data โจ-mms-bitfields,-mno-ms-bitfieldsโ enables or disables bit-field layout compatible with the native Microsoft Windows compiler ๐
If packed is used on a structure, or if bit-fields are used, it may be that the Microsoft ABI lays out the structure differently than the way GCC normally does ๐ Particularly when moving packed data between functions compiled with GCC and the native Microsoft compiler (either via function call or as data in a file), it may be necessary to access either format.
This option is enabled by default for Microsoft Windows targets ๐ช This behavior can also be controlled locally by use of variable or type attributes. For more information, see x86 Variable Attributes and x86 Type Attributes.
The Microsoft structure layout algorithm is fairly simple with the exception of the bit-field packing ๐งฉ The padding and alignment of members of structures, and whether a bit-field can straddle a storage-unit boundary, are determined by these rules:
- Structure members are stored sequentially in the order in which they are declared: the first member has the lowest memory address and the last member the highest.
- Every data object has an alignment requirement. The alignment requirement for all data except structures, unions, and arrays is either the size of the object or the current packing size (specified with either the
alignedattribute or thepackpragma), whichever is less. For structures, unions, and arrays, the alignment requirement is the largest alignment requirement of its members. Every object is allocated an offset so that:offset % alignment_requirement == 0 - Adjacent bit-fields are packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size and if the next bit-field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit-fields.
MSVC interprets zero-length bit-fields in the following ways:
- If a zero-length bit-field is inserted between two bit-fields that are normally coalesced, the bit-fields are not coalesced. For example:
struct
{
unsigned long bf_1 : 12;
unsigned long : 0;
unsigned long bf_2 : 12;
} t1;
The size of t1 is 8 bytes with the zero-length bit-field. If the zero-length bit-field were removed, t1's size would be 4 bytes.
- 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, thenbaris aligned as the type of the zero-length bit-field. For example:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For t2, bar is placed at offset 2, 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 that come after non-bit-field members get ignored, bestie. Check out this struct:
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 run faster when the destination is already aligned but GCC doesn't realize it, so it's a lowkey win.-minline-all-stringopsโ โจ By default, GCC only inlines string operations when it knows the destination is aligned to at least a 4-byte boundary. This option inlines way more, so the code gets bigger, but code that leans on fastmemcpyandmemsetfor short lengths might get faster. It also turns on inline expansion ofstrlenfor all pointer alignments. Main character energy ๐-minline-stringops-dynamicallyโ ๐ง For string operations where the size isn't known until runtime, you get run-time checks. Small blocks get inline code, and big blocks get a library call. Smart, right? ๐ง-mstringop-strategy=algโ ๐ฅ This overrides GCC's internal heuristic for picking which algorithm to use when inlining string operations. The allowed values foralgare:rep_byte,rep_4byte,rep_8byteโ expand using the i386repprefix at the specified size.byte_loop,loop,unrolled_loopโ expand into an inline loop.libcallโ always use a library call, no inlining drama.
-mmemcpy-strategy=strategyโ ๐ This overrides the heuristic that decides whether__builtin_memcpygets inlined, and which inline algorithm to use when the expected copy size is known. Thestrategyis a comma-separated list ofalg:max_size:dest_aligntriplets. Thealgis one of the values from-mstringop-strategy, andmax_sizeis the biggest byte size thatalgis allowed to handle. The last triplet has to use amax_sizeof-1. Themax_sizevalues in the list must go in increasing order. The minimum byte size foralgis0for the first triplet, andmax_size + 1of the range before it for every other triplet. Very organized, bestie ๐-mmemset-strategy=strategyโ ๐ฆ Basically the same vibe as-mmemcpy-strategy=, except this one controls how__builtin_memsetgets expanded.-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-pointerdrops the frame pointer for leaf functions too, but ngl that might make debugging harder ๐-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ ๐ซถ This controls whether TLS variables can be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer has to be added. Whether that's valid depends on the operating system, and on whether it maps the segment to cover the entire TLS area. For systems using 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), this puts the profiling counter call before the prologue. Heads up: on x86 architectures, the attributems_hook_prologueisn't possible at the moment for-mfentryand-pg. Not it ๐-mrecord-mcount,-mno-record-mcountโ ๐ If profiling is active (-pg), this generates a__mcount_locsection full of pointers to each profiling call. Super handy for automatically patching those calls in and out.-mnop-mcount,-mno-nop-mcountโ ๐ธ If profiling is active (-pg), the calls to the profiling functions get generated as NOPs. This is useful when they should get patched in later on, dynamically. It's likely only useful together with-mrecord-mcount.-minstrument-return=typeโ ๐ Instruments function exit in-pg -mfentryinstrumented functions with a call to the specified function. It only instruments true returns that end withret, not sibling calls that end with a jump. The valid types are:noneโ don't instrument at all.callโ generate a call to__return__.nop5โ generate a 5-byte nop.
-mrecord-return,-mno-record-returnโ ๐ฆ Generates a__return_locsection that points to all the return instrumentation code.-mfentry-name=nameโ ๐ง Sets the name of the__fentry__symbol that gets called at function entry for-pg -mfentryfunctions.-mfentry-section=nameโ ๐ Sets the name of the section where-mrecord-mcountcalls get recorded. The default is__mcount_loc.-mskip-rax-setup,-mno-skip-rax-setupโ ๐ฅ When generating code for the x86-64 architecture with SSE extensions disabled,-mskip-rax-setupcan skip setting up the RAX register when no variable arguments are passed in vector registers.
โ ๏ธ Warning: RAX 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 doesn't have those issues, regardless of the RAX register value. ๐ญ
-m8bit-idiv,-mno-8bit-idivโ ๐ On some processors, like Intel Atom, 8-bit unsigned integer divide is way faster than 32-bit/64-bit integer divide. This option generates a run-time check. If both the dividend and the divisor are within the range of 0 to 255, an 8-bit unsigned integer divide gets used instead of the 32-bit/64-bit one. Galaxy brain ๐ง โจ-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 (which is 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 also specify which segment register (%fs or %gs) to use as the base register for reading the canary, and what offset from that base register to use. The defaults for those are whatever the relevant ABI specifies. ๐
-mgeneral-regs-onlyโ ๐ธ Generates code that only uses the general-purpose registers. This stops the compiler from using floating-point, vector, mask, and bound registers.-mindirect-branch=choiceโ ๐ฆ Converts indirect calls and jumps according tochoice. The default iskeep, which leaves indirect calls and jumps unmodified.thunkconverts them to call and return thunks.thunk-inlineconverts them to inlined call and return thunks.thunk-externconverts them to external call and return thunks, provided in a separate object file. You can control this behavior for a specific function with the function attribute"indirect_branch".
Note: -mcmodel=large is incompatible with -mindirect-branch=thunk and -mindirect-branch=thunk-extern, since the thunk function may not be reachable in the large code model.
Note: -mindirect-branch=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable the control-flow check. ๐ซถ
-mfunction-return=choiceโ ๐ Converts function returns according tochoice. The default iskeep, which leaves function returns unmodified.thunkconverts function returns to call and return thunks.thunk-inlineconverts them to inlined call and return thunks.thunk-externconverts them to external call and return thunks, provided in a separate object file. You can control this behavior for a specific function with the function attribute"function_return".
Note: -mindirect-return=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable the control-flow check.
Note: -mcmodel=large is incompatible with -mfunction-return=thunk and -mfunction-return=thunk-extern, since the thunk function may not be reachable in the large code model.
-mindirect-branch-registerโ ๐ฅ Forces indirect calls and jumps to go through a register.-mharden-sls=choiceโ ๐ก๏ธ Generates code to mitigate straight line speculation (SLS) according tochoice. The default isnone, which disables all SLS hardening. The other options are:returnโ enables SLS hardening for function returns.indirect-jmpโ enables SLS hardening for indirect jumps.allโ enables all SLS hardening.
-mindirect-branch-cs-prefixโ โจ Adds a CS prefix to calls and jmps to an indirect thunk, where the branch target is in ther8-r15registers. This makes the call and jmp instructions 6 bytes long, so they can be replaced at run-time withlfence; call *%r8-r15orlfence; jmp *%r8-r15. Big brain move ๐ง
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 in 32-bit mode.-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".code16gcc"assembly 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โ ๐ฆ Doesn't use a so-called "red zone" for x86-64 code. The red zone is mandated by the x86-64 ABI: it's a 128-byte area beyond the stack pointer that signal or interrupt handlers don't modify, so it can be used for temporary data without adjusting the stack pointer. The flag-mno-red-zonedisables this red zone. Bye bye, red zone ๐-mcmodel=smallโ okay so this is the default code model ๐ The program and its symbols have to be linked in the lower 2 GB of the address space. Pointers are 64 bits, and you can link statically or dynamically ๐ซถ-mcmodel=kernelโ this one is giving kernel energy ๐ The kernel runs in the negative 2 GB of the address space, and you have to use it for Linux kernel code. No skipping, bestie ๐-mcmodel=mediumโ the program gets linked in the lower 2 GB, and small symbols chill there too ๐ฆ Anything bigger than-mlarge-data-thresholdgets tossed into large data or BSS sections, and those can sit above 2GB. Static or dynamic linking both work ๐ธ-mcmodel=largeโ no assumptions about addresses and sizes of sections at all ๐ Full freedom, no cap.-maddress-mode=longโ long address mode ๐ง It's only for 64-bit and x32 environments, and it's the default for 64-bit ones โจ-maddress-mode=shortโ short address mode ๐ Only for 32-bit and x32 environments, and it's the default for 32-bit and x32 ones.-mneeded,-mno-neededโ this emits theGNU_PROPERTY_X86_ISA_1_NEEDEDGNU property for the Linux target ๐ฅ It tells you which micro-architecture ISA level the binary needs in order to run.
โจ x86 Windows Options โจ
Windows main character era ๐ช๐ These extra options are for Microsoft Windows targets:
-mconsoleโ makes a console application ๐ป It tells the linker to set the PE header subsystem type for console apps. Works for Cygwin and MinGW, and it's on by default there.-mdllโ Cygwin and MinGW only ๐ฆ This makes a DLL (a dynamic link library, obviously ๐), and it lets you pick the required runtime startup object and entry point.-mnop-fun-dllimportโ Cygwin and MinGW ๐ Tells GCC to ignore the"dllimport"attribute. Bye, attribute.-mthreadโ MinGW only ๐งต Turns on MinGW-specific thread support.-municodeโ MinGW-w64 only ๐ Predefines the"UNICODE"preprocessor macro and picks Unicode-capable runtime startup code.-mwin32โ Cygwin and MinGW ๐ธ Sets the typical Microsoft Windows predefined macros in the preprocessor. It doesn't change which runtime library or startup code gets picked, though.-mwindowsโ Cygwin and MinGW ๐ช Makes a GUI app by having the linker set the PE header subsystem type appropriately.-fno-set-stack-executableโ MinGW only โ ๏ธ Stops the executable flag from being set on the stack used by nested functions. This is necessary for binaries running in Windows kernel mode, since the User32 API (the one used to set executable privileges) isn't available there.-fwritable-relocated-rdataโ MinGW and Cygwin ๐ Puts relocated data from a read-only section into the".data"section. This is necessary for older runtimes that don't support modifying".rdata"sections for pseudo-relocation.-mpe-aligned-commonsโ Cygwin and MinGW ๐ Uses the GNU extension to the PE file format that lets COMMON variables align correctly 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โ picks startup files and a linker script that suit the simulator ๐น๏ธ
โจ Xtensa Options โจ
These options are supported for Xtensa targets ๐ท
-mconst16,-mno-const16โ turnCONST16instructions on or off for loading constant values. Heads up:CONST16isn't a standard Tensilica option ๐ When it's enabled,CONST16instructions are always used in place of the standardL32Rinstructions. It's only enabled by default if theL32Rinstruction isn't available.-mfused-madd,-mno-fused-maddโ toggles fused multiply/add and multiply/subtract instructions in the floating-point option. If the floating-point option isn't also enabled, this does nothing ๐ด Disabling them forces the compiler to use separate instructions for the multiply and the add/subtract. That can be the move when strict IEEE 754-compliant results are required, because fused instructions don't round the intermediate result, which gives you more bits of precision than the IEEE standard specifies. Disabling them also makes sure 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 disables PIC for compiling kernel code ๐-mtext-section-literals,-mno-text-section-literalsโ these control the treatment of literal pools ๐ The default,-mno-text-section-literals, places literals in a separate section in the output file. That lets the literal pool live in data RAM/ROM, and it lets the linker combine literal pools from separate object files to remove redundant literals and improve code size. With-mtext-section-literals, the literals are interspersed in the text section so they stay as close as possible to their references. This may be necessary for large assembly files. Literals for each function get placed right before that function.-mauto-litpools,-mno-auto-litpoolsโ more literal pool drama ๐ The default is-mno-auto-litpools, which places literals in a separate section in the output file unless-mtext-section-literalsis used. With-mauto-litpools, the literals are interspersed in the text section by the assembler. The compiler doesn't produce explicit".literal"directives and loads literals into registers withMOVIinstructions instead ofL32R, so the assembler can do relaxation and place literals as necessary. This option lets the assembler create several literal pools per function and assemble very big functions, which might not be possible with-mtext-section-literals.-mtarget-align,-mno-target-alignโ when enabled, GCC tells the assembler to automatically align instructions to reduce branch penalties, at the expense of some code density ๐ฏ The assembler tries to widen density instructions to align branch targets and the instructions following call instructions. If there aren't enough preceding safe density instructions to align a target, no widening happens. The default is-mtarget-align. These options don't affect auto-aligned instructions likeLOOP, which the assembler always aligns, either by widening density instructions or by insertingNOPinstructions.-mlongcalls,-mno-longcallsโ when enabled, GCC tells the assembler to translate direct calls into indirect calls unless it can determine that the target of a direct call is in the range the call instruction allows ๐ This usually happens for calls to functions in other source files. Specifically, the assembler turns a directCALLinto anL32Rfollowed by aCALLX. The default is-mno-longcalls. Use this option in programs where the call target can potentially be out of range. It's implemented in the assembler, not the compiler, so the assembly code GCC generates still shows direct call instructions. To see the actual instructions, look at the disassembled object code ๐ Also, the assembler uses an indirect call for every cross-file call, not just the ones that really are out of range.-mabi=nameโ generates code for the specified ABI ๐ Permissible values arecall0andwindowed. The default ABI is chosen by the Xtensa core configuration.-mabi=call0โ function parameters are passed in 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__gets defined.-mabi=windowedโ function parameters are passed in registersa10througha15, and the called function rotates the register window by 8 registers on entry so its arguments are found 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__gets defined.
โจ zSeries Options โจ
These are listed under ๐ซ
โจ ENVIRONMENT โจ
Okay bestie, these environment variables are the secret settings that change how GCC behaves ๐ธ Some tell it where to look for stuff (directories and prefixes), and others set up the rest of your compile vibe. ๐
Also, you can point GCC at places with options like -B, -I, and -L. Those beat the environment variables, and the environment variables beat whatever GCC was configured with. Options > env vars > defaults, no cap ๐
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL ๐
These handle localization, so GCC can vibe with different national conventions. GCC checks the LC_CTYPE and LC_MESSAGES locale categories if it was set up to do that. They can be set to any value your installation supports. A typical one is en_GB.UTF-8, which is English from the United Kingdom encoded in UTF-8 ๐ฌ๐ง
LC_CTYPEโ this one handles character classification. GCC uses it to figure out where characters start and stop in a string. That matters for some multibyte encodings with quote and escape characters that could otherwise be read as the end of a string or as an escape. Lowkey important ๐ฆLC_MESSAGESโ this picks the language for diagnostic messages (the error and warning text) ๐ฌLC_ALLโ if this is set, it overridesLC_CTYPEandLC_MESSAGES. If it isn't, those two default to whateverLANGsays. If none of these are set, GCC defaults to traditional C English behavior ๐
TMPDIR ๐๏ธ
If TMPDIR is set, it tells GCC which directory to use for temporary files. GCC makes temp files to hold the output of one stage of compilation that gets fed into 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 that option's docs for the full tea โ
GCC_EXEC_PREFIX ๐ฃ๏ธ
If GCC_EXEC_PREFIX is set, it gives a prefix for the names of the subprograms GCC runs. No slash gets added when the prefix is combined with a subprogram name, so if you want a slash, end your prefix with one ๐ซถ
If it isn't set, GCC tries to guess a sensible prefix from the path it was invoked with โจ
If GCC can't find the subprogram using your prefix, it goes looking in the usual places ๐
The default value of GCC_EXEC_PREFIX is prefix/lib/gcc/, where prefix is the prefix of the installed compiler. In a lot of cases, prefix is whatever you set prefix to when you ran the configure script ๐
Prefixes given with -B beat this one ๐
This prefix is also used to find files like crt0.o that get used for linking ๐
Here's the unusual part: the prefix also affects which directories get searched for header files. For each standard directory that normally starts with /usr/local/lib/gcc (more precisely, with the value of GCC_INCLUDE_DIR), GCC tries swapping that beginning out for your prefix to make an alternate directory name. So with -Bfoo/, GCC searches foo/bar just before it searches the standard directory /usr/local/lib/bar. And if a standard directory starts with the configured prefix, GCC swaps that prefix out for GCC_EXEC_PREFIX when it hunts for header files ๐ฆ
COMPILER_PATH ๐งญ
The value of COMPILER_PATH is a colon-separated list of directories, very much like PATH. GCC checks these directories when searching for subprograms, but only if it couldn't find them using GCC_EXEC_PREFIX ๐
LIBRARY_PATH ๐
The value of LIBRARY_PATH is a colon-separated list of directories, very much like PATH. When GCC is configured as a native compiler, it checks these directories for special linker files, but only if it couldn't find them using GCC_EXEC_PREFIX. Linking with GCC also searches these directories for ordinary libraries when you use the -l option. (Directories given with -L go first though ๐ฅ)
LANG (the second one, for multibyte characters) ๐
This variable passes locale info to the compiler. One thing it's used for is deciding which character set to use when parsing character literals, string literals, and comments in C and C++. When the compiler is configured to allow multibyte characters, these values for LANG are recognized:
C-JISโ 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 ๐ซง
GCC_EXTRA_DIAGNOSTIC_OUTPUT ๐ฉน
If GCC_EXTRA_DIAGNOSTIC_OUTPUT is set to one of the values below, extra text gets printed to stderr whenever fix-it hints are printed. Note that -fdiagnostics-parseable-fixits and -fno-diagnostics-parseable-fixits win over this environment variable ๐
fixits-v1โ emits parseable fix-it hints, same as-fdiagnostics-parseable-fixits. Columns are counted in bytes, starting at byte 1 for the initial column ๐ขfixits-v2โ same asfixits-v1, except columns are counted as display columns, per-fdiagnostics-column-unit=display๐
Some extra environment variables also change how the preprocessor behaves ๐งโโ๏ธ
CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH ๐
Each of these holds a list of directories to look in for header files, separated by a special character, kind of like PATH. That special character is called PATH_SEPARATOR. It's decided when GCC gets built, and it's a semicolon on Microsoft Windows-based targets and a colon on almost everything else ๐ช
CPATH lists directories that get searched as if you'd used -I, but they come after any paths given with -I on the command line. This one gets used no matter which language is being preprocessed ๐
The other three only apply when preprocessing their particular language. Each one lists directories searched as if you'd used -isystem, placed 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 go at the beginning or end of a path. For instance, if CPATH is :/special/include, that's the same as -I. -I/special/include โญ
DEPENDENCIES_OUTPUT ๐ธ๏ธ
If this one is set, its value says how to output dependencies for Make, based on the non-system header files the compiler processes. System header files get ignored in the dependency output ๐
The value 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 take the form file target, in which case the rules get written to file using target as the target name ๐ฏ
Basically, this variable does the same job as combining -MM and -MF, plus an optional -MT switch ๐
SUNPRO_DEPENDENCIES ๐
This is the same as DEPENDENCIES_OUTPUT, except system header files are not ignored. That means 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 used in place of the current date and time in the __DATE__ and __TIME__ macros. That keeps the embedded timestamps reproducible ๐
A SOURCE_DATE_EPOCH value has to be a UNIX timestamp, which means the number of seconds (leap seconds not counted) since 01 Jan 1970 00:00:00, written in ASCII. It's the same output you'd get from date +%s on GNU/Linux and other systems whose date command supports the %s extension โ
A good pick is a known timestamp like the last modification time of the source or package, and the build process should set it ๐ ๏ธ
๐ BUGS ๐
For instructions on reporting bugs, check out <file:///usr/share/doc/gcc-11/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 ๐
Check these out, bestie: 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 <http://gcc.gnu.org/onlinedocs/gcc/Contributors.html>, for the contributors to GCC. They're the real MVPs ๐
โ๏ธ COPYRIGHT โ๏ธ
Copyright (c) 1988-2021 Free Software Foundation, Inc.
Okay, the legal bit, but make it cute: you're allowed to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation. The 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.
Okay bestie, that's the whole GCC(1) page, fully served ๐ Sourced from gcc-11 and dated 2024-07-19, filed under GCC(1), and now you officially know more about GCC than most people ever will ๐ฆโจ
๐ฆ where this page comes from
- ubuntu questing: g++-11-alpha-linux-gnu 11.5.0-7ubuntu1cross1
- ubuntu resolute: g++-11-alpha-linux-gnu 11.5.0-11ubuntu2cross1
- ubuntu stonking: g++-11-alpha-linux-gnu 11.5.0-11ubuntu2cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms