GCC(1)
โจ GCC(1) โ GNU โจ
Part 1 of 116. More parts are coming, so stay tuned, bestie ๐
๐ 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 only the most useful options are listed up there, and you'll find the rest further down. ๐ง g++ takes mostly the same options as gcc, so no stress.
๐ DESCRIPTION ๐
When you invoke GCC, it normally does preprocessing, compilation, assembly and linking, the whole glow-up ๐
. The "overall options" let you stop that process at an intermediate stage. For example, the -c option says not to run the linker, so the output is just object files spit out by the assembler. It's giving stop-early energy โจ.
Other options get passed along to one or more stages. Some control the preprocessor, some control the compiler itself, and yet other options control the assembler and linker. Most of those last ones aren't documented here, because honestly you rarely need them ๐.
Most of the command-line options you can use with GCC are useful for C programs. When an option only matters for another language (usually C++), the explanation says so right out loud. If an option's description doesn't mention a source language, you can use it with all supported languages ๐.
The usual way to run GCC is to run the executable called gcc, or machine-gcc when you're cross-compiling, or machine-gcc-version if you want one specific version of GCC. When you compile C++ programs, you should invoke GCC as g++ instead ๐ซถ.
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so multiple single-letter options can't be grouped together. -dv is very different from -d -v, so don't be sloppy ๐.
You can mix options and other arguments, and for the most part the order doesn't matter. Order does matter when you use several options of the same kind. For example, if you specify -L more than once, the directories get searched in the order you specified them. Also, the placement of the -l option is significant ๐.
Many options have long names starting with -f or with -W, like -fmove-loop-invariants, -Wformat and so on. Most of these come in both positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of those two forms, whichever one isn't the default. Main character energy, the default is the one you get without asking ๐.
Some options take one or more arguments, usually separated from the option name by either a space or an equals sign (=). Unless documented otherwise, an argument can be either numeric or a string. Numeric arguments 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. That includes kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, GB and GiB for gigabyte and gigibyte, and so on ๐ฆ. Those arguments are designated by byte-size in the rest of the text. If you want the full lore on the binary and decimal byte size prefixes, check the NIST, IEC, and other relevant national and international standards, because they've got the whole list and explanation ๐ค.
๐ OPTIONS ๐
๐ Option Summary
Here is a summary of all the options, grouped by type. The explanations live in the following sections, so keep scrolling, bestie โจ.
๐ธ Overall Options
-c -S -E -o file -dumpbase dumpbase -dumpbase-ext auxdropsuf
-dumpdir dumppfx -x language -v -### --help[=class[,...]]
--target-help --version -pass-exit-codes -pipe -specs=file
-wrapper @file -ffile-prefix-map=old=new -fplugin=file
-fplugin-arg-name=arg -fdump-ada-spec[-slim] -fada-spec-parent=unit
-fdump-go-spec=file
๐ง C Language Options
-ansi -std=standard -aux-info filename
-fallow-parameterless-variadic-functions -fno-asm -fno-builtin
-fno-builtin-function -fcond-mismatch -ffreestanding -fgimple
-fgnu-tm -fgnu89-inline -fhosted -flax-vector-conversions
-fms-extensions -foffload=arg -foffload-options=arg -fopenacc
-fopenacc-dim=geom -fopenmp -fopenmp-simd
-fpermitted-flt-eval-methods=standard -fplan9-extensions
-fsigned-bitfields -funsigned-bitfields -fsigned-char
-funsigned-char -fsso-struct=endianness
๐ C++ Language Options
-fabi-version=n -fno-access-control -faligned-new=n
-fargs-in-order=n -fchar8_t -fcheck-new -fconstexpr-depth=n
-fconstexpr-cache-depth=n -fconstexpr-loop-limit=n
-fconstexpr-ops-limit=n -fno-elide-constructors
-fno-enforce-eh-specs -fno-gnu-keywords -fno-implicit-templates
-fno-implicit-inline-templates -fno-implement-inlines
-fmodule-header[=kind] -fmodule-only -fmodules-ts
-fmodule-implicit-inline -fno-module-lazy
-fmodule-mapper=specification -fmodule-version-ignore
-fms-extensions -fnew-inheriting-ctors -fnew-ttp-matching
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names
-fno-optional-diags -fpermissive -fno-pretty-templates -fno-rtti
-fsized-deallocation -ftemplate-backtrace-limit=n -ftemplate-depth=n
-fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++
-fvisibility-inlines-hidden -fvisibility-ms-compat
-fext-numeric-literals -flang-info-include-translate[=header]
-flang-info-include-translate-not -flang-info-module-cmi[=module]
-stdlib=libstdc++,libc++ -Wabi-tag -Wcatch-value -Wcatch-value=n
-Wno-class-conversion -Wclass-memaccess -Wcomma-subscript
-Wconditionally-supported -Wno-conversion-null
-Wctad-maybe-unsupported -Wctor-dtor-privacy -Wno-delete-incomplete
-Wdelete-non-virtual-dtor -Wno-deprecated-array-compare
-Wdeprecated-copy -Wdeprecated-copy-dtor
-Wno-deprecated-enum-enum-conversion
-Wno-deprecated-enum-float-conversion -Weffc++ -Wno-exceptions
-Wextra-semi -Wno-inaccessible-base -Wno-inherited-variadic-ctor
-Wno-init-list-lifetime -Winvalid-imported-macros
-Wno-invalid-offsetof -Wno-literal-suffix -Wmismatched-new-delete
-Wmismatched-tags -Wmultiple-inheritance -Wnamespaces -Wnarrowing
-Wnoexcept -Wnoexcept-type -Wnon-virtual-dtor -Wpessimizing-move
-Wno-placement-new -Wplacement-new=n -Wrange-loop-construct
-Wredundant-move -Wredundant-tags -Wreorder -Wregister
-Wstrict-null-sentinel -Wno-subobject-linkage -Wtemplates
-Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual
-Wno-pmf-conversions -Wsign-promo -Wsized-deallocation
-Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override
-Wno-terminate -Wuseless-cast -Wno-vexing-parse
-Wvirtual-inheritance -Wno-virtual-move-assign -Wvolatile
-Wzero-as-null-pointer-constant
๐ซง Objective-C and Objective-C++ Language Options
-fconstant-string-class=class-name -fgnu-runtime -fnext-runtime
-fno-nil-receivers -fobjc-abi-version=n -fobjc-call-cxx-cdtors
-fobjc-direct-dispatch -fobjc-exceptions -fobjc-gc -fobjc-nilcheck
-fobjc-std=objc1 -fno-local-ivars
-fivar-visibility=[public|protected|private|package]
-freplace-objc-classes -fzero-link -gen-decls -Wassign-intercept
-Wno-property-assign-default -Wno-protocol -Wobjc-root-class
-Wselector -Wstrict-selector-match -Wundeclared-selector
๐ Diagnostic Message Formatting Options
-fmessage-length=n -fdiagnostics-plain-output
-fdiagnostics-show-location=[once|every-line]
-fdiagnostics-color=[auto|never|always]
-fdiagnostics-urls=[auto|never|always]
-fdiagnostics-format=[text|json] -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-labels
-fno-diagnostics-show-line-numbers -fno-diagnostics-show-cwe
-fdiagnostics-minimum-margin-width=width
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type
-fdiagnostics-path-format=[none|separate-events|inline-events]
-fdiagnostics-show-path-depths -fno-show-column
-fdiagnostics-column-unit=[display|byte]
-fdiagnostics-column-origin=origin
-fdiagnostics-escape-format=[unicode|bytes]
โ ๏ธ Warning Options
okay so this is the big warning squad ๐จ bestie, there's a LOT of them and no explanations on this part of the page, so I'm serving them straight up ๐
-fsyntax-only -fmax-errors=n -Wpedantic -pedantic-errors -w
-Wextra -Wall -Wabi=n -Waddress -Wno-address-of-packed-member
-Waggregate-return -Walloc-size-larger-than=byte-size -Walloc-zero
-Walloca -Walloca-larger-than=byte-size
-Wno-aggressive-loop-optimizations -Warith-conversion -Warray-bounds
-Warray-bounds=n -Warray-compare -Wno-attributes
-Wattribute-alias=n -Wno-attribute-alias -Wno-attribute-warning
-Wbidi-chars=[none|unpaired|any|ucn] -Wbool-compare
-Wbool-operation -Wno-builtin-declaration-mismatch
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat
-Wc11-c2x-compat -Wc++-compat -Wc++11-compat -Wc++14-compat
-Wc++17-compat -Wc++20-compat -Wno-c++11-extensions
-Wno-c++14-extensions -Wno-c++17-extensions -Wno-c++20-extensions
-Wno-c++23-extensions -Wcast-align -Wcast-align=strict
-Wcast-function-type -Wcast-qual -Wchar-subscripts -Wclobbered
-Wcomment -Wconversion -Wno-coverage-mismatch -Wno-cpp
-Wdangling-else -Wdangling-pointer -Wdangling-pointer=n
-Wdate-time -Wno-deprecated -Wno-deprecated-declarations
-Wno-designated-init -Wdisabled-optimization
-Wno-discarded-array-qualifiers -Wno-discarded-qualifiers
-Wno-div-by-zero -Wdouble-promotion -Wduplicated-branches
-Wduplicated-cond -Wempty-body -Wno-endif-labels -Wenum-compare
-Wenum-conversion -Werror -Werror=* -Wexpansion-to-defined
-Wfatal-errors -Wfloat-conversion -Wfloat-equal -Wformat
-Wformat=2 -Wno-format-contains-nul -Wno-format-extra-args
-Wformat-nonliteral -Wformat-overflow=n -Wformat-security
-Wformat-signedness -Wformat-truncation=n -Wformat-y2k
-Wframe-address -Wframe-larger-than=byte-size
-Wno-free-nonheap-object -Wno-if-not-aligned
-Wno-ignored-attributes -Wignored-qualifiers
-Wno-incompatible-pointer-types -Wimplicit -Wimplicit-fallthrough
-Wimplicit-fallthrough=n -Wno-implicit-function-declaration
-Wno-implicit-int -Winfinite-recursion -Winit-self -Winline
-Wno-int-conversion -Wint-in-bool-context -Wno-int-to-pointer-cast
-Wno-invalid-memory-model -Winvalid-pch -Wjump-misses-init
-Wlarger-than=byte-size -Wlogical-not-parentheses -Wlogical-op
-Wlong-long -Wno-lto-type-mismatch -Wmain -Wmaybe-uninitialized
-Wmemset-elt-size -Wmemset-transposed-args -Wmisleading-indentation
-Wmissing-attributes -Wmissing-braces -Wmissing-field-initializers
-Wmissing-format-attribute -Wmissing-include-dirs
-Wmissing-noreturn -Wno-missing-profile -Wno-multichar
-Wmultistatement-macros -Wnonnull -Wnonnull-compare
-Wnormalized=[none|id|nfc|nfkc] -Wnull-dereference -Wno-odr
-Wopenacc-parallelism -Wopenmp-simd -Wno-overflow
-Woverlength-strings -Wno-override-init-side-effects -Wpacked
-Wno-packed-bitfield-compat -Wpacked-not-aligned -Wpadded
-Wparentheses -Wno-pedantic-ms-format -Wpointer-arith
-Wno-pointer-compare -Wno-pointer-to-int-cast -Wno-pragmas
-Wno-prio-ctor-dtor -Wredundant-decls -Wrestrict
-Wno-return-local-addr -Wreturn-type -Wno-scalar-storage-order
-Wsequence-point -Wshadow -Wshadow=global -Wshadow=local
-Wshadow=compatible-local -Wno-shadow-ivar -Wno-shift-count-negative
-Wno-shift-count-overflow -Wshift-negative-value
-Wno-shift-overflow -Wshift-overflow=n -Wsign-compare
-Wsign-conversion -Wno-sizeof-array-argument -Wsizeof-array-div
-Wsizeof-pointer-div -Wsizeof-pointer-memaccess -Wstack-protector
-Wstack-usage=byte-size -Wstrict-aliasing -Wstrict-aliasing=n
-Wstrict-overflow -Wstrict-overflow=n -Wstring-compare
-Wno-stringop-overflow -Wno-stringop-overread
-Wno-stringop-truncation
-Wsuggest-attribute=[pure|const|noreturn|format|malloc] -Wswitch
-Wno-switch-bool -Wswitch-default -Wswitch-enum
-Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand
-Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs
-Wtsan -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas
-Wunsuffixed-float-constants -Wunused -Wunused-but-set-parameter
-Wunused-but-set-variable -Wunused-const-variable
-Wunused-const-variable=n -Wunused-function -Wunused-label
-Wunused-local-typedefs -Wunused-macros -Wunused-parameter
-Wno-unused-result -Wunused-value -Wunused-variable -Wno-varargs
-Wvariadic-macros -Wvector-operation-performance -Wvla
-Wvla-larger-than=byte-size -Wno-vla-larger-than
-Wvolatile-register-var -Wwrite-strings -Wzero-length-bounds
๐ Static Analyzer Options
the analyzer crew is up next ๐ง same deal, no descriptions here, just the full lineup
-fanalyzer -fanalyzer-call-summaries -fanalyzer-checker=name
-fno-analyzer-feasibility -fanalyzer-fine-grained
-fanalyzer-state-merge -fanalyzer-state-purge
-fanalyzer-transitivity -fanalyzer-verbose-edges
-fanalyzer-verbose-state-changes -fanalyzer-verbosity=level
-fdump-analyzer -fdump-analyzer-stderr -fdump-analyzer-callgraph
-fdump-analyzer-exploded-graph -fdump-analyzer-exploded-nodes
-fdump-analyzer-exploded-nodes-2 -fdump-analyzer-exploded-nodes-3
-fdump-analyzer-exploded-paths -fdump-analyzer-feasibility
-fdump-analyzer-json -fdump-analyzer-state-purge
-fdump-analyzer-supergraph -Wno-analyzer-double-fclose
-Wno-analyzer-double-free -Wno-analyzer-exposure-through-output-file
-Wno-analyzer-file-leak -Wno-analyzer-free-of-non-heap
-Wno-analyzer-malloc-leak -Wno-analyzer-mismatching-deallocation
-Wno-analyzer-null-argument -Wno-analyzer-null-dereference
-Wno-analyzer-possible-null-argument
-Wno-analyzer-possible-null-dereference
-Wno-analyzer-shift-count-negative
-Wno-analyzer-shift-count-overflow -Wno-analyzer-stale-setjmp-buffer
-Wno-analyzer-tainted-allocation-size
-Wno-analyzer-tainted-array-index -Wno-analyzer-tainted-divisor
-Wno-analyzer-tainted-offset -Wno-analyzer-tainted-size
-Wanalyzer-too-complex
-Wno-analyzer-unsafe-call-within-signal-handler
-Wno-analyzer-use-after-free
-Wno-analyzer-use-of-pointer-in-stale-stack-frame
-Wno-analyzer-use-of-uninitialized-value
-Wno-analyzer-write-to-const -Wno-analyzer-write-to-string-literal
๐ธ C and Objective-C-only Warning Options
these ones are C and Objective-C only, so they're a little picky about who they hang out with ๐
-Wbad-function-cast -Wmissing-declarations -Wmissing-parameter-type
-Wmissing-prototypes -Wnested-externs -Wold-style-declaration
-Wold-style-definition -Wstrict-prototypes -Wtraditional
-Wtraditional-conversion -Wdeclaration-after-statement
-Wpointer-sign
๐ Debugging Options
last but not least, the debugging options ๐ฆ the list is LONG so grab a snack ๐
-g -glevel -gdwarf -gdwarf-version -gbtf -gctf -gctflevel -ggdb
-grecord-gcc-switches -gno-record-gcc-switches -gstabs -gstabs+
-gstrict-dwarf -gno-strict-dwarf -gas-loc-support
-gno-as-loc-support -gas-locview-support -gno-as-locview-support
-gcolumn-info -gno-column-info -gdwarf32 -gdwarf64
-gstatement-frontiers -gno-statement-frontiers
-gvariable-location-views -gno-variable-location-views
-ginternal-reset-location-views -gno-internal-reset-location-views
-ginline-points -gno-inline-points -gvms -gxcoff -gxcoff+
-gz[=type] -gsplit-dwarf -gdescribe-dies -gno-describe-dies
-fdebug-prefix-map=old=new -fdebug-types-section
-fno-eliminate-unused-debug-types -femit-struct-debug-baseonly
-femit-struct-debug-reduced -femit-struct-debug-detailed[=spec-list]
-fno-eliminate-unused-debug-symbols -femit-class-debug-always
-fno-merge-debug-strings -fno-dwarf2-cfi-asm -fvar-tracking
-fvar-tracking-assignments
๐ธ Optimization Options ๐ธ
okay bestie, the optimization drawer is LOADED ๐ โจ here's the whole stash:
-faggressive-loop-optimizations-falign-functions[=n[:m:[n2[:m2]]]]-falign-jumps[=n[:m:[n2[:m2]]]]-falign-labels[=n[:m:[n2[:m2]]]]-falign-loops[=n[:m:[n2[:m2]]]]-fno-allocation-dce-fallow-store-data-races-fassociative-math-fauto-profile-fauto-profile[=path]-fauto-inc-dec-fbranch-probabilities-fcaller-saves-fcombine-stack-adjustments-fconserve-stack-fcompare-elim-fcprop-registers-fcrossjumping-fcse-follow-jumps-fcse-skip-blocks-fcx-fortran-rules-fcx-limited-range-fdata-sections-fdce-fdelayed-branch-fdelete-null-pointer-checks-fdevirtualize-fdevirtualize-speculatively-fdevirtualize-at-ltrans-fdse-fearly-inlining-fipa-sra-fexpensive-optimizations-ffat-lto-objects-ffast-math-ffinite-math-only-ffloat-store-fexcess-precision=style-ffinite-loops-fforward-propagate-ffp-contract=style-ffunction-sections-fgcse-fgcse-after-reload-fgcse-las-fgcse-lm-fgraphite-identity-fgcse-sm-fhoist-adjacent-loads-fif-conversion-fif-conversion2-findirect-inlining-finline-functions-finline-functions-called-once-finline-limit=n-finline-small-functions-fipa-modref-fipa-cp-fipa-cp-clone-fipa-bit-cp-fipa-vrp-fipa-pta-fipa-profile-fipa-pure-const-fipa-reference-fipa-reference-addressable-fipa-stack-alignment-fipa-icf-fira-algorithm=algorithm-flive-patching=level-fira-region=region-fira-hoist-pressure-fira-loop-pressure-fno-ira-share-save-slots-fno-ira-share-spill-slots-fisolate-erroneous-paths-dereference-fisolate-erroneous-paths-attribute-fivopts-fkeep-inline-functions-fkeep-static-functions-fkeep-static-consts-flimit-function-alignment-flive-range-shrinkage-floop-block-floop-interchange-floop-strip-mine-floop-unroll-and-jam-floop-nest-optimize-floop-parallelize-all-flra-remat-flto-flto-compression-level-flto-partition=alg-fmerge-all-constants-fmerge-constants-fmodulo-sched-fmodulo-sched-allow-regmoves-fmove-loop-invariants-fmove-loop-stores-fno-branch-count-reg-fno-defer-pop-fno-fp-int-builtin-inexact-fno-function-cse-fno-guess-branch-probability-fno-inline-fno-math-errno-fno-peephole-fno-peephole2-fno-printf-return-value-fno-sched-interblock-fno-sched-spec-fno-signed-zeros-fno-toplevel-reorder-fno-trapping-math-fno-zero-initialized-in-bss-fomit-frame-pointer-foptimize-sibling-calls-fpartial-inlining-fpeel-loops-fpredictive-commoning-fprefetch-loop-arrays-fprofile-correction-fprofile-use-fprofile-use=path-fprofile-partial-training-fprofile-values-fprofile-reorder-functions-freciprocal-math-free-frename-registers-freorder-blocks-freorder-blocks-algorithm=algorithm-freorder-blocks-and-partition-freorder-functions-frerun-cse-after-loop-freschedule-modulo-scheduled-loops-frounding-math-fsave-optimization-record-fsched2-use-superblocks-fsched-pressure-fsched-spec-load-fsched-spec-load-dangerous-fsched-stalled-insns-dep[=n]-fsched-stalled-insns[=n]-fsched-group-heuristic-fsched-critical-path-heuristic-fsched-spec-insn-heuristic-fsched-rank-heuristic-fsched-last-insn-heuristic-fsched-dep-count-heuristic-fschedule-fusion-fschedule-insns-fschedule-insns2-fsection-anchors-fselective-scheduling-fselective-scheduling2-fsel-sched-pipelining-fsel-sched-pipelining-outer-loops-fsemantic-interposition-fshrink-wrap-fshrink-wrap-separate-fsignaling-nans-fsingle-precision-constant-fsplit-ivs-in-unroller-fsplit-loops-fsplit-paths-fsplit-wide-types-fsplit-wide-types-early-fssa-backprop-fssa-phiopt-fstdarg-opt-fstore-merging-fstrict-aliasing-fipa-strict-aliasing-fthread-jumps-ftracer-ftree-bit-ccp-ftree-builtin-call-dce-ftree-ccp-ftree-ch-ftree-coalesce-vars-ftree-copy-prop-ftree-dce-ftree-dominator-opts-ftree-dse-ftree-forwprop-ftree-fre-fcode-hoisting-ftree-loop-if-convert-ftree-loop-im-ftree-phiprop-ftree-loop-distribution-ftree-loop-distribute-patterns-ftree-loop-ivcanon-ftree-loop-linear-ftree-loop-optimize-ftree-loop-vectorize-ftree-parallelize-loops=n-ftree-pre-ftree-partial-pre-ftree-pta-ftree-reassoc-ftree-scev-cprop-ftree-sink-ftree-slsr-ftree-sra-ftree-switch-conversion-ftree-tail-merge-ftree-ter-ftree-vectorize-ftree-vrp-ftrivial-auto-var-init-funconstrained-commons-funit-at-a-time-funroll-all-loops-funroll-loops-funsafe-math-optimizations-funswitch-loops-fipa-ra-fvariable-expansion-in-unroller-fvect-cost-model-fvpt-fweb-fwhole-program-fwpa-fuse-linker-plugin-fzero-call-used-regs--param name=value-O-O0-O1-O2-O3-Os-Ofast-Og-Oz
๐ฆ Program Instrumentation Options ๐ฆ
next up, the instrumentation squad ๐ซถ profiling, sanitizing, and hardening flags, all in one spot:
-p-pg-fprofile-arcs--coverage-ftest-coverage-fprofile-abs-path-fprofile-dir=path-fprofile-generate-fprofile-generate=path-fprofile-info-section-fprofile-info-section=name-fprofile-note=path-fprofile-prefix-path=path-fprofile-update=method-fprofile-filter-files=regex-fprofile-exclude-files=regex-fprofile-reproducible=[multithreaded|parallel-runs|serial]-fsanitize=style-fsanitize-recover-fsanitize-recover=style-fasan-shadow-offset=number-fsanitize-sections=s1,s2,...-fsanitize-undefined-trap-on-error-fbounds-check-fcf-protection=[full|branch|return|none|check]-fharden-compares-fharden-conditional-branches-fstack-protector-fstack-protector-all-fstack-protector-strong-fstack-protector-explicit-fstack-check-fstack-limit-register=reg-fstack-limit-symbol=sym-fno-stack-limit-fsplit-stack-fvtable-verify=[std|preinit|none]-fvtv-counts-fvtv-debug-finstrument-functions-finstrument-functions-exclude-function-list=sym,sym,...-finstrument-functions-exclude-file-list=file,file,...-fprofile-prefix-map=old=new
๐ Preprocessor Options ๐
the preprocessor crew is giving very organized energy ๐ง
-Aquestion=answer-A-question[=answer]-C-CC-Dmacro[=defn]-dD-dI-dM-dN-dU-fdebug-cpp-fdirectives-only-fdollars-in-identifiers-fexec-charset=charset-fextended-identifiers-finput-charset=charset-flarge-source-files-fmacro-prefix-map=old=new-fmax-include-depth=depth-fno-canonical-system-headers-fpch-deps-fpch-preprocess-fpreprocessed-ftabstop=width-ftrack-macro-expansion-fwide-exec-charset=charset-fworking-directory-H-imacros file-include file-M-MD-MF-MG-MM-MMD-MP-MQ-MT-Mno-modules-no-integrated-cpp-P-pthread-remap-traditional-traditional-cpp-trigraphs-Umacro-undef-Wp,option-Xpreprocessor option
๐ง Assembler Options ๐ง
only two of these, but they're iconic ๐
-Wa,option-Xassembler option
๐ Linker Options ๐
the linking section is bringing the main character energy ๐
object-file-name-fuse-ld=linker-llibrary-nostartfiles-nodefaultlibs-nolibc-nostdlib-e entry--entry=entry-pie-pthread-r-rdynamic-s-static-static-pie-static-libgcc-static-libstdc++-static-libasan-static-libtsan-static-liblsan-static-libubsan-shared-shared-libgcc-symbolic-T script-Wl,option-Xlinker option-u symbol-z keyword
๐ Directory Options ๐
ngl the directory options are a whole vibe ๐
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--sysroot=dir
๐ Code Generation Options ๐
this section is where the real craft happens ๐ธ
-fcall-saved-reg-fcall-used-reg-ffixed-reg-fexceptions-fnon-call-exceptions-fdelete-dead-exceptions-funwind-tables-fasynchronous-unwind-tables-fno-gnu-unique-finhibit-size-directive-fcommon-fno-ident-fpcc-struct-return-fpic-fPIC-fpie-fPIE-fno-plt-fno-jump-tables-fno-bit-tests-frecord-gcc-switches-freg-struct-return-fshort-enums-fshort-wchar-fverbose-asm-fpack-struct[=n]-fleading-underscore-ftls-model=model-fstack-reuse=reuse_level-ftrampolines-ftrapv-fwrapv-fvisibility=[default|internal|hidden|protected]-fstrict-volatile-bitfields-fsync-libcalls
๐ Developer Options ๐
ok this one is for the nerds, and we love them ๐ค๐ฅ
-dletters-dumpspecs-dumpmachine-dumpversion-dumpfullversion-fcallgraph-info[=su,da]-fchecking-fchecking=n-fdbg-cnt-list-fdbg-cnt=counter-value-list-fdisable-ipa-pass_name-fdisable-rtl-pass_name-fdisable-rtl-pass-name=range-list-fdisable-tree-pass_name-fdisable-tree-pass-name=range-list-fdump-debug-fdump-earlydebug-fdump-noaddr-fdump-unnumbered-fdump-unnumbered-links-fdump-final-insns[=file]-fdump-ipa-all-fdump-ipa-cgraph-fdump-ipa-inline-fdump-lang-all-fdump-lang-switch-fdump-lang-switch-options-fdump-lang-switch-options=filename-fdump-passes-fdump-rtl-pass-fdump-rtl-pass=filename-fdump-statistics-fdump-tree-all-fdump-tree-switch-fdump-tree-switch-options-fdump-tree-switch-options=filename-fcompare-debug[=opts]-fcompare-debug-second-fenable-kind-pass-fenable-kind-pass=range-list-fira-verbose=n-flto-report-flto-report-wpa-fmem-report-wpa-fmem-report-fpre-ipa-mem-report-fpost-ipa-mem-report-fopt-info-fopt-info-options[=file]-fprofile-report-frandom-seed=string-fsched-verbose=n-fsel-sched-verbose-fsel-sched-dump-cfg-fsel-sched-pipelining-verbose-fstats-fstack-usage-ftime-report-ftime-report-details-fvar-tracking-assignments-toggle-gtoggle-print-file-name=library-print-libgcc-file-name-print-multi-directory-print-multi-lib-print-multi-os-directory-print-prog-name=program-print-search-dirs-Q-print-sysroot-print-sysroot-headers-suffix-save-temps-save-temps=cwd-save-temps=obj-time[=file]
๐ Machine-Dependent Options ๐
last stop, the machine-specific flags, and every target has its own little personality ๐ฆ
โญ AArch64 Options โญ
-mabi=name-mbig-endian-mlittle-endian-mgeneral-regs-only-mcmodel=tiny-mcmodel=small-mcmodel=large-mstrict-align-mno-strict-align-momit-leaf-frame-pointer-mtls-dialect=desc-mtls-dialect=traditional-mtls-size=size-mfix-cortex-a53-835769-mfix-cortex-a53-843419-mlow-precision-recip-sqrt-mlow-precision-sqrt-mlow-precision-div-mpc-relative-literal-loads-msign-return-address=scope-mbranch-protection=none|standard|pac-ret[+leaf +b-key]|bti-mharden-sls=opts-march=name-mcpu=name-mtune=name-moverride=string-mverbose-cost-dump-mstack-protector-guard=guard-mstack-protector-guard-reg=sysreg-mstack-protector-guard-offset=offset-mtrack-speculation-moutline-atomics
โจ Adapteva Epiphany Options โจ
Okay bestie, the Epiphany flags are up next ๐ฆ Here's the full lineup:
-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 โจ
Now the AMD GCN crew ๐ Three flags, all iconic:
-march=gpu-mtune=gpu-mstack-size=bytes
โจ ARC Options โจ
The ARC section is giving main character energy ๐ It's a long one, so grab a snack ๐
-mbarrel-shifter-mjli-always-mcpu=cpu-mA6-mARC600-mA7-mARC700-mdpfp-mdpfp-compact-mdpfp-fast-mno-dpfp-lrsr-mea-mno-mpy-mmul32x16-mmul64-matomic-mnorm-mspfp-mspfp-compact-mspfp-fast-msimd-msoft-float-mswap-mcrc-mdsp-packa-mdvbf-mlock-mmac-d16-mmac-24-mrtsc-mswape-mtelephony-mxy-misize-mannotate-align-marclinux-marclinux_prof-mlong-calls-mmedium-calls-msdata-mirq-ctrl-saved-mrgf-banked-regs-mlpc-width=width-G num-mvolatile-cache-mtp-regno=regno-malign-call-mauto-modify-reg-mbbit-peephole-mno-brcc-mcase-vector-pcrel-mcompact-casesi-mno-cond-exec-mearly-cbranchsi-mexpand-adddi-mindexed-loads-mlra-mlra-priority-none-mlra-priority-compact-mlra-priority-noncompact-mmillicode-mmixed-code-mq-class-mRcq-mRcw-msize-level=level-mtune=cpu-mmultcost=num-mcode-density-frame-munalign-prob-threshold=probability-mmpy-option=multo-mdiv-rem-mcode-density-mll64-mfpu=fpu-mrf16-mbranch-index
โจ ARM Options โจ
Next up is ARM ๐ Lots of flags, but they're all serving looks:
-mapcs-frame-mno-apcs-frame-mabi=name-mapcs-stack-check-mno-apcs-stack-check-mapcs-reentrant-mno-apcs-reentrant-mgeneral-regs-only-msched-prolog-mno-sched-prolog-mlittle-endian-mbig-endian-mbe8-mbe32-mfloat-abi=name-mfp16-format=name-mthumb-interwork-mno-thumb-interwork-mcpu=name-march=name-mfpu=name-mtune=name-mprint-tune-info-mstructure-size-boundary=n-mabort-on-noreturn-mlong-calls-mno-long-calls-msingle-pic-base-mno-single-pic-base-mpic-register=reg-mnop-fun-dllimport-mpoke-function-name-mthumb-marm-mflip-thumb-mtpcs-frame-mtpcs-leaf-frame-mcaller-super-interworking-mcallee-super-interworking-mtp=name-mtls-dialect=dialect-mword-relocations-mfix-cortex-m3-ldrd-mfix-cortex-a57-aes-1742098-mfix-cortex-a72-aes-1655431-munaligned-access-mneon-for-64bits-mslow-flash-data-masm-syntax-unified-mrestrict-it-mverbose-cost-dump-mpure-code-mcmse-mfix-cmse-cve-2021-35465-mstack-protector-guard=guard-mstack-protector-guard-offset=offset-mfdpic
โจ AVR Options โจ
AVR time ๐ฆ These are a whole vibe:
-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 โจ
Moving on to Blackfin ๐ฅ Keep scrolling, it's worth it:
-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 โจ
The C6X flags are short and sweet ๐
-mbig-endian-mlittle-endian-march=cpu-msim-msdata=sdata-type
โจ CRIS Options โจ
CRIS is serving retro vibes ๐ Lots of options, let's go:
-mcpu=cpu-march=cpu-mtune=cpu-mmax-stack-frame=n-melinux-stacksize=n-metrax4-metrax100-mpdebug-mcc-init-mno-side-effects-mstack-align-mdata-align-mconst-align-m32-bit-m16-bit-m8-bit-mno-prologue-epilogue-mno-gotplt-melf-maout-melinux-mlinux-sim-sim2-mmul-bug-workaround-mno-mul-bug-workaround
โจ CR16 Options โจ
Now the CR16 flags ๐ธ
-mmac-mcr16cplus-mcr16c-msim-mint32-mbit-ops-mdata-model=model
โจ C-SKY Options โจ
C-SKY is up next, and it's a big one ๐ซถ
-march=arch-mcpu=cpu-mbig-endian-EB-mlittle-endian-EL-mhard-float-msoft-float-mfpu=fpu-mdouble-float-mfdivdu-mfloat-abi=name-melrw-mistack-mmp-mcp-mcache-msecurity-mtrust-mdsp-medsp-mvdsp-mdiv-msmart-mhigh-registers-manchor-mpushpop-mmultiple-stld-mconstpool-mstack-size-mccrt-mbranch-cost=n-mcse-cc-msched-prolog-msim
โจ Darwin Options โจ
Darwin is the longest list in this batch, so settle in ๐ โจ
-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 โจ
DEC Alpha is a certified classic ๐ง
-mno-fp-regs-msoft-float-mieee-mieee-with-inexact-mieee-conformant-mfp-trap-mode=mode-mfp-rounding-mode=mode-mtrap-precision=mode-mbuild-constants-mcpu=cpu-type-mtune=cpu-type-mbwx-mmax-mfix-mcix-mfloat-vax-mfloat-ieee-mexplicit-relocs-msmall-data-mlarge-data-msmall-text-mlarge-text-mmemory-latency=time
โจ eBPF Options โจ
eBPF flags, bestie, they're giving tech-girl energy ๐โจ
-mbig-endian-mlittle-endian-mkernel=version-mframe-limit=bytes-mxbpf-mco-re-mno-co-re-mjmpext-mjmp32-malu32-mcpu=version
โจ FR30 Options โจ
Just two for FR30, and they're both pretty ๐
-msmall-model-mno-lsim
โจ FT32 Options โจ
FT32 keeps it short and iconic ๐ฆ
-msim-mlra-mnodiv-mft32b-mcompress-mnopm
โจ FRV Options โจ
FRV has a whole lineup, periodt ๐
-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 โจ
The GNU/Linux flags are next, and they're so relatable ๐ซถ
-mglibc-muclibc-mmusl-mbionic-mandroid-tno-android-cc-tno-android-ld
โจ H8/300 Options โจ
H8/300 time, and it's a cute little set ๐ธ
-mrelax-mh-ms-mn-mexr-mno-exr-mint32-malign-300
โจ HPPA Options โจ
HPPA is up next, and it has a lot going on โจ
-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 โจ
IA-64 is a big, dramatic moment ๐ฅ Buckle up, bestie:
-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 โจ
LM32 is short and sweet ๐ง
-mbarrel-shift-enabled-mdivide-enabled-mmultiply-enabled-msign-extend-enabled-muser-enabled
โจ M32R/D Options โจ
M32R/D flags coming through ๐
-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 โจ
Just three for M32C ๐
-mcpu=cpu-msim-memregs=number
โจ M680x0 Options โจ
M680x0 is a whole throwback era, and it's so iconic ๐
-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 โจ
MCore is the last stretch of this part, and it's a fun one ๐
-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 โจ
And we close out with MeP ๐ A big finish, bestie:
-mabsdiff-mall-opts-maverage-mbased=n-mbitops-mc=n-mclip-mconfig=name-mcop-mcop32-mcop64-mivc2-mdc-mdiv-meb-mel-mio-volatile-ml-mleadz-mm-mminmax-mmult-mno-opts-mrepeat-ms-msatur-msdram-msim-msimnovec-mtf-mtiny=n
๐ฆ MicroBlaze Options ๐ฆ
Okay bestie, the MicroBlaze squad is up first and they're all giving main character energy ๐
-msoft-float-mhard-float-msmall-divides-mcpu=cpu-mmemcpy-mxl-soft-mul-mxl-soft-div-mxl-barrel-shift-mxl-pattern-compare-mxl-stack-check-mxl-gp-opt-mno-clearbss-mxl-multiply-high-mxl-float-convert-mxl-float-sqrt-mbig-endian-mlittle-endian-mxl-reorder-mxl-mode-app-model-mpic-data-is-text-relative
๐ธ MIPS Options ๐ธ
The MIPS section is literally huge, so grab a snack ๐ Every flag is here, no skipping ๐
-EL-EB-march=arch-mtune=arch-mips1-mips2-mips3-mips4-mips32-mips32r2-mips32r3-mips32r5-mips32r6-mips64-mips64r2-mips64r3-mips64r5-mips64r6-mips16-mno-mips16-mflip-mips16-minterlink-compressed-mno-interlink-compressed-minterlink-mips16-mno-interlink-mips16-mabi=abi-mabicalls-mno-abicalls-mshared-mno-shared-mplt-mno-plt-mxgot-mno-xgot-mgp32-mgp64-mfp32-mfpxx-mfp64-mhard-float-msoft-float-mno-float-msingle-float-mdouble-float-modd-spreg-mno-odd-spreg-mabs=mode-mnan=encoding-mdsp-mno-dsp-mdspr2-mno-dspr2-mmcu-mmno-mcu-meva-mno-eva-mvirt-mno-virt-mxpa-mno-xpa-mcrc-mno-crc-mginv-mno-ginv-mmicromips-mno-micromips-mmsa-mno-msa-mloongson-mmi-mno-loongson-mmi-mloongson-ext-mno-loongson-ext-mloongson-ext2-mno-loongson-ext2-mfpu=fpu-type-msmartmips-mno-smartmips-mpaired-single-mno-paired-single-mdmx-mno-mdmx-mips3d-mno-mips3d-mmt-mno-mt-mllsc-mno-llsc-mlong64-mlong32-msym32-mno-sym32-Gnum-mlocal-sdata-mno-local-sdata-mextern-sdata-mno-extern-sdata-mgpopt-mno-gopt-membedded-data-mno-embedded-data-muninit-const-in-rodata-mno-uninit-const-in-rodata-mcode-readable=setting-msplit-addresses-mno-split-addresses-mexplicit-relocs-mno-explicit-relocs-mcheck-zero-division-mno-check-zero-division-mdivide-traps-mdivide-breaks-mload-store-pairs-mno-load-store-pairs-munaligned-access-mno-unaligned-access-mmemcpy-mno-memcpy-mlong-calls-mno-long-calls-mmad-mno-mad-mimadd-mno-imadd-mfused-madd-mno-fused-madd-nocpp-mfix-24k-mno-fix-24k-mfix-r4000-mno-fix-r4000-mfix-r4400-mno-fix-r4400-mfix-r5900-mno-fix-r5900-mfix-r10000-mno-fix-r10000-mfix-rm7000-mno-fix-rm7000-mfix-vr4120-mno-fix-vr4120-mfix-vr4130-mno-fix-vr4130-mfix-sb1-mno-fix-sb1-mflush-func=func-mno-flush-func-mbranch-cost=num-mbranch-likely-mno-branch-likely-mcompact-branches=policy-mfp-exceptions-mno-fp-exceptions-mvr4130-align-mno-vr4130-align-msynci-mno-synci-mlxc1-sxc1-mno-lxc1-sxc1-mmadd4-mno-madd4-mrelax-pic-calls-mno-relax-pic-calls-mmcount-ra-address-mframe-header-opt-mno-frame-header-opt
๐ง MMIX Options ๐ง
-mlibfuncs-mno-libfuncs-mepsilon-mno-epsilon-mabi=gnu-mabi=mmixware-mzero-extend-mknuthdiv-mtoplevel-symbols-melf-mbranch-predict-mno-branch-predict-mbase-addresses-mno-base-addresses-msingle-exit-mno-single-exit
๐ MN10300 Options ๐
-mmult-bug-mno-mult-bug-mno-am33-mam33-mam33-2-mam34-mtune=cpu-type-mreturn-pointer-on-d0-mno-crt0-mrelax-mliw-msetlb
๐ Moxie Options ๐
-meb-mel-mmul.x-mno-crt0
๐ซถ MSP430 Options ๐ซถ
-msim-masm-hex-mmcu=-mcpu=-mlarge-msmall-mrelax-mwarn-mcu-mcode-region=-mdata-region=-msilicon-errata=-msilicon-errata-warn=-mhwmult=-minrt-mtiny-printf-mmax-inline-shift=
๐ NDS32 Options ๐
-mbig-endian-mlittle-endian-mreduced-regs-mfull-regs-mcmov-mno-cmov-mext-perf-mno-ext-perf-mext-perf2-mno-ext-perf2-mext-string-mno-ext-string-mv3push-mno-v3push-m16bit-mno-16bit-misr-vector-size=num-mcache-block-size=num-march=arch-mcmodel=code-model-mctor-dtor-mrelax
โญ Nios II Options โญ
-G num-mgpopt=option-mgpopt-mno-gpopt-mgprel-sec=regexp-mr0rel-sec=regexp-mel-meb-mno-bypass-cache-mbypass-cache-mno-cache-volatile-mcache-volatile-mno-fast-sw-div-mfast-sw-div-mhw-mul-mno-hw-mul-mhw-mulx-mno-hw-mulx-mno-hw-div-mhw-div-mcustom-insn=N-mno-custom-insn-mcustom-fpu-cfg=name-mhal-msmallc-msys-crt0=name-msys-lib=name-march=arch-mbmx-mno-bmx-mcdx-mno-cdx
๐ฅ Nvidia PTX Options ๐ฅ
-m64-mmainkernel-moptimize
๐ OpenRISC Options ๐
-mboard=name-mnewlib-mhard-mul-mhard-div-msoft-mul-msoft-div-msoft-float-mhard-float-mdouble-float-munordered-float-mcmov-mror-mrori-msext-msfimm-mshftimm-mcmodel=code-model
๐ PDP-11 Options ๐
-mfpu-msoft-float-mac0-mno-ac0-m40-m45-m10-mint32-mno-int16-mint16-mno-int32-msplit-munix-asm-mdec-asm-mgnu-asm-mlra
๐ฆ picoChip Options ๐ฆ
-mae=ae_type-mvliw-lookahead=N-msymbol-as-address-mno-inefficient-warnings
๐ธ PowerPC Options ๐ธ
Quick heads-up, these live with the next squad, so just peek at RS/6000 and PowerPC Options below ๐
โจ 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-misa-spec=ISA-spec-string-march=ISA-string-mtune=processor-string-mpreferred-stack-boundary=num-msmall-data-limit=N-bytes-msave-restore-mno-save-restore-mshorten-memrefs-mno-shorten-memrefs-mstrict-align-mno-strict-align-mcmodel=medlow-mcmodel=medany-mexplicit-relocs-mno-explicit-relocs-mrelax-mno-relax-mriscv-attribute-mmo-riscv-attribute-malign-data=type-mbig-endian-mlittle-endian-mstack-protector-guard=guard-mstack-protector-guard-reg=reg-mstack-protector-guard-offset=offset
๐ RL78 Options ๐
-msim-mmul=none-mmul=g13-mmul=g14-mallregs-mcpu=g10-mcpu=g13-mcpu=g14-mg10-mg13-mg14-m64bit-doubles-m32bit-doubles-msave-mduc-in-interrupts
๐ธ RS/6000 and PowerPC Options ๐ธ
This is the big one, bestie, the whole PowerPC family is in 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 ๐ธ
Okay bestie, first up is the SPARC crew ๐ yes it's a LOT of flags, but every single one is here, no cap โจ
-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 ๐
the old-school System V flags, lowkey iconic ๐
-Qy -Qn -YP,paths -Ym,dir
๐ฆ TILE-Gx Options ๐ฆ
the TILE-Gx set, serving endianness realness ๐
-mcpu=CPU -m32 -m64 -mbig-endian -mlittle-endian -mcmodel=code-model
๐ง TILEPro Options ๐ง
small but mighty, the TILEPro flags ๐
-mcpu=cpu -m32
๐ V850 Options ๐
the V850 list is giving main character energy, no cap ๐ฅ
-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 flags, short and sweet ๐
-mg -mgnu -munix -mlra
๐ซง Visium Options ๐ซง
the Visium set, ngl it's a vibe โจ
-mdebug -msim -mfpu -mno-fpu -mhard-float -msoft-float -mcpu=cpu-type
-mtune=cpu-type -msv-mode -muser-mode
๐ VMS Options ๐
the VMS crew, lowkey dramatic about return codes and pointers ๐
-mvms-return-codes -mdebug-main=prefix -mmalloc64 -mpointer-size=size
๐ VxWorks Options ๐
VxWorks has its own little squad ๐ฆ
-mrtp -non-static -Bstatic -Bdynamic -Xbind-lazy -Xbind-now
๐ x86 Options ๐
okay the x86 list is HUGE and it's also the most iconic one, so buckle up ๐ญ every flag is here, just the way it's written in the page:
-mtune=cpu-type -march=cpu-type -mtune-ctrl=feature-list -mdump-tune-features
-mno-default -mfpmath=unit -masm=dialect -mno-fancy-math-387 -mno-fp-ret-in-387
-m80387 -mhard-float -msoft-float -mno-wide-multiply -mrtd -malign-double
-mpreferred-stack-boundary=num -mincoming-stack-boundary=num -mcld -mcx16
-msahf -mmovbe -mcrc32 -mmwait -mrecip -mrecip=opt -mvzeroupper
-mprefer-avx128 -mprefer-vector-width=opt -mmove-max=bits -mstore-max=bits
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx -mavx2
-mavx512f -mavx512pf -mavx512er -mavx512cd -mavx512vl -mavx512bw
-mavx512dq -mavx512ifma -mavx512vbmi -msha -maes -mpclmul -mfsgsbase
-mrdrnd -mf16c -mfma -mpconfig -mwbnoinvd -mptwrite -mprefetchwt1
-mclflushopt -mclwb -mxsavec -mxsaves -msse4a -m3dnow -m3dnowa -mpopcnt
-mabm -mbmi -mtbm -mfma4 -mxop -madx -mlzcnt -mbmi2 -mfxsr -mxsave
-mxsaveopt -mrtm -mhle -mlwp -mmwaitx -mclzero -mpku -mthreads -mgfni
-mvaes -mwaitpkg -mshstk -mmanual-endbr -mforce-indirect-call
-mavx512vbmi2 -mavx512bf16 -menqcmd -mvpclmulqdq -mavx512bitalg
-mmovdiri -mmovdir64b -mavx512vpopcntdq -mavx5124fmaps -mavx512vnni
-mavx5124vnniw -mprfchw -mrdpid -mrdseed -msgx -mavx512vp2intersect
-mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset
-mavxvnni -mavx512fp16 -mcldemote -mms-bitfields -mno-align-stringops
-minline-all-stringops -minline-stringops-dynamically
-mstringop-strategy=alg -mkl -mwidekl -mmemcpy-strategy=strategy
-mmemset-strategy=strategy -mpush-args -maccumulate-outgoing-args
-m128bit-long-double -m96bit-long-double -mlong-double-64 -mlong-double-80
-mlong-double-128 -mregparm=num -msseregparm -mveclibabi=type
-mvect8-ret-in-mem -mpc32 -mpc64 -mpc80 -mstackrealign
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs
-mcmodel=code-model -mabi=name -maddress-mode=mode -m32 -m64
-mx32 -m16 -miamcu -mlarge-data-threshold=num -msse2avx -mfentry
-mrecord-mcount -mnop-mcount -m8bit-idiv -minstrument-return=type
-mfentry-name=name -mfentry-section=name
-mavx256-split-unaligned-load -mavx256-split-unaligned-store
-malign-data=type -mstack-protector-guard=guard
-mstack-protector-guard-reg=reg
-mstack-protector-guard-offset=offset
-mstack-protector-guard-symbol=symbol -mgeneral-regs-only
-mcall-ms2sysv-xlogues -mrelax-cmpxchg-loop -mindirect-branch=choice
-mfunction-return=choice -mindirect-branch-register
-mharden-sls=choice -mindirect-branch-cs-prefix -mneeded
-mno-direct-extern-access
๐ช x86 Windows Options ๐ช
the Windows x86 crew, bringing the drama ๐ซถ
-mconsole -mcygwin -mno-cygwin -mdll -mnop-fun-dllimport -mthread -municode
-mwin32 -mwindows -fno-set-stack-executable
๐ธ Xstormy16 Options ๐ธ
just one flag for the Xstormy16 lol, simple is slay ๐
-msim
๐ง Xtensa Options ๐ง
the Xtensa list is long and honestly kind of a whole personality ๐ฎ
-mconst16 -mno-const16 -mfused-madd -mno-fused-madd -mforce-no-pic
-mserialize-volatile -mno-serialize-volatile -mtext-section-literals
-mno-text-section-literals -mauto-litpools -mno-auto-litpools
-mtarget-align -mno-target-align -mlongcalls -mno-longcalls -mabi=abi-type
๐ zSeries Options ๐
- zSeries Options โ no list here, just go check out S/390 and zSeries Options ๐ซถ
โจ Options Controlling the Kind of Output โจ
okay so compiling can have up to four stages: preprocessing, compilation proper, assembly, and linking, and they always happen in that order ๐ gcc can preprocess and compile a bunch of files into several assembler input files, or into one assembler input file. Then each assembler input file makes an object file, and linking mashes all the object files together (the ones just compiled and the ones you handed it) into an executable file ๐
For any given input file, the file name suffix decides what kind of compilation happens ๐ธ
๐ Input file suffixes
file.cโ C source code that has to be preprocessed ๐ทfile.iโ C source code that should not be preprocessed ๐ซงfile.iiโ C++ source code that should not be preprocessed ๐ฆfile.mโ Objective-C source code. Heads up, you have to link with thelibobjclibrary to make an Objective-C program work ๐ฅfile.miโ Objective-C source code that should not be preprocessed ๐file.mm,file.Mโ Objective-C++ source code. Same deal, you must link with thelibobjclibrary for an Objective-C++ program to work. Also,.Mmeans a literal capital M ๐file.miiโ Objective-C++ source code that should not be preprocessed โจfile.hโ C, C++, Objective-C, or Objective-C++ header file that gets turned into a precompiled header (that's the default), or a C or C++ header file 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 code that must be preprocessed. Careful with.cxx, the last two letters must both be literallyx. And.Cmeans a literal capital C ๐file.mm,file.Mโ Objective-C++ source code that must be preprocessed (yep, it's listed again) ๐file.miiโ Objective-C++ source code that should not be preprocessed (also listed again, iykyk) ๐ฆfile.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ header file that gets turned into a precompiled header or an Ada spec ๐file.f,file.for,file.ftnโ Fixed form Fortran source code that should not be preprocessed ๐ธfile.F,file.FOR,file.fpp,file.FPP,file.FTNโ Fixed form Fortran source code that must be preprocessed (with the traditional preprocessor) ๐ซถfile.f90,file.f95,file.f03,file.f08โ Free form Fortran source code that should not be preprocessed ๐file.F90,file.F95,file.F03,file.F08โ Free form Fortran source code that must be preprocessed (with the traditional preprocessor) ๐file.goโ Go source code ๐นfile.dโ D source code ๐ฎfile.diโ D interface file ๐file.ddโ D documentation code (Ddoc) ๐file.adsโ Ada source code file that 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 code file with 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 gets treated this way ๐ฆ
You can tell the input language yourself with the -x option ๐
๐ Picking a language with -x
-x languageโ Explicitly sets the language for the input files that come after it, instead of letting the compiler guess a default from the file name suffix. It sticks for every following input file until the next-xshows up. 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
-x noneโ Turns off any language setting, so the files that follow are handled by their file name suffixes, exactly like if-xhad never been used at all ๐ท
If you only want some of the stages, use -x (or filename suffixes) to tell gcc where to start, and one of -c, -S, or -E to say where gcc should stop ๐ฆ
Heads up bestie โ ๏ธ some combinations, for example-x cpp-output -E, tellgccto do absolutely nothing at all ๐
๐ง Stopping early with -c, -S, or -E
-cโ Compiles or assembles the source files, but does not link ๐ The linking stage just doesn't happen, and the ultimate output is an object file for each source file.- By default, the object file name for a source file is made by replacing the suffix
.c,.i,.s, etc., with.o. - Unrecognized input files, which don't need compilation or assembly, are ignored.
- By default, the object file name for a source file is made by replacing the suffix
-Sโ Stops after the compilation proper and does not assemble ๐ซง The output is an assembler code file for each non-assembler input file you specified.- By default, the assembler file name for a source file is made by replacing the suffix
.c,.i, etc., with.s. - Input files that don't need compilation are ignored.
- By default, the assembler file name for a source file is made by replacing the suffix
-Eโ Stops after the preprocessing stage and doesn't run the compiler proper ๐ The output is preprocessed source code, which gets sent to the standard output.- Input files that don't need preprocessing are ignored.
-o file ๐
Okay bestie, -o is how you tell GCC where the primary output goes ๐ That could be an executable, an object file, an assembler file, or preprocessed C code. It's all the same to -o โจ
If you skip -o, GCC picks the spots itself ๐ธ An executable lands in a.out, the object file for source.suffix goes in source.o, its assembler file goes in source.s, a precompiled header goes in source.suffix.gch, and all preprocessed C source gets dumped on standard output. ๐
Here's the lowkey twist: even though -o only names the primary output, it also changes what your auxiliary and dump outputs are called ๐ฆ (see the examples below, they're giving clarity). Unless you override it, those extra files land in the same directory as the primary output ๐ง For auxiliary outputs, the input file's suffix gets swapped for the suffix of the aux file type. For dump outputs, the dump file's suffix gets tacked onto the input file's suffix ๐ซถ
In compile-only commands, the base name of both aux and dump outputs is the base name of the primary output. In compile and link commands, it's the primary output name minus the executable suffix, combined with the input file name. If both sides share the same base name (ignoring the suffix), the result is just that base name. Otherwise they get smooshed together with a dash between them โจ
Example:
gcc -c foo.c ...
This one uses foo.o as the primary output and puts aux outputs and dumps right next to it. For instance, the aux file foo.dwo shows up for -gsplit-dwarf, and the dump file foo.c.???r.final shows up for -fdump-rtl-final ๐
If you explicitly give a non-linker output file, aux and dump files take the same base name by default, which is very main character of them ๐
Example:
gcc -c foo.c -o dir/foobar.o ...
This will name aux outputs dir/foobar.* and dump outputs dir/foobar.c.* ๐
A linker output works differently, though ๐ It prefixes the aux and dump outputs instead:
gcc foo.c bar.c -o dir/foobar ...
This will generally name aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and dump outputs dir/foobar-foo.c.* and dir/foobar-bar.c.* ๐ฆ
The one exception is when the executable shares its base name with the single input:
gcc foo.c -o dir/foo ...
Here, aux outputs are named dir/foo.* and dump outputs are named 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 sets the base name for aux and dump files, but it does not change the name of the primary output file ๐ Intermediate outputs that get preserved aren't primary outputs anymore. They count as auxiliary outputs instead โจ
Check this out:
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. Meanwhile:
gcc -save-temps -dumpbase save-foo -c foo.c
This preprocesses into save-foo.i, compiles to save-foo.s (now an intermediate, so it's auxiliary), and then assembles to the (implied) output file foo.o ๐ง
Without this option, dump and aux files take their names from the input file, or from the (non-linker) output file if you explicitly named one. Dump output files, like the ones requested by -fdump-* options, keep the input name's suffix. Aux output files, the ones requested by other non-dump options like "-save-temps", "-gsplit-dwarf", and "-fcallgraph-info", drop it ๐ซถ
If you want that same suffix differentiation for an explicit -dumpbase basename.suf, just also add -dumpbase-ext .suf ๐
If dumpbase is explicitly given with any directory component, then any dumppfx specification (like -dumpdir or -save-temps=*) gets ignored. dumpbase doesn't append to it, it fully overrides it ๐
โโ๏ธ
Example:
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.*, and it completely ignores dir/ from -o, the ./ prefix implied by -save-temps=cwd, and pfx- from -dumpdir ๐
When -dumpbase shows up in a command that compiles multiple inputs, or one that compiles and then links, it can be combined with a dumppfx, just like under -dumpdir. Each input file then gets compiled using the combined dumppfx, and default values for dumpbase and auxdropsuf get computed for each input file ๐
Example:
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs. To avoid overwriting the aux and dump outputs, it uses the dumpbase as a prefix, so you get aux and dump outputs named main-foo.* and main-bar.* โจ
An empty string given as dumpbase stops the output basename from affecting how aux and dump outputs are named during compilation. The default values get computed instead ๐
gcc -c foo.c -o dir/foobar.o -dumpbase " ...
This will name aux outputs dir/foo.* and dump outputs dir/foo.c.*. Notice how the basenames come from the input name, but the directory still defaults to the output's directory ๐ฆ
An empty-string dumpbase does not stop the output basename from being used during linking, though ๐ง
gcc foo.c bar.c -o dir/foobar -dumpbase " -flto ...
The compilation of the source files names aux outputs dir/foo.* and dir/bar.*, and 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 GCC forms the name of an auxiliary output file (not a dump file), it drops the trailing auxdropsuf from dumpbase before adding any suffixes ๐ If you don't specify it, it defaults to the suffix of a default dumpbase. That means the suffix of the input file when -dumpbase isn't on the command line, or when the dumpbase is combined with a dumppfx โจ
Example:
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 puts auxiliary outputs in dir/x-foo.*. It takes the location from the primary output and drops the .c suffix from the dumpbase. Dump outputs keep the suffix, so they end up as dir/x-foo.c.* ๐
This option gets ignored if it doesn't match the suffix of a specified dumpbase. The one exception is when it's used as an alternative to the executable suffix while appending the linker output base name to dumppfx, as described below ๐
gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
This creates main.out as the primary output. To avoid overwriting aux and dump outputs, it uses 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 forming the name of an auxiliary or dump output file, this uses dumppfx as a prefix ๐
gcc -dumpdir pfx- -c foo.c ...
This creates foo.o as the primary output and auxiliary outputs named pfx-foo.*. It combines the given dumppfx with the default dumpbase, which comes from the default primary output, which in turn comes from the input name. Dump outputs also take the input name suffix, so they're pfx-foo.c.* โจ
If you want dumppfx to act 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 auxiliary outputs named dir/bar.*. It combines the given dumppfx with the default dumpbase derived from the primary output name. Dump outputs also take the input name suffix, so they're dir/bar.c.* ๐
By default, dumppfx is the location of the output file, unless the output file is a special file like "/dev/null". The options -save-temps=cwd and -save-temps=obj override this default, just like an explicit -dumpdir does. If more than one of these shows up, the last one wins ๐ซถ
gcc -dumpdir pfx- -c foo.c -save-temps=obj ...
This outputs foo.o, with auxiliary outputs named foo.*, because -save-temps=* overrides the dumppfx from the earlier -dumpdir option. It doesn't matter that =obj is 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 multiple input files and specify -dumpbase, the dumpbase (minus an auxdropsuf suffix) plus a dash gets appended to the explicit or defaulted dumppfx. If the dumpbase contains any directory components, it overrides the dumppfx instead. This way, each of the multiple compilations gets its own differently named aux and dump outputs ๐
gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
This sends auxiliary dumps to dir/pfx-main-foo.* and dir/pfx-main-bar.*, appending dumpbase- to dumppfx. Dump outputs keep the input file suffix: dir/pfx-main-foo.c.* and dir/pfx-main-bar.c.*, respectively ๐ง
Now contrast that with single-input compilation:
gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
Applying -dumpbase to a single source doesn't compute and append a separate dumpbase per input file. Its auxiliary and dump outputs go in dir/pfx-main.* ๐ธ
When you compile and then link from multiple input files, a defaulted or explicitly specified dumppfx also gets the dumpbase- transformation above. The compilation of foo.c and bar.c above is an example, just without -c. If you give neither -dumpdir nor -dumpbase, then the linker output base name, minus auxdropsuf if you specified it (or the executable suffix otherwise), plus a dash, gets appended to the default dumppfx instead ๐ Heads up, though, this is different from the earlier linking cases:
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
This does not append the output name main to dumppfx, because -dumpdir was explicitly specified. The idea is that an explicit dumppfx can contain the output name as part of the prefix, if that's what you want. Only an explicitly specified -dumpbase would get combined with it, so that a meaningful option doesn't just get thrown away ๐
When you compile and then link from a single input file, the linker output base name only gets appended to the default dumppfx (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 when an explicit -dumpdir stops the combination from happening, even if -save-temps=* overrides it:
gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
Okay so, auxiliary outputs get named foo.*, and dump outputs get named foo.c.*, and both land in the current working directory when you ask for it with -save-temps=cwd ๐โจ
Here's the big-picture version (a little fuzzy, but the vibe is 100% right ๐
). The primary output name gets split into a directory part and a basename part. dumppfx gets set to the directory part, unless you override it with -dumpdir or -save-temps=*. dumpbase gets set to the basename part, unless you override it with -dumpbase. If there are multiple inputs or you're linking, this dumpbase can get combined with dumppfx and pulled from each input file ๐งฉ. Auxiliary output names for each input are formed by smooshing together dumppfx, dumpbase minus its suffix, and the auxiliary output suffix. Dump output names are only different in that they keep the suffix from dumpbase ๐ธ
Now for LTO recompilation ๐ฆ: a combo of dumppfx and dumpbase gets passed down to lto-wrapper as a -dumpdir option. That combo can be whatever you gave, or something derived from the linker output name (but never from the inputs), even in cases where it wouldn't otherwise get used that way. A trailing period takes the place of the compiler-added dash, if there is one. Since gcc is involved in linking, it doesn't normally get any -dumpbase or -dumpbase-ext, and it ignores them ๐
When lto-wrapper runs sub-compilers, it tacks LTO stage names onto the dumppfx it received, makes sure that thing has a directory component so it overrides any -dumpdir, and passes the result along as -dumpbase to the sub-compilers ๐
-vโ Prints (on standard error) the commands run for each stage of compilation. It also prints the version number of the compiler driver program, plus the preprocessor and the compiler proper ๐ฃ-###โ Like-v, except nothing actually runs, and arguments only get quoted unless they're made of alphanumeric characters or"./-_". Super handy for shell scripts that want to snag the command lines the driver generates ๐ค--helpโ Prints (on standard output) a description of the command-line options gcc understands. If-vis also specified,--helpgets passed on to the various processes gcc invokes too, so they can show the options they accept. If-Wextrawas specified too (before--help), then options with no documentation get displayed as well ๐--target-helpโ Prints (on standard output) a description of the target-specific command-line options for each tool. For some targets, extra target-specific info may get printed too ๐ฏ--help={class|[^]qualifier}[,...]โ Prints (on standard output) a description of the command-line options the compiler understands that fit into all the classes and qualifiers you specify. These 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 are not shown, because those tools don't currently support the extended--help=syntax ๐ โโ๏ธparamsโ Shows the values recognized by--param๐ง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 ๐
And here are the qualifiers, bestie:
undocumentedโ Shows only the options that are undocumented ๐ซฅjoinedโ Shows options that take an argument appearing after an equal sign in the same continuous piece of text, like--help=target๐separateโ Shows options that take an argument appearing as a separate word right after the original option, like-o output-fileโ๏ธ
Thus, for example, to display all the undocumented target-specific switches the compiler supports, use:
--help=target,undocumented
The sense of a qualifier can be flipped by putting the ^ character in front of it. So, for example, to display all the binary warning options (the ones that are either on or off and don't take an argument) that have a description, use:
--help=warnings,^joined,^undocumented
Heads up: the argument to --help= should not consist solely of inverted qualifiers ๐ซ
Combining several classes is possible, although it usually narrows the output so much that there's nothing to display ๐ซ . One case where it does work is when one of the classes is target. For example, to display all the target-specific optimization options, use:
--help=target,optimizers
The --help= option can be repeated on the command line. Each successive use displays its requested class of options, skipping any that have already been displayed ๐. If --help is also specified anywhere on the command line, then it takes precedence over any --help= option ๐
If the -Q option appears on the command line before the --help= option, then the descriptive text displayed by --help= changes ๐ช. Instead of describing the options, it shows 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 it's possible to find out which optimizations are enabled at -O2 by using:
-Q -O2 --help=optimizers
Or, alternatively, you can discover which binary optimizations are enabled by -O3 by using:
gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
diff /tmp/O2-opts /tmp/O3-opts | grep enabled
--versionโ Displays the version number and copyrights of the GCC you invoked ๐-pass-exit-codesโ Normally, the gcc program exits with the code of 1 if any phase of the compiler returns a non-success return code. If you specify-pass-exit-codes, gcc instead returns the numerically highest error produced by any phase that returns an error indication. The C, C++, and Fortran front ends return 4 if an internal compiler error is encountered ๐ฅ-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 the gcc driver uses when deciding which switches to pass tocc1,cc1plus,as,ld, etc. You can use 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 get passed as a comma separated list ๐
gcc -c t.c -wrapper gdb,--args
This invokes all subprograms of gcc under gdb --args, so the invocation of cc1 is gdb --args cc1 .... ๐
-ffile-prefix-map=old=newโ When compiling files living in directory old, records any references to them in the result of the compilation as if the files lived in directory new instead. Specifying this option is equivalent to specifying all the individual-f*-prefix-mapoptions. This is great for reproducible builds that are location independent ๐บ๏ธ. See also-fmacro-prefix-map,-fdebug-prefix-mapand-fprofile-prefix-map.-fplugin=name.soโ Loads the plugin code in file name.so, which is assumed to be a shared object to bedlopen'd by the compiler ๐งฉ. The base name of the shared object file is used to identify the plugin for argument parsing (see-fplugin-arg-name-key=valuebelow). Each plugin should define the callback functions specified in the Plugins API.-fplugin-arg-name-key=valueโ Defines an argument called key with a value of value for the plugin called name ๐-fdump-ada-spec[-slim]โ For C and C++ source and include files, generates corresponding Ada specs ๐ฆ-fada-spec-parent=unitโ Used together with-fdump-ada-spec[-slim]above, this generates Ada specs as child units of parent unit ๐ถ-fdump-go-spec=fileโ For input files in any language, generates corresponding Go declarations in file. This generates Go"const","type","var", and"func"declarations, which can be a 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, then the option is treated literally and not removed ๐ซฃ
Options in file are separated by whitespace. A whitespace character can be included in an option by wrapping the entire option in either single or double quotes. Any character (including a backslash) can be included by putting a backslash in front of it. The file can even contain more @file options of its own, and those get processed recursively ๐
โจ Compiling C++ Programs โจ
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx ๐. C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc, 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, this is where g++ comes in โจ. It's a program that calls GCC and automatically specifies linking against the C++ library, so you don't have to think about it ๐. It also treats .c, .h and .i files as C++ source files instead of C source files, unless you use -x ๐
. It's super handy for precompiling a C header file with a .h extension for use in C++ compilations ๐ง. On lots of systems, g++ is also installed under the name c++ ๐ธ.
When you compile C++ programs, you can use a lot 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++ ๐. Mix and match, it's giving versatile.
๐ Options Controlling C Dialect ๐
The following options control the dialect of C (or languages derived from C, such as C++, Objective-C and Objective-C++) that the compiler accepts ๐:
-ansiโ In C mode this is 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 (for C code) or standard C++ (for C++ code), like theasmandtypeofkeywords, and predefined macros such asunixandvaxthat identify what kind of system you're on. It also turns on the undesirable and rarely used ISO trigraph feature ๐. For the C compiler, it also disables recognition of C++ style//comments as well as theinlinekeyword.
The alternate keywords __asm__, __extension__, __inline__ and __typeof__ keep working even with -ansi. You wouldn't want them in an ISO C program, obviously ๐, but they're useful in header files that might get included in -ansi builds. Alternate predefined macros like __unix__ and __vax__ are available too, with or without -ansi.
-ansi doesn't reject non-ISO programs gratuitously. For that, you need -Wpedantic in addition to -ansi ๐ง.
The macro __STRICT_ANSI__ is predefined when -ansi is used. Some header files notice it and skip declaring certain functions or defining certain macros that ISO doesn't ask for, so they don't interfere with programs using those names for other things ๐ซถ.
Functions that are normally built in but have no semantics defined by ISO C (like alloca and ffs) are not built-in functions when -ansi is used.
-std=โ Determines the language standard. This option is only supported when compiling C or C++ ๐.
The compiler can accept several base standards, like c90 or c++98, plus GNU dialects of those, like gnu90 or gnu++98. With a base standard, the compiler accepts all programs following that standard plus GNU extensions that don't contradict it. For example, -std=c90 turns off GCC features that clash with ISO C90, like the asm and typeof keywords, but keeps other GNU extensions that don't mean anything in ISO C90, like leaving out the middle term of a ?: expression. With a GNU dialect, though, every feature the compiler supports gets enabled, even when those features change the meaning of the base standard. So some strictly conforming programs may get rejected ๐ฌ. -Wpedantic uses the chosen standard to figure out which features are GNU extensions for that version. For example, -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic does not.
A value for this option must be provided. Possible values are:
c90,c89,iso9899:1990โ Supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code.iso9899:199409โ ISO C90 as modified in amendment 1.c99,c9x,iso9899:1999,iso9899:199xโ ISO C99. This standard is substantially completely supported, modulo bugs and floating-point issues (mainly but not entirely relating to optional C99 features from Annexes F and G). See<https://gcc.gnu.org/c99status.html>for more information. The namesc9xandiso9899:199xare deprecated.c11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard. This standard is substantially completely supported, modulo bugs, floating-point issues (mainly but not entirely relating to optional C11 features from Annexes F and G) and the optional Annexes K (Bounds-checking interfaces) and L (Analyzability). The namec1xis deprecated.c17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision of the ISO C standard (published in 2018). This standard is the same as C11 except for corrections of defects (all of which are also applied with-std=c11) and a new value of__STDC_VERSION__, so it's supported to the same extent as C11.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.
-aux-info filenameโ Outputs prototyped declarations for all functions declared and/or defined in a translation unit, including those in header files, to the given filename ๐. This option is silently ignored in any language other than C.
Besides declarations, the file notes in comments the origin of each declaration (source file and line). It also shows whether each declaration was implicit, prototyped or unprototyped (I, N for new or O for old, respectively, in the first character after the line number and the colon), and whether it came from a declaration or a definition (C or F, 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 isn't very useful, since it's not possible to read the arguments. This is only supported for C, as this construct is allowed by C++.
-fno-asmโ Doesn't recognizeasm,inlineortypeofas keywords, so code can use these words as identifiers. You can use the keywords__asm__,__inline__and__typeof__instead. In C,-ansiimplies-fno-asm.
In C++, inline is a standard keyword and isn't affected by this switch. You may want to use the -fno-gnu-keywords flag instead, which disables typeof but not asm and inline. In C99 mode (-std=c99 or -std=gnu99), this switch only affects the asm and typeof keywords, since inline is a standard keyword in ISO C99.
-fno-builtin,-fno-builtin-functionโ Doesn't recognize built-in functions whose names don't start with the__builtin_prefix ๐.
GCC normally generates special code to handle certain built-in functions more efficiently โจ. For instance, calls to alloca may become single instructions that adjust the stack directly, and calls to memcpy may become inline copy loops. The resulting code is often both smaller and faster, but since the function calls no longer appear as such, you can't set a breakpoint on those calls, nor can you change the behavior of the functions by linking with a different library ๐ญ. In addition, when a function is recognized as a built-in function, GCC may use information about that function to warn about problems with calls to it, or to generate more efficient code, even if the resulting code still contains calls to that function. For example, warnings are given with -Wformat for bad calls to printf when printf is built in and strlen is known not to modify global memory.
Okay so with -fno-builtin-function, only the built-in version of function gets switched off ๐ function can't begin with __builtin_ ๐ซ. If the function isn't built-in in your GCC version, the option just gets ignored, no drama ๐
. There's no matching -fbuiltin-function option, though. If you want to turn built-ins back on one at a time while using -fno-builtin or -ffreestanding, you can define your own macros like this ๐:
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fcond-mismatchโ This lets conditional expressions have mismatched types in the second and third arguments ๐ฆ. The value of that kind of expression isvoid. ngl, this one is not supported for C++ ๐.-ffreestandingโ Tells GCC that compilation targets a freestanding environment ๐ง. This implies-fno-builtin. Freestanding means the standard library might not exist, and program startup might not be at"main"๐ญ. The most obvious example is an OS kernel ๐. This is equivalent to-fno-hosted.-fgimpleโ Enables parsing of function definitions marked with"__GIMPLE"๐งช. It's experimental, and it exists so you can unit test GIMPLE passes โจ.-fgnu-tmโ When you pass this, GCC generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009) ๐. It's experimental, so the interface may change in future GCC versions as the official spec changes โ ๏ธ. Also, not all architectures are supported for this feature ๐.
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) ๐ซ.
-fgnu89-inlineโ Tells GCC to use the traditional GNU semantics forinlinefunctions when in C99 mode ๐ธ. Using this is roughly equivalent to adding thegnu_inlinefunction attribute to all inline functions.-fno-gnu89-inlineโ Explicitly tells GCC to use the C99 semantics forinlinewhen in C99 orgnu99mode, which is the default behavior ๐ . This option is not supported in-std=c90or-std=gnu90mode.
To check which inline semantics are in effect, you can use the preprocessor macros "__GNUC_GNU_INLINE__" and "__GNUC_STDC_INLINE__" ๐.
-fhostedโ Tells GCC that compilation targets a hosted environment ๐ . This implies-fbuiltin. A hosted environment has the entire standard library available, andmainhas a return type ofint๐. Examples are nearly everything except a kernel. This is equivalent to-fno-freestanding.-flax-vector-conversionsโ Allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types ๐. Honestly? Don't use this for new code ๐ .-fms-extensionsโ Accepts some non-standard constructs used in Microsoft header files ๐ช. In C++ code, this lets member names in structures be similar to previous type declarations. Like this:
typedef int UOW;
struct ABC {
UOW UOW;
};
Also, some cases of unnamed fields in structures and unions are only accepted with this option โจ. Note that this option is off for all targets except for x86 targets using ms-abi ๐ฏ.
-foffload=disable,-foffload=default,-foffload=target-listโ These specify which OpenMP and OpenACC offload targets get code generated ๐ฏ. The default, which is equivalent to-foffload=default, generates code for all supported offload targets ๐ซ.-foffload=disablegenerates code only for the host fallback, while-foffload=target-listgenerates code only for the specified comma-separated list of offload targets ๐งฉ.
Offload targets are written in GCC's internal target-triplet format ๐. Run the compiler with -v to see the list of configured offload targets under "OFFLOAD_TARGET_NAMES" ๐.
-foffload-options=options,-foffload-options=target-triplet-list=optionsโ With-foffload-options=options, GCC passes the specified options to the compilers for all enabled offloading targets ๐. If you want options that only apply to a specific target or targets, use the-foffload-options=target-list=optionsform. The target-list is a comma-separated list in the same format as the-foffload=option.
Typical command lines are:
-foffload-options=-lgfortran -foffload-options=-lm
-foffload-options="-lgfortran -lm" -foffload-options=nvptx-none=-latomic
-foffload-options=amdgcn-amdhsa=-march=gfx906 -foffload-options=-lm
-fopenaccโ Enables handling of OpenACC directives"#pragma acc"in C/C++ and"!$acc"in Fortran ๐งโ๐ป. When this is on, the compiler generates accelerated code according to the OpenACC Application Programming Interface v2.6, which you can look up athttps://www.openacc.orgโจ. This option implies-pthread, so it's only supported on targets that have support for-pthreadโ ๏ธ.-fopenacc-dim=geomโ Specifies default compute dimensions for parallel offload regions that don't explicitly specify their own ๐. Thegeomvalue is a triple of':'-separated sizes, in the order'gang','worker'and'vector'๐งฎ. You can omit a size to use a target-specific default value.-fopenmpโ Enables handling of OpenMP directives"#pragma omp"in C/C++ and"!$omp"in Fortran ๐ท. When this is on, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5, found athttps://www.openmp.org๐งต. This option implies-pthread, so it's only supported on targets that have support for-pthread.-fopenmpalso implies-fopenmp-simd.-fopenmp-simdโ Enables handling of OpenMP's SIMD directives with"#pragma omp"in C/C++ and"!$omp"in Fortran ๐ถ. Other OpenMP directives are ignored.-fpermitted-flt-eval-methods=styleโ ISO/IEC TS 18661-3 defines new permissible values forFLT_EVAL_METHOD๐ง . These say operations and constants with a semantic type that's an interchange or extended format should be evaluated to the precision and range of that type. The new values are a superset of the ones permitted under C99/C11, which doesn't specify the meaning of other positive values ofFLT_EVAL_METHOD. So, code that conforms to C11 may not have been written expecting the new values ๐ซ .
This option decides whether the compiler allows only the FLT_EVAL_METHOD values from C99/C11, or the extended set from ISO/IEC TS 18661-3 ๐
. style is either "c11" or "ts-18661-3", as appropriate. The default in a standards-compliant mode (-std=c11 or similar) is -fpermitted-flt-eval-methods=c11. The default in a GNU dialect (-std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3.
-fplan9-extensionsโ Accepts some non-standard constructs used in Plan 9 code ๐. This enables-fms-extensions, permits passing pointers to structures with anonymous fields to functions that expect pointers to elements of the type of the field, and permits referring to anonymous fields declared using a typedef. This is only supported for C, not C++ ๐ .-fsigned-bitfields,-funsigned-bitfields,-fno-signed-bitfields,-fno-unsigned-bitfieldsโ These control whether a bit-field is signed or unsigned when the declaration doesn't use eithersignedorunsigned๐ข. By default, such a bit-field is signed, because that's consistent: the basic integer types, such asint, are signed types ๐.-fsigned-charโ Lets the typecharbe signed, likesigned char๐. This is equivalent to-fno-unsigned-char, which is the negative form of-funsigned-char. Likewise,-fno-signed-charis equivalent to-funsigned-char.-funsigned-charโ Lets the typecharbe unsigned, likeunsigned char๐. Each kind of machine has a default for whatcharshould be. It's either likeunsigned charby default or likesigned charby default.
Ideally, a portable program should always use signed char or unsigned char when it depends on the signedness of an object ๐งผ. But many programs were written to use plain char and expect it to be signed, or expect it to be unsigned, depending on the machines they were written for ๐. This option, and its inverse, let you make such a program work with the opposite default ๐.
The type char is always a distinct type from each of signed char or unsigned char, even though its behavior is always just like one of those two ๐งฌ.
-fsso-struct=endiannessโ Sets the default scalar storage order of structures and unions to the specified endianness ๐งฑ. The accepted values arebig-endian,little-endianandnative, which is the native endianness of the target and the default. This option is not supported for C++.
Warning: the -fsso-struct switch causes GCC to generate code that is not binary compatible with code generated without it if the specified endianness is not the native endianness of the target ๐จ.
๐ Options Controlling C++ Dialect ๐
This section covers the command-line options that are only meaningful for C++ programs ๐ป. You can 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 supported by GCC ๐ธ.
Some options for compiling C programs, such as -std, are also relevant for C++ programs ๐.
Here is a list of options that are only for compiling C++ programs:
-fabi-version=nโ Uses versionnof the C++ ABI ๐งพ. The default is version0.- Version
0refers to the version conforming most closely to the C++ ABI specification. Therefore, the ABI obtained using version0will change in different versions of G++ as ABI bugs are fixed. - Version
1is the version of the C++ ABI that first appeared in G++ 3.2. - Version
2is the version of the C++ ABI that first appeared in G++ 3.4, and was the default through G++ 4.9. - Version
3corrects an error in mangling a constant address as a template argument.
- Version
Version 4 is where G++ 4.5 dropped a standard mangling for vector types ๐ฆ Version 5 showed up with G++ 4.6 and fixed the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and using a function parameter in the declaration of another parameter ๐
Version 6 came with G++ 4.7 and fixed the promotion behavior of C++11 scoped enums, plus the mangling of template argument packs, const/static_cast, prefix ++ and --, and a class scope function used as a template argument โจ
Version 7 is G++ 4.8's glow-up ๐ธ It treats nullptr_t as a builtin type and fixes the mangling of lambdas in default argument scope.
Version 8 landed with G++ 4.9 and corrected the substitution behavior of function types with function-cv-qualifiers ๐
Version 9 came in with G++ 5.2 and fixed the alignment of "nullptr_t" ๐
Version 10 is from G++ 6.1 and adds mangling for attributes that affect type identity, like ia32 calling convention attributes (e.g. stdcall) ๐ง
Version 11 is from 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 changes starting with the twelfth occurrence. It also implies -fnew-inheriting-ctors.
Version 12 came with G++ 8 and fixed calling conventions for empty classes on the x86_64 target, and for classes with only deleted copy/move constructors. It accidentally changed the calling convention for classes with a deleted copy constructor and a trivial move constructor ๐ญ
Version 13 arrived with G++ 8.2 and fixed that accidental change from version 12 ๐ซถ
Version 14 is G++ 10's contribution and corrects the mangling of the nullptr expression ๐
Version 15 is from G++ 11 and changes the mangling of "__alignof__" so it's distinct from that of "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 you define a symbol with an incorrect one ๐ง This switch picks which ABI version that alias uses. 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 skip this option but do give-Wabi=n, that version gets used for the compatibility aliases. If you give this option along with-Wabi(without a version), the version from this option gets used for the warning ๐-fno-access-controlโ turns off all access checking ๐ It's mainly useful for working around bugs in the access control code.-faligned-newโ enables C++17newfor types that need more alignment thanvoid* ::operator new(std::size_t)provides โจ You can pass a number like-faligned-new=32to say how much alignment (in bytes) that function provides, but honestly few users will need to override the default ofalignof(std::max_align_t). This flag is enabled by default for-std=c++17๐-fchar8_t,-fno-char8_tโ enables support forchar8_tas adopted for C++20 ๐ This adds a brand newchar8_tfundamental type, changes the types of UTF-8 string and character literals, adds new signatures for user-defined literals, comes with associated standard library updates, and adds the new__cpp_char8_tand__cpp_lib_char8_tfeature test macros.
This option lets you overload functions for ordinary and UTF-8 strings ๐ฆ
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
It also introduces new signatures for user-defined literals ๐ธ
int operator""_udl1(char8_t);
int v3 = u8'x'_udl1;
int operator""_udl2(const char8_t*, std::size_t);
int v4 = u8"text"_udl2;
template<typename T, T...> int operator""_udl3();
int v5 = u8"text"_udl3;
โ ๏ธ bestie, the change to the types of UTF-8 string and character literals breaks compatibility with ISO C++11 and later. For example, this 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 byoperator newis non-null before it tries to modify the storage it allocated ๐ Normally this check is unnecessary, since the C++ standard saysoperator newonly returns 0 if it's declaredthrow(). In that case the compiler always checks the return value, even without this option. In all other cases, whenoperator newhas a non-empty exception specification, memory exhaustion is signalled by throwingstd::bad_alloc. See alsonew (nothrow).-fconcepts,-fconcepts-tsโ below-std=c++20,-fconceptsenables support for the C++ Extensions for Concepts Technical Specification, ISO 19217 (2015) ๐ง
With -std=c++20 and above, Concepts are part of the language standard, so -fconcepts defaults to on ๐ But the standard spec for Concepts is pretty different from the TS, so some constructs that were allowed in the TS but didn't make it into the standard can still be enabled with -fconcepts-ts ๐
-fconstexpr-depth=nโ sets the maximum nested evaluation depth for C++11 constexpr functions ton๐ A limit is needed to catch endless recursion during constant expression evaluation. The minimum the standard specifies is 512.-fconstexpr-cache-depth=nโ sets the maximum nesting level of evaluation depth for C++11 constexpr functions that will be cached ton๐ง It's 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 change it, but if your code does heavy constexpr calculations, you might want to experiment to find which value works best for you ๐-fconstexpr-fp-exceptโ okay so Annex F of the C standard says IEC559 floating point exceptions hit at compile time shouldn't stop compilation โจ C++ compilers have historically not followed this, and instead treat floating point division by zero as non-constant, even though it has a well defined value. This flag tells the compiler to give Annex F priority over other rules that say a particular operation is undefined.
constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
-fconstexpr-loop-limit=nโ sets the maximum number of iterations for a loop in C++14 constexpr functions ton๐ A limit is needed to catch 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 number of iterations in a single loop is limited by the loop limit above, you can still get trouble. If there are several nested loops that each have lots of iterations (but are still under that loop limit), or if too many expressions need evaluating in a loop body (or even outside a loop), the constexpr evaluation might take way too long. The default is 33554432 (1<<25).-fcoroutinesโ enables support for the C++ coroutines extension ๐งช This one is still experimental, so proceed with a little caution, bestie.-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 ๐ Using this option turns that optimization off and forces G++ to call the copy constructor in all cases. It also makes G++ call trivial member functions that would otherwise be expanded inline.
In C++17, the compiler is required to omit these temporaries, but this option still affects trivial member functions ๐ซถ
-fno-enforce-eh-specsโ this one is spicy ๐ถ๏ธ It tells G++ not to generate code that checks for violations of exception specifications at run time. This option violates the C++ standard, but it can be useful for shrinking code size in production builds, kind of like definingNDEBUG. It does NOT give your code permission to throw exceptions that break the exception specifications ๐ The compiler still optimizes based on those specifications, so if you throw an unexpected exception, the result is undefined behavior at run time.-fextern-tls-init,-fno-extern-tls-initโ okay so the C++11 and OpenMP standards letthread_localandthreadprivatevariables do dynamic (runtime) initialization ๐ง. To make that work, every use of one of these variables goes through a wrapper function that does any initialization needed. If the use and the definition are in the same translation unit, that overhead can get optimized away ๐ . But if the use is in a different translation unit, there's real overhead even when the variable doesn't need dynamic initialization at all ๐ญ. If you can be sure that no use in a non-defining TU needs to trigger dynamic initialization (because the variable is statically initialized, or a use in the defining TU runs before any use in another TU), you can skip that overhead with-fno-extern-tls-initโจ. On targets that support symbol aliases, the default is-fextern-tls-init. On targets that don't, the default is-fno-extern-tls-init.-fno-gnu-keywordsโtypeofstops being a keyword, so you can use it as a regular identifier ๐ธ. If you still want the keyword,__typeof__is there for you ๐. This is already implied by the strict ISO C++ dialects, like-ansi,-std=c++98,-std=c++11, etc.-fimplicit-constexprโ inline functions become implicitlyconstexpr๐ฅ, as long as they meet the requirements for a constexpr function. This works in C++14 mode or later, and it can switch initialization from dynamic to static, plus other optimizations โจ.-fno-implicit-templatesโ never emit code for non-inline templates that get instantiated implicitly (aka just by using them) ๐. Only explicit instantiations get code emitted.
Heads up, bestie: if you use this, you have to structure your code so every necessary explicit instantiation is included, or you'll get 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 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๐. Just know this causes linker errors if those functions aren't inlined everywhere they're called.-fmodules-ts,-fno-modules-tsโ enables support for C++20 modules ๐ง.-fno-modules-tsis usually not needed, since that's already the default. Even though modules are a C++20 feature, picking that standard version doesn't implicitly turn them on.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ compiles a header file into an importable header unit ๐.-fmodule-implicit-inlineโ member functions defined inside their class definitions aren't implicitly inline for modular code ๐ค. That's different from traditional C++ behavior, and it's different for good reasons, but it can be a headache when porting code. This option makes those function definitions implicitly inline. It does create an ABI incompatibility, so you must use it everywhere or nowhere. (Definitions outside of a named module stay implicitly inline regardless.)-fno-module-lazyโ disables lazy module importing and module mapper creation ๐ค.-fmodule-mapper=...โ basically an oracle you can query for module name to filename mappings ๐ฎ. If you don't specify one, theCXX_MODULE_MAPPERenvironment variable gets used, and if that's unset too, an in-process default is provided. The 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โ disablesWpedanticwarnings about constructs used in MFC, like implicitintand getting a pointer to a member function via non-standard syntax ๐.-fnew-inheriting-ctorsโ enables the P0136 adjustment to C++11 constructor inheritance semantics โจ. It's part of C++17, but it's also considered a Defect Report against C++11 and C++14. This flag is on by default unless-fabi-version=10or lower is specified.-fnew-ttp-matchingโ enables the P0522 resolution to Core issue 150 (template template parameters and default arguments) ๐ฆ. Basically, a template with default template arguments can be used as an argument for a template template parameter with fewer template parameters. This flag is enabled by default for-std=c++17.-fno-nonansi-builtinsโ disables built-in declarations of functions that aren't mandated by ANSI/ISO C ๐ โโ๏ธ. That includesffs,alloca,_exit,index,bzero,conjf, and other related functions.-fnothrow-optโ treats athrow()exception specification as if it were anoexceptspecification ๐, to reduce or eliminate the text size overhead compared to a function with no exception specification. If the function has local variables with non-trivial destructors, the exception specification actually makes the function smaller, because the EH cleanups for those variables can be optimized away. The semantic effect is that an exception thrown out of a function with that spec results in a call toterminaterather thanunexpected.
Watch out: thatterminatevsunexpectedswap is a real behavior change, so don't flip this on without thinking it through ๐.
-fno-operator-namesโ don't treat the operator name keywordsand,bitand,bitor,compl,not,orandxoras synonyms for keywords ๐ โโ๏ธ.-fno-optional-diagsโ disables diagnostics that the standard says a compiler doesn't need to issue ๐. Right now, the only one G++ issues like that is the one for a name having multiple meanings within a class.-fpermissiveโ downgrades some diagnostics about nonconformant code from errors to warnings ๐ค. So using-fpermissivelets some nonconforming code compile.-fno-pretty-templatesโ okay so 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 the signature. You'll see something likevoid 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, you can turn them off with-fno-pretty-templates๐ .-fno-rttiโ disables generation of run-time type information for every class with virtual functions, which is what the C++ run-time type identification features (dynamic_castandtypeid) use ๐ง . If you don't use those parts of the language, you can save some space with this flag. Exception handling uses the same info, but G++ generates it as needed. Thedynamic_castoperator still works for casts that don't need run-time type information, i.e. casts tovoid *or to unambiguous base classes.
Mixing code compiled with-frttiwith code compiled with-fno-rttimay not work. For example, programs may fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti๐ต.
-fsized-deallocationโ enables the built-in global declarations below, which were introduced in C++14 ๐ธ. They're useful for user-defined replacement deallocation functions that, for example, use the size of the object to make deallocation faster.
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
This is enabled by default under -std=c++14 and above. The flag -Wsized-deallocation warns about places that might want to add a definition.
-fstrict-enumsโ lets the compiler optimize using the assumption that a value of an enumerated type can only be one of the values of the enumeration ๐ฏ. (As defined in the C++ standard, basically a value that fits in the minimum number of bits needed to represent all the enumerators.)
This assumption may not hold if your program uses a cast to convert an arbitrary integer value to the enumerated type ๐.
-fstrong-eval-orderโ evaluates member access, array subscripting, and shift expressions left-to-right, and evaluates assignment right-to-left, as adopted for C++17 ๐. Enabled by default with-std=c++17.-fstrong-eval-order=someenables just the ordering of member access and shift expressions, and it's the default without-std=c++17.-ftemplate-backtrace-limit=nโ 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 recursions 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โ doesn't emit the extra code that uses the routines from the C++ ABI for thread-safe initialization of local statics ๐งต. You can use this to shave a bit of code size off 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โ don't use the__cxa_get_exception_ptrruntime routine ๐ โโ๏ธ. This makesstd::uncaught_exceptionincorrect, but it's necessary if that runtime routine isn't available.-fvisibility-inlines-hiddenโ declares that you won't compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects ๐ฆ.
Okay so GCC can basically slap __attribute__ ((visibility ("hidden"))) on inline methods ๐ซถ, which means they stay out of a DSO's export table and skip the PLT indirection when they're used inside that same DSO โจ. Turning this on can have a dramatic effect on load and link times for a DSO ๐ญ, because it massively shrinks the dynamic export table when the library leans hard on templates ๐
.
The behavior is not quite the same as marking methods hidden directly ๐. This switch doesn't touch static variables local to the function, and it doesn't make the compiler deduce that the function is defined in only one shared object ๐ง.
You can give a method an explicit visibility to negate the switch for that method ๐. Like, if you do want to compare pointers to a particular inline method, mark it as default visibility ๐ฆ. Marking the enclosing class with explicit visibility does nothing though ๐.
Explicitly instantiated inline methods are unaffected by this option, since their linkage might otherwise cross a shared library boundary ๐ธ.
-fvisibility-ms-compatโ this flag tries to use visibility settings to make GCC's C++ linkage model match Microsoft Visual Studio's ๐. It makes three 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 can rely (maybe accidentally) on the Visual Studio behavior ๐ฌ.
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. With this flag on, defining types with the same name differently is a violation of the ODR ๐จ.
-fno-weakโ don't use weak symbol support, even if the linker provides it ๐ . By default G++ uses weak symbols when they're available. This option exists only for testing, so end-users should steer clear ๐ซ. It results in inferior code and has no benefits, and it may be removed in a future release of G++ ๐.-fext-numeric-literals(C++ and Objective-C++ only) โ accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions โจ. When this option is turned off, those suffixes get treated as C++11 user-defined literal numeric suffixes instead. It's on by default for all pre-C++11 dialects and all GNU dialects:-std=c++98,-std=gnu++98,-std=gnu++11,-std=gnu++14. It's off by default for ISO C++11 onwards (-std=c++11, ...) ๐ง.-nostdinc++โ doesn't search for header files in the standard directories specific to C++, but still searches the other standard directories ๐. (This one gets used when building the C++ library ๐ ๏ธ.)-flang-info-include-translate,-flang-info-include-translate-not,-flang-info-include-translate=headerโ these inform you about include translation events ๐. The first notes accepted include translations, and the second notes declined ones ๐ โโ๏ธ. Theheaderform tells you about include translations relating to that specific header. Ifheaderis of the form"user"or"<system>", it gets resolved to a specific user or system header using the include path ๐บ๏ธ.-flang-info-module-cmi,-flang-info-module-cmi=moduleโ inform you about Compiled Module Interface pathnames ๐งพ. The first one notes all the read CMI pathnames ๐. Themoduleform covers a specific module's CMI. Themodulevalue can be a named module or a header-unit, and a header-unit is indicated either by a pathname containing directory separators or by being enclosed in"<>"or""๐ฆ.-stdlib=libstdc++,libc++โ when G++ is configured to support this option, you can pick an alternate C++ runtime library ๐ง. There are two choices:libstdc++(the default, and the native C++ runtime for G++) andlibc++, which is the C++ runtime installed on some operating systems (for example, Darwin versions from Darwin11 onwards) ๐. Picking one switches G++ to use the headers from that library, and it emits-lstdc++or-lc++respectively when a C++ runtime is needed for linking ๐.
In addition, these warning options have meanings only for C++ programs ๐.
-Wabi-tag(C++ and Objective-C++ only) โ warns when a type with an ABI tag is used in a context that doesn't have that ABI tag ๐ท๏ธ. Peep C++ Attributes for the full scoop on ABI tags ๐.-Wcomma-subscript(C++ and Objective-C++ only) โ warns about uses of a comma expression within a subscripting expression ๐. This usage was deprecated in C++20 and is going to be removed in C++23 ๐. However, a comma expression wrapped in( )is not deprecated โจ. Example:
void f(int *a, int b, int c) {
a[b,c]; // deprecated in C++20, invalid in C++23
a[(b,c)]; // OK
}
In C++23, it's valid to have comma-separated expressions in a subscript when an overloaded subscript operator is found and supports the right number and types of arguments ๐ง . G++ will accept the formerly valid syntax for code that isn't valid in C++23 but used to be valid (deprecated) in C++20, with a pedantic warning that can be disabled with -Wno-comma-subscript ๐ซ .
It's enabled by default with -std=c++20 unless -Wno-deprecated is given, and with -std=c++23 regardless of -Wno-deprecated ๐.
-Wctad-maybe-unsupported(C++ and Objective-C++ only) โ warns when you perform class template argument deduction (CTAD) on a type with no explicitly written deduction guides ๐ต๏ธ. This warning points out cases where CTAD only succeeded because the compiler synthesized the implicit deduction guides, which might not be what you intended ๐ค. Certain style guides only allow CTAD on types that specifically "opt-in", meaning types that are designed to support CTAD ๐. You can suppress this warning with the following pattern:
struct allow_ctad_t; // any name works
template <typename T> struct S {
S(T) { }
};
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 its constructors or destructors are private, and it has neither friends nor public static member functions ๐. It also warns if there are no non-private methods and there's at least one private member function that isn't a constructor or destructor ๐ง.-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ warns whendeleteis used to destroy an instance of a class that has virtual functions and a non-virtual destructor ๐ฅ. It's unsafe to delete an instance of a derived class through a pointer to a base class if the base class doesn't have a virtual destructor โ ๏ธ. This warning is enabled by-Wall๐.-Wdeprecated-copy(C++ and Objective-C++ only) โ warns that the implicit declaration of a copy constructor or copy assignment operator is deprecated if the class has a user-provided copy constructor or copy assignment operator, in C++11 and up ๐ข. This warning is enabled by-Wextra๐ง. With-Wdeprecated-copy-dtor, it also deprecates the implicit declaration if the class has a user-provided destructor ๐ซถ.-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only) โ disables the warning about the case where the usual arithmetic conversions are applied to operands where one is of enumeration type and the other is of a different enumeration type ๐ . This conversion was deprecated in C++20 ๐. For example:
enum E1 { e };
enum E2 { f };
int k = f - e;
-Wdeprecated-enum-enum-conversion is enabled by default with -std=c++20 ๐
. In pre-C++20 dialects, this warning can be enabled by -Wenum-conversion ๐ธ.
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only) โ disables the warning about the case where the usual arithmetic conversions are applied to operands where one is of enumeration type and the other is of a floating-point type ๐. This conversion was deprecated in C++20 โณ. For example:
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7;
-Wdeprecated-enum-float-conversion is enabled by default with -std=c++20 ๐ฅ. In pre-C++20 dialects, this warning can be enabled by -Wenum-conversion ๐.
-Wno-init-list-lifetime(C++ and Objective-C++ only) โ don't warn about uses ofstd::initializer_listthat are likely to result in dangling pointers ๐งจ. The underlying array for aninitializer_listis handled like a normal C++ temporary object, so it's super easy to accidentally keep a pointer to the array past the end of the array's lifetime ๐ญ. Some examples of that:- 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 ๐.
// 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
Heads up bestie: that last line is undefined behavior ๐, so don't go poking at dangling pointers like that ๐.
- ๐ซฃ When a list constructor stores the
beginpointer from theinitializer_listargument, that does not extend the lifetime of the array. So if a class variable gets built from a temporaryinitializer_list, the pointer is left dangling by the end of the variable declaration statement. ๐
-Winvalid-imported-macrosโ okay so this one checks that every imported macro definition is still valid at the end of compilation ๐. It's not enabled by default because it needs extra processing to figure that out. It's super handy when you're putting together sets of header-units and want your macros to stay consistent โจ.-Wno-literal-suffix(C++ and Objective-C++ only) โ bestie, don't warn when a string or character literal gets followed by a ud-suffix that doesn't start with an underscore ๐ . GCC treats those suffixes as separate preprocessing tokens. It's a conforming extension, and it keeps older code working when it uses formatting macros from<inttypes.h>๐. For example:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
int main() {
int64_t i64 = 123;
printf("My int64: %" PRId64"\n", i64);
}
In this case, PRId64 gets treated as a separate preprocessing token.
This option also controls warnings for a user-defined literal operator declared with a literal suffix identifier that doesn't begin with an underscore ๐. Those identifiers are reserved for future standardization, so the warning is a heads up.
These warnings are enabled by default. ๐
-Wno-narrowing(C++ and Objective-C++ only) โ for C++11 and later, narrowing conversions get diagnosed by default, as the standard requires ๐. A narrowing conversion from a constant gives an error, and a narrowing conversion from a non-constant gives a warning.-Wno-narrowingsilences that diagnostic ๐.
Just so you know, it doesn't change what well-formed code means, since narrowing conversions are still ill-formed in SFINAE contexts.
With -Wnarrowing in C++98, it warns when a narrowing conversion that C++11 prohibits happens inside { }, 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) โ it warns when a noexcept-expression evaluates to false because of a call to a function that doesn't have a non-throwing exception specification (so,throw()ornoexcept) but that the compiler knows will never actually throw ๐ง.-Wnoexcept-type(C++ and Objective-C++ only) โ this one's about the C++17 feature that makesnoexceptpart of a function type. It warns if that changes the mangled name of a symbol compared to C++14 ๐ฆ. Enabled by-Wabiand-Wc++17-compat.
As an example:
template <class T> void f(T t) { t(); };
void g() noexcept;
void h() { f(g); }
In C++14, f calls f<void(*)()>, but in C++17 it calls f<void(*)()noexcept> ๐คฏ.
-Wclass-memaccess(C++ and Objective-C++ only) โ it warns when the destination of a call to a raw memory function likememsetormemcpyis an object of class type ๐จ. It also warns when writing into that object might 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 representation of these objects can violate invariants that the class's member functions rely on.
๐ For example, the call to memset below is undefined because it modifies a non-trivial class object, so it gets diagnosed:
std::string str = "abc";
memset (&str, 0, sizeof str);
The safe way to initialize or clear the storage of objects like these is to use the appropriate constructor or assignment operator, if one is available ๐ .
The -Wclass-memaccess option is enabled by -Wall. Explicitly casting the pointer to the class object to void *, or to a type that the raw memory function can safely access, suppresses the warning โจ.
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ it warns when a class has virtual functions but an accessible non-virtual destructor, either on itself or in an accessible polymorphic base class ๐ฌ. That makes it possible, but unsafe, to delete a derived-class instance through a pointer to the class itself or its base class. This warning is automatically enabled if-Weffc++is specified.-Wregister(C++ and Objective-C++ only) โ it warns on uses of theregisterstorage class specifier, except when it's part of the GNU Explicit Register Variables extension ๐ โโ๏ธ. Theregisterkeyword as a storage class specifier was deprecated in C++11 and removed in C++17. Enabled by default with-std=c++17.-Wreorder(C++ and Objective-C++ only) โ it warns when the member initializers in your code aren't in the order they actually have to run ๐งฉ. For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler rearranges the member initializers for i and j to match the declaration order of the members, and it emits a warning to say so. This warning is enabled by -Wall.
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this warning goes off when a call tostd::moveprevents copy elision ๐. A typical scenario where copy elision can happen is returning from a function with a class return type, when the 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.
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 flags redundant calls tostd::move, meaning cases where a move would have happened even without thestd::movecall ๐. That happens because the compiler is forced to treat the object as an rvalue in certain situations, like returning a local variable where copy elision isn't applicable. Look:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant. Because G++ implements Core Issue 1579, another example is:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this example, copy elision isn't applicable because the type of the expression being returned and the function return type differ. Still, G++ treats the return value as if it were designated by an rvalue ๐คทโโ๏ธ. This warning is enabled by -Wextra.
-Wrange-loop-construct(C++ and Objective-C++ only) โ it 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 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 results in a copy. For example:
void fn() {
int arr[10];
for (const double &x : arr) { ... }
}
In the example above, every iteration of the loop creates and destroys a temporary value of type double, and the reference const double & is bound to that temporary ๐ต. This warning is enabled by -Wall.
-Wredundant-tags(C++ and Objective-C++ only) โ it warns about redundant class-key and enum-key in references to class types and enumerated types, in spots where the key could be dropped without causing an ambiguity ๐. For example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
On the other hand, in this example there's no warning, because the keyword is needed:
struct foo;
void foo (); // "hides" struct foo
void bar (struct foo&); // no warning, keyword struct is necessary
-Wno-subobject-linkage(C++ and Objective-C++ only) โ 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 typeAdepends on a typeBwith no or internal linkage, defining it in multiple translation units would be an ODR violation, because the meaning ofBis different in each translation unit. IfAonly shows up in a single translation unit, the best way to silence the warning is to give it internal linkage by putting it in an anonymous namespace as well. The compiler doesn't give this warning for types defined in the main.Cfile, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default.-Weffc++(C++ and Objective-C++ only) โ it warns about violations of these style guidelines from Scott Meyers' Effective C++ series of books ๐:- Write a copy constructor and an assignment operator for any class holding 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 have to return an object ๐ .
- Tell the prefix and postfix forms of the increment and decrement operators apart ๐ฏ.
- Never overload
&&,||, or,๐ซ.
This option also enables -Wnon-virtual-dtor, which is also one of the effective C++ recommendations. The check is extended, though, so it also warns about a missing virtual destructor in accessible non-polymorphic base classes ๐ซถ.
Okay bestie, heads up before you flip these on ๐ the standard library headers don't follow all of these guidelines, so use grep -v to filter out those warnings ๐
-Wno-exceptions(C++ and Objective-C++ only) โ no more warnings when one exception handler gets shadowed by another one ๐ This can point out a wrong ordering of your exception handlers, but you can turn it off here.-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about using an uncastedNULLas a sentinel ๐ When you compile only with GCC, it's a valid sentinel, sinceNULLis defined to__null. It's a null pointer constant rather than a null pointer, but it's guaranteed to be the same size as a pointer. Still, this use isn't portable across different compilers, so be careful ๐ซถ-Wno-non-template-friend(C++ and Objective-C++ only) โ turns off warnings for non-template friend functions declared inside a template โจ In very old GCC versions that came before the ISO standard was implemented, declarations likefriend int foo(int), where the friend's name is an unqualified-id, could be read as a particular specialization of a template function. The warning exists to catch 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 shows up 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, and 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 a member function into a plain pointer ๐ฆ-Wsign-promo(C++ and Objective-C++ only) โ warns when overload resolution picks a promotion from an unsigned or enumerated type to a signed type, instead of a conversion to an unsigned type of the same size ๐ง Older versions of G++ tried to preserve unsignedness, but the standard mandates the current behavior, so that's the vibe now.-Wtemplates(C++ and Objective-C++ only) โ warns when a primary template declaration is encountered ๐ซ Some coding rules disallow templates, and this can be used to enforce that rule. The warning is inactive inside a system header file, like the STL, so you can still use the STL ๐ You can also instantiate or specialize templates.-Wmismatched-new-delete(C++ and Objective-C++ only) โ warns about mismatches between calls tooperator neworoperator deleteand the corresponding allocation or deallocation function ๐ฅ That includes C++operator deletebeing called with pointers returned from mismatched forms ofoperator new, or from other functions that allocate objects for whichoperator deleteisn't a suitable deallocator. It also covers calls to other deallocation functions with pointers returned fromoperator newwhere that deallocation function isn't suitable.
For example, the delete expression in the function below gets diagnosed, because it doesn't match the array form of the new expression the pointer was returned from. The call to free gets diagnosed too ๐ญ
void f ()
{
int *a = new int[n];
delete a; // warning: mismatch in array forms of expressions
char *p = new char[n];
free (p); // warning: mismatch between new and free
}
The related option -Wmismatched-dealloc diagnoses mismatches involving allocation and deallocation functions other than operator new and operator delete ๐ง
-Wmismatched-new-delete is included in -Wall โจ
-Wmismatched-tags(C++ and Objective-C++ only) โ warns for declarations of structs, classes, and class templates, plus their specializations, that use a class-key which doesn't match either the definition or the first declaration when no definition is provided ๐
For example, the declaration of struct Object in the argument list of draw triggers the warning. To avoid it, either remove the redundant class-key struct or replace it with class to match its definition.
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
It's not wrong to declare a class with the class-key struct, as the example above shows ๐โโ๏ธ The -Wmismatched-tags option is meant to help you keep a consistent style of class declarations. In code that's intended to be portable to Windows-based compilers, the warning 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 disallow multiple inheritance, so this can be used to enforce that rule. The warning is inactive inside a system header file, like the STL, so you can still use the STL. You can also define classes that indirectly use multiple inheritance.-Wvirtual-inheritanceโ warns when a class is defined with a virtual direct base class ๐ฆ Some coding rules disallow multiple inheritance, and this can be used to enforce that rule. The warning is inactive inside a system header file, like the STL, so you can still use the STL. You can also define classes that indirectly use virtual inheritance.-Wno-virtual-move-assignโ suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator ๐ซฃ
This is dangerous! If the virtual base is reachable along more than one path, it gets moved multiple times, which can 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, you can disable this warning.
-Wnamespacesโ warns when a namespace definition is opened ๐ฆ Some coding rules disallow namespaces, and this can be used to enforce that rule. The warning is inactive inside a system header file, like the STL, so you can still use the STL. You can also use using directives and qualified names.-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 will suggest options for dealing with the ambiguity, e.g., it can suggest removing the parentheses or using braces instead ๐ง
This warning is enabled by default โ
-Wno-class-conversion(C++ and Objective-C++ only) โ don't warn when a conversion function converts an object to the same type, to a base class of that type, or tovoid๐ Such a conversion function will never be called, so the warning is just noise ๐-Wvolatile(C++ and Objective-C++ only) โ warns about deprecated uses of thevolatilequalifier ๐ This includes:- postfix and prefix
++and--expressions ofvolatile-qualified types - simple assignments where the left operand is a
volatile-qualified non-class type, for their value - compound assignments where the left operand is a
volatile-qualified non-class type - a
volatile-qualified function return type - a
volatile-qualified parameter type - structured bindings of a
volatile-qualified type
- postfix and prefix
This usage was deprecated in C++20 ๐
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 useful for making the switch tonullptrin C++11 โจ-Waligned-newโ warns about a new-expression of a type that requires 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 type of the object ๐งธ For example, the placement new expression below is 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, the followingnewexpression 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]();
Cranking it up to -Wplacement-new=2 ๐
gets you everything level 1 catches, plus a warning for placement new expressions that build an object inside the last member of a struct when that member is a single-element array and the object being built is bigger than the array. ๐ญ The previous example would get flagged, but the flexible member array extension lets you dodge the warning at level 2 ๐ฆ
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ bestie, this one roasts catch handlers that don't catch by reference ๐-Wcatch-value=1(or-Wcatch-valuefor short) โ flags polymorphic class types that get caught by value-Wcatch-value=2โ flags all class types caught by value-Wcatch-value=3โ flags all types that aren't caught by reference-Wcatch-valueis enabled by-Wall, so you're basically getting it for free โจ
-Wconditionally-supported(C++ and Objective-C++ only) โ warns about conditionally-supported constructs (C++11[intro.defs]) ๐ธ-Wno-delete-incomplete(C++ and Objective-C++ only) โ turns off the warning for deleting a pointer to an incomplete type. Heads up, that can cause undefined behavior at runtime ๐ This warning is on by default.-Wextra-semi(C++, Objective-C++ only) โ catches redundant semicolons after in-class function definitions ๐ง-Wno-inaccessible-base(C++, Objective-C++ only) โ controls the warnings you get when a base class is inaccessible in a derived class because of ambiguity. It's on by default, and the warning for ambiguous virtual bases comes along with-Wextra. Check out this drama:
struct A { int a; };
struct B : A { };
struct C : B, A { };
-Wno-inherited-variadic-ctorโ silences the warnings about C++11 inheriting constructors when the base class has a C variadic constructor. That warning is on by default, since the ellipsis doesn't get inherited, so this is you saying "I know, I know" ๐-Wno-invalid-offsetof(C++ and Objective-C++ only) โ shushes the warnings for using theoffsetofmacro on a non-POD type. The 2014 ISO C++ standard says applyingoffsetofto a non-standard-layout type is undefined, but existing C++ implementations usually give meaningful results anyway. This flag is for the girlies who know their code is nonportable and chose to ignore the warning on purpose ๐
The restrictions on offsetof may be relaxed in a future version of the C++ standard, so keep your eyes open ๐
-Wsized-deallocation(C++ and Objective-C++ only) โ warns when you define an unsized deallocation function like this:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
...without also defining the matching sized deallocation function like this:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
...or the other way around. It's enabled by -Wextra along with -fsized-deallocation ๐ฅ
-Wsuggest-final-typesโ suggests when a type with virtual methods would look better with the C++11finalspecifier or, if possible, living in an anonymous namespace. This lets GCC devirtualize polymorphic calls more aggressively ๐ It's way more useful with link-time optimization, since that gives the full class hierarchy graph.-Wsuggest-final-methodsโ suggests when a virtual method would be better off with thefinalspecifier, or if possible, when its type lives in an anonymous namespace or usesfinal. Same deal, it's more effective with link-time optimization. Pro tip: look at-Wsuggest-final-typessuggestions first, then rebuild with the new annotations ๐-Wsuggest-overrideโ warns when you override virtual functions without theoverridekeyword ๐ซถ-Wuse-after-free,-Wuse-after-free=nโ warns about using pointers to dynamically allocated objects that a deallocation function has made indeterminate. It's enabled at every optimization level, but the results can change depending on whether optimization is on ๐-Wuse-after-free=1โ only diagnoses unconditional uses of pointers made indeterminate by a deallocation call, or by a successfulrealloccall (whether or not it actually moved the memory). That includes doublefreecalls and uses in arithmetic and relational expressions. Uses in equality or inequality expressions aren't diagnosed at this level, even though they're still undefined.-Wuse-after-free=2โ adds conditional uses of pointers made indeterminate by a deallocation call. Just like level 1, equality and inequality uses don't get flagged here. In this example, the secondfreecall is the one that gets caught:
struct A { int refcount; void *data; };
void release (struct A *p)
{
int refcount = --p->refcount;
free (p);
if (refcount == 0)
free (p->data); // warning: p may be used after free
}
-Wuse-after-free=3โ also diagnoses equality expressions that use indeterminate pointers. All uses of indeterminate pointers are undefined, but equality tests sometimes show up afterrealloccalls to check whether the object moved to a new address. This level is separate so legacy code can slowly move to safer alternatives ๐ฆ In this function, the equality test is what gets flagged:
void adjust_pointers (int**, int);
void grow (int **p, int n)
{
int **q = (int**)realloc (p, n *= 2);
if (q == p)
return;
adjust_pointers ((int**)q, n);
}
To avoid the warning at this level, store offsets into the allocated memory instead of pointers. That way you never have to fix up stored pointers after reallocation, which is so much cleaner ๐ง
-Wuse-after-free=2 is included in -Wall.
-Wuseless-cast(C++ and Objective-C++ only) โ warns when an expression gets cast to its own type. Why are we doing that ๐-Wno-conversion-null(C++ and Objective-C++ only) โ stops the warnings for conversions betweenNULLand non-pointer types.-Wconversion-nullis enabled by default, so this is the opt-out ๐
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
NOTE: This manual does not describe the Objective-C and Objective-C++ languages themselves. Okay, this section is only about the command-line options that matter for Objective-C and Objective-C++ programs ๐
You can also use most of the language-independent GNU compiler options. For example, you might compile a file called some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
In that example, -fgnu-runtime is an option meant only for Objective-C and Objective-C++ programs. The other options work with any language GCC supports ๐ธ
Objective-C is an extension of the C language, so Objective-C compilations can also use options specific to the C front-end (for example, -Wtraditional). In the same way, Objective-C++ compilations can use C++-specific options (for example, -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 to instantiate for each literal string written with the"@"...""syntax. The default is"NXConstantString"if the GNU runtime is in use, and"NSConstantString"if the NeXT runtime is in use (see below). If-fconstant-cfstringsis also present, it overrides-fconstant-string-classand makes"@"...""literals get laid out as constant CoreFoundation strings โจ-fgnu-runtimeโ generates object code that works with the standard GNU Objective-C runtime. This is the default on most systems ๐ฆ-fnext-runtimeโ generates output that works with the NeXT runtime. This is the default on 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 every Objective-C message dispatch ("[receiver message:arg]") in this translation unit makes sure the receiver is not"nil". That lets the runtime use faster entry points. This option only works with the NeXT runtime and ABI version 0 or 1 โ ๏ธ-fobjc-abi-version=nโ uses version n of the Objective-C ABI for the selected runtime. Right now it's only supported for the NeXT runtime ๐- Version 0 is the traditional (32-bit) ABI, with no support for properties or the other Objective-C 2.0 additions.
- Version 1 is the traditional (32-bit) ABI with support for properties and the other Objective-C 2.0 additions.
- Version 2 is the modern (64-bit) ABI.
- If you don't specify anything, the default is Version 0 on 32-bit target machines and Version 2 on 64-bit target machines.
-fobjc-call-cxx-cdtorsโ okay so for every Objective-C class, GCC peeks at its instance variables ๐. If any of them is a C++ object with a non-trivial default constructor, GCC quietly synthesizes a special- (id) .cxx_constructinstance method โจ. That method runs those constructors on the instance variables, in order, and then returnsself๐. Same energy for destructors: if any instance variable is a C++ object with a non-trivial destructor, GCC synthesizes a- (void) .cxx_destructmethod that runs all of those default destructors in reverse order ๐.- The generated methods only work on instance variables declared in the current Objective-C class, not the ones inherited from superclasses ๐ โโ๏ธ. Making sure every method in an object's inheritance hierarchy gets invoked is the Objective-C runtime's job ๐ซถ.
- The runtime calls
- (id) .cxx_constructright after a new object instance is allocated โฐ. It calls- (void) .cxx_destructright before deallocating an object instance ๐๏ธ. - As of this writing, only the NeXT runtime on Mac OS X 10.4 and later has support for invoking
- (id) .cxx_constructand- (void) .cxx_destruct๐.
-fobjc-direct-dispatchโ allows fast jumps to the message dispatcher โก. On Darwin, this is done via the comm page ๐.-fobjc-exceptionsโ turns on syntactic support for structured exception handling in Objective-C, kinda like what C++ offers ๐ง. You need this flag to use the Objective-C keywords@try,@throw,@catch,@finallyand@synchronized๐. It works with both the GNU runtime and the NeXT runtime, but not with the NeXT runtime on Mac OS X 10.2 and earlier ๐ซ.-fobjc-gcโ enables garbage collection (GC) in Objective-C and Objective-C++ programs ๐. This is only available with the NeXT runtime. The GNU runtime has a different GC implementation that doesn't need any special compiler flags โจ.-fobjc-nilcheckโ for the NeXT runtime with version 2 of the ABI, this checks for a nil receiver in method invocations before the actual method call ๐. It's the default, and you can switch it off with-fno-objc-nilcheck๐ . Class methods and super calls are never checked for nil this way, no matter what this flag is set to ๐คท. Right now this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is in use ๐ค.-fobjc-std=objc1โ conforms to the language syntax of Objective-C 1.0, the language recognized by GCC 4.0 ๐ฐ๏ธ. It only affects the Objective-C additions to C/C++, and doesn't change conformance to C/C++ standards, which is controlled by the separate C/C++ dialect option flags ๐. With the Objective-C or Objective-C++ compiler, any Objective-C syntax that GCC 4.0 doesn't recognize gets rejected โ. This is super useful if you need to make sure your Objective-C code compiles 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 in at run time instead ๐ฆ. This is used with the Fix-and-Continue debugging mode, where the object file can be recompiled and dynamically reloaded during execution, no restart needed ๐. Right now, Fix-and-Continue is only available with the NeXT runtime on Mac OS X 10.3 and later ๐.-fzero-linkโ when compiling for the NeXT runtime, GCC normally swaps calls toobjc_getClass("...")(when the class name is known at compile time) for static class references that get initialized at load time, which improves run-time performance ๐๏ธ. This flag suppresses that behavior and keeps the calls toobjc_getClass("...")๐. It's useful 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 can be accessed as if they were local variables from within the methods of the class they're declared in ๐ง. That can cause shadowing between instance variables and other variables, whether those are declared locally inside a class method or globally with the same name ๐ฏ. This flag disables that behavior, so you avoid the variable shadowing issues ๐ซ.-fivar-visibility=[public|protected|private|package]โ sets the default instance variable visibility to whatever option you pick ๐. Instance variables declared outside the scope of any access modifier directive will default to that visibility.-gen-declsโ dumps 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 is being intercepted by the garbage collector ๐จ.-Wno-property-assign-default(Objective-C and Objective-C++ only) โ no warning if a property for an Objective-C object has no assign semantics specified ๐คซ.-Wno-protocol(Objective-C and Objective-C++ only) โ if a class says it implements a protocol, you normally get a warning for every protocol method the class doesn't implement ๐ฃ. By default, that includes methods the class doesn't explicitly implement even when the superclass has them, which is lowkey extra ๐. With-Wno-protocol, inherited methods count as implemented, so no warning gets issued for them ๐.-Wobjc-root-class(Objective-C and Objective-C++ only) โ warns if a class interface lacks a superclass ๐ณ. Most classes inherit from"NSObject"(or"Object"), for example ๐งธ. When you're declaring classes that are meant to be root classes, you can suppress the warning by marking their interfaces with__attribute__((objc_root_class))๐คซ.-Wselector(Objective-C and Objective-C++ only) โ warns if multiple methods of different types for the same selector are found during compilation ๐ต๏ธ. The check runs on the list of methods in the final stage of compilation ๐. It also checks each selector appearing in a@selector(...)expression, if a corresponding method for that selector was found during compilation ๐. Because these checks only scan the method table at the end, these warnings won't be produced if the final stage isn't reached ๐ญ. That happens if an error is found during compilation, or if the-fsyntax-onlyoption is being used.-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if multiple methods with differing argument and/or return types are found for a given selector when you try to send a message with it to a receiver of typeidorClass๐จ. When this flag is off (which is the default), the compiler skips these warnings if the differences are confined to types that share the same size and alignment ๐ซ .-Wundeclared-selector(Objective-C and Objective-C++ only) โ warns if a@selector(...)expression referring to an undeclared selector is found ๐. A selector counts as undeclared if no method with that name has been declared before the@selector(...)expression, either explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection ๐. This option checks as soon as a@selector(...)expression is found, while-Wselectoronly checks in the final stage of compilation โฑ๏ธ. It also enforces the coding style convention 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 any ๐งพ.
โจ Options to Control Diagnostic Messages Formatting โจ
Traditionally, diagnostic messages have been formatted without caring about the output device's aspect (like its width, etc.) ๐ฅ๏ธ. The options here let you control the formatting algorithm, like how many characters go on a line, or how often source location info gets reported ๐. Heads up: some language front ends may not honor these options ๐ซฃ.
-fmessage-length=nโ tries to format error messages so they fit on lines of aboutncharacters ๐. Ifnis zero, no line-wrapping gets done, and each error message appears on a single line ๐งต. This is the default for all front ends ๐ธ.
Note: this option also affects the display of the#errorand#warningpre-processor directives, and the deprecated function/type/variable attribute ๐. It does not affect thepragma GCC warningandpragma GCC errorpragmas ๐ซ.
-fdiagnostics-plain-outputโ requests diagnostic output that looks as plain as possible ๐งผ. This can be useful when running dejagnu or other utilities that parse diagnostics output and prefer it stay more stable over time ๐งช. It's currently equivalent to the following options:
-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never -fdiagnostics-urls=never -fdiagnostics-path-format=separate-events
Looking ahead ๐ฎ, if GCC ever changes the default appearance of its diagnostics, the matching option to disable the new behavior will be added to this list ๐.
-fdiagnostics-show-location=onceโ only meaningful in line-wrapping mode ๐. It tells the diagnostic messages reporter to emit source location info once. If a message is too long to fit on one physical line and has to be wrapped, the source location won't be emitted again as a prefix on each continuation line ๐ . This is the default behavior ๐ .-fdiagnostics-show-location=every-lineโ also only meaningful in line-wrapping mode ๐. It tells the reporter to emit the same source location info (as a prefix) for each physical line that results from breaking up a message that's too long to fit on a single line ๐.-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ slap color on your diagnostics (or take it right off) ๐
This one decides whether GCC's messages come out in color ๐. WHEN can be never, always, or auto. The default depends on how the compiler was configured ๐ง. It can be any of those WHEN options too, or never if the GCC_COLORS environment variable isn't in the environment, and auto otherwise.
auto only uses color when standard error is a terminal and GCC isn't running in an emacs shell ๐. The forms -fdiagnostics-color and -fno-diagnostics-color are aliases for -fdiagnostics-color=always and -fdiagnostics-color=never, respectively ๐.
The colors themselves come from the GCC_COLORS environment variable โจ. Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings. SGR commands are interpreted by your terminal or terminal emulator, so check your text terminal's docs for the permitted values and what they mean as character attributes ๐. These substring values are decimal integers, and they can be stuck together with semicolons ๐ซถ.
Here are some common values you can concatenate:
1โ bold4โ underline5โ blink7โ inverse39โ default foreground color30to37โ foreground colors90to97โ 16-color mode foreground colors38;5;0to38;5;255โ 88-color and 256-color modes foreground colors49โ default background color40to47โ background colors100to107โ 16-color mode background colors48;5;0to48;5;255โ 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
So 01;31 is bold red, 01;35 is bold magenta, 01;36 is bold cyan, 32 is green, 34 is blue, 01 is bold, and 31 is red ๐. Setting GCC_COLORS to the empty string disables colors entirely ๐
. These are the capabilities you can customize:
"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"range2="โ the SGR substring for the second additional range"locus="โ the SGR substring for location info, likefile:lineorfile:line:columnetc. ๐"quote="โ the SGR substring for 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]โ sneak clickable-vibe URLs into your diagnostics ๐ฆ
This uses escape sequences to embed URLs in diagnostics. For example, when -fdiagnostics-show-option prints the command-line option controlling a diagnostic, it can embed a URL pointing to the documentation 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 GCC isn't running in an emacs shell or in any graphical terminal known to be incompatible with this feature (see below) ๐.
The default depends on how the compiler was configured, and it can be any of the above WHEN options ๐ง.
GCC can also be configured with 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 compiler's environment, or never if neither is.
Even with -fdiagnostics-urls=always, the behavior still depends on those environment variables ๐ง:
- If
GCC_URLSis set to empty orno, URLs 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 with the string terminator ESC \. BEL is an ASCII character, CTRL-G, that usually sounds like a beep ๐.
GCC tries to detect a few terminals that don't implement the URL feature and that have bugs (or at least had bugs in some versions still in use), where URL escapes are likely to misbehave. That list is currently xfce4-terminal, certain known buggy gnome-terminal versions, the linux console, and mingw ๐. This check can be skipped with -fdiagnostics-urls=always.
Heads up, bestie: on those terminals the URL escapes are likely to misbehave, i.e. print garbage on the screen ๐.
-fno-diagnostics-show-optionโ stop naming the controlling option ๐
By default, each diagnostic includes text indicating the command-line option that directly controls it (if that option is known to the diagnostic machinery). Specifying -fno-diagnostics-show-option suppresses that behavior ๐ซ.
-fno-diagnostics-show-caretโ no source line, no caret ๐
By default, each diagnostic includes the original source line and a caret ^ pointing at the column. This option suppresses that info ๐
. The source line is truncated to n characters if the -fmessage-length=n option is given. When the output goes to the terminal, the width is limited to the width given by the COLUMNS environment variable or, if that isn't set, to the terminal width ๐.
-fno-diagnostics-show-labelsโ skip the little labels ๐ท๏ธ
By default, when printing source code (via -fdiagnostics-show-caret), diagnostics can label ranges of source code with pertinent information, such as the types of expressions:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses the printing of these labels. In the example above, that means the vertical bars and the "char *" and "long int" text disappear ๐.
-fno-diagnostics-show-cweโ hide the CWE metadata ๐
Diagnostic messages can optionally have an associated CWE (https://cwe.mitre.org/index.html) identifier. GCC itself only provides this metadata for some of the -fanalyzer diagnostics. GCC plugins may also provide diagnostics with this metadata. By default, if the information is present, it gets printed with the diagnostic. This option suppresses printing that metadata ๐ซ.
-fno-diagnostics-show-line-numbersโ no line-number margin ๐ข
By default, when printing source code (via -fdiagnostics-show-caret), a left margin is printed, showing line numbers. This option suppresses that left margin ๐
.
-fdiagnostics-minimum-margin-width=widthโ set the minimum margin width ๐
This option controls the minimum width of the left margin printed by -fdiagnostics-show-line-numbers. It defaults to 6 ๐.
-fdiagnostics-parseable-fixitsโ machine-readable fix-its, made for IDEs ๐ค
This emits fix-it hints in a machine-parseable format, which is suitable for IDEs to consume ๐ซถ. For each fix-it, a line gets printed after the relevant diagnostic, starting with the string fix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
The location is a half-open range, expressed as a count of bytes, starting at byte 1 for the initial column. In the example above, bytes 3 through 20 of line 45 of "test.c" get replaced with the given string ๐:
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape backslash as "\\", tab as "\t", newline as "\n", and double quotes as "\"". Non-printable characters get written as octal, so vertical tab shows up as "\013" ๐งฉ.
An empty replacement string means that range is to be removed ๐๏ธ. An empty range, like "45:3-45:3", means the string is to be inserted at the given position โ.
-fdiagnostics-generate-patchโ fix-its served up as a diff ๐ฉน
This prints fix-it hints to stderr in unified diff format, after any diagnostics are printed. For example:
--- test.c
+++ test.c
@ -42,5 +42,5 @
void show_cb(GtkDialog *dlg)
{
- gtk_widget_showall(dlg);
+ gtk_widget_show_all(dlg);
}
The diff may or may not be colorized, following the same rules as for diagnostics (see -fdiagnostics-color) ๐จ.
-fdiagnostics-show-template-treeโ template mismatches as a tree ๐ณ
In the C++ frontend, when printing diagnostics that show mismatching template types, you get messages like this:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
The -fdiagnostics-show-template-tree flag turns on a tree-like structure that shows the common and differing parts of the types, like this:
map<
[...],
vector<
[double != float]>>
The parts that differ get highlighted with color ("double" and "float" in this case) ๐.
-fno-elide-typeโ stop squishing the matching bits into[...]๐
By default, when the C++ frontend prints diagnostics showing mismatching template types, the common parts get printed as "[...]" to keep the error message simpler ๐
. For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying -fno-elide-type suppresses that behavior. This flag also affects the output of the -fdiagnostics-show-template-tree flag โจ.
-fdiagnostics-path-format=KINDโ okay so this one decides how control-flow paths get shown ๐ค๏ธ for diagnostics that actually have one attached โจ
KIND can be none, separate-events, or inline-events, and inline-events is the default ๐
none means no diagnostic paths get printed at all ๐
separate-events prints a separate "note" diagnostic for every event in the diagnostic ๐ Here's how that looks:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-events prints the events right inside the source code ๐ผ๏ธ It tries to group events that sit close together into runs and shows them as labelled ranges. Same events as above, but the vibe is totally different:
'test': events 1-3
|
| 25 | list = PyList_New(0);
| | ^~~~~~~~~~~~~
| | |
| | (1) when 'PyList_New' fails, returning NULL
| 26 |
| 27 | for (i = 0; i < count; i++) {
| | ~~~
| | |
| | (2) when 'i < count'
| 28 | item = PyLong_FromLong(random());
| 29 | PyList_Append(list, item);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
|
Interprocedural control flow gets shown by grouping the events by stack frame ๐ Indentation shows how stack frames nest, get pushed, and get popped, and it's giving organized ๐ง Like this:
'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โ bonus info ๐ for when GCC prints control-flow paths attached to a diagnostic
If this option is provided, the stack depth gets printed for each run of events within -fdiagnostics-path-format=separate-events ๐ง
This one is mainly for GCC developers and plugin developers who are debugging diagnostics that report interprocedural control flow ๐ง
-fno-show-columnโ no column numbers in diagnostics, periodt ๐
Do not print column numbers in diagnostics. This might be necessary if a program that doesn't understand column numbers is scanning your diagnostics, like dejagnu ๐ซถ
-fdiagnostics-column-unit=UNITโ pick the units used for column numbers ๐ This affects traditional diagnostics (when-fno-show-columnisn't set), plus JSON diagnostics if you ask for them
The default, display, counts the number of display columns each character takes up ๐ฅ๏ธ That can be bigger than the number of bytes needed to encode the character (like with tab characters), or smaller (like with multibyte characters). For example, "GREEK SMALL LETTER PI (U+03C0)" takes up one display column but needs two bytes in UTF-8. Meanwhile "SLIGHTLY SMILING FACE (U+1F642)" takes up two display columns and needs four bytes in UTF-8 ๐
Setting UNIT to byte changes the column number to the raw byte count in all cases ๐งฎ That's how GCC did it before version 11.1.0, so it's giving throwback ๐ฐ๏ธ
-fdiagnostics-column-origin=ORIGINโ choose what number the first column starts at ๐ข
The default value of 1 matches traditional GCC behavior and the GNU style guide, so it's the safe pick โจ Some utilities might work better with an origin of 0, and any non-negative value can be specified ๐ธ
-fdiagnostics-escape-format=FORMATโ how weird bytes in source lines get escaped ๐ค
Normally, when GCC prints the relevant source lines for a diagnostic, it tries to print the source bytes directly ๐ But some diagnostics are about encoding issues in the source file, like malformed UTF-8 or Unicode normalization problems. Those get flagged, so GCC escapes any bytes that aren't printable ASCII when it prints those source lines ๐
This option controls how those bytes get escaped ๐
The default, unicode, displays non-printable-ASCII Unicode characters as <U+XXXX>, and bytes that aren't validly encoded UTF-8 as hexadecimal in the form <XX> ๐ฆ For example, say a source line has the string before, then the Unicode character U+03C0 ("GREEK SMALL LETTER PI", which is UTF-8 encoded as 0xCF 0x80), then the byte 0xBF (a stray UTF-8 trailing byte), then the string after. For that diagnostic it would be printed as:
before<U+03C0><BF>after
Setting FORMAT to bytes displays all non-printable-ASCII bytes as <XX>, which shows the underlying encoding of non-ASCII Unicode characters ๐ง For the same example above, this is what gets printed:
before<CF><80><BF>after
-fdiagnostics-format=FORMATโ pick a different format for printing diagnostics ๐ FORMAT istextorjson, and the default istext
The json format is a top-level JSON array full of JSON objects, each one representing a diagnostic ๐งพ
The JSON gets emitted as one line with no formatting, so the examples below were formatted just so they're readable ๐
Diagnostics can have child diagnostics. For example, this error and note:
misleading-indentation.c:15:3: warning: this 'if' clause does not
guard... [-Wmisleading-indentation]
15 | if (flag)
| ^~
misleading-indentation.c:17:5: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
17 | y = 2;
| ^
might be printed in JSON form (after formatting) like this:
[
{
"kind": "warning",
"locations": [
{
"caret": {
"display-column": 3,
"byte-column": 3,
"column": 3,
"file": "misleading-indentation.c",
"line": 15
},
"finish": {
"display-column": 4,
"byte-column": 4,
"column": 4,
"file": "misleading-indentation.c",
"line": 15
}
}
],
"message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"display-column": 5,
"byte-column": 5,
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"escape-source": false,
"message": "...this statement, but the latter is ..."
}
]
"escape-source": false,
"column-origin": 1,
}
]
Here the "note" is a child of the "warning" ๐ซง
A diagnostic has a "kind". If that kind is "warning", then there's an "option" key describing the command-line option that controls the warning โ ๏ธ
A diagnostic can have zero or more locations ๐โจ and each one can carry an optional "label" string plus up to three positions: a "caret" position, and optional "start" and "finish" positions. Each position is described by a "file" name, a "line" number, and three numbers that tell you the column:
display-columnโ counts display columns, accounting for tabs and multibyte characters ๐byte-columnโ counts raw bytes ๐งฎcolumnโ is equal to one of the two above, depending on-fdiagnostics-column-unit๐
All three columns are relative to the origin set by -fdiagnostics-column-origin. That's usually 1, but you can set it to 0 for compatibility with other tools that count columns from 0 ๐ธ The column origin gets recorded in the JSON output under the "column-origin" tag. In the examples below I've left out the extra column number outputs to keep things short, bestie ๐ซถ
Okay so, for example, this error:
bad-binary-ops.c:64:23: error: invalid operands to binary + (have 'S' {aka
'struct s'} and 'T' {aka 'struct t'})
64 | return callee_4a () + callee_4b ();
| ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| | |
| | T {aka struct t}
| S {aka struct s}
has three locations ๐ญ Its primary location is at the "+" token at column 23. It also has two secondary locations, one for the left and one for the right-hand side of the expression, and both of those have labels ๐ It might be printed in JSON form as:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"escape-source": false,
"message": "invalid operands to binary + ..."
}
If a diagnostic has fix-it hints, it gets a "fixits" array ๐ง The array is made of half-open intervals, kind of like the output of -fdiagnostics-parseable-fixits. For example, this diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
might be printed in JSON form as:
{
"children": [],
"fixits": [
{
"next": {
"column": 21,
"file": "demo.c",
"line": 8
},
"start": {
"column": 15,
"file": "demo.c",
"line": 8
},
"string": "color"
}
],
"kind": "error",
"locations": [
{
"caret": {
"column": 15,
"file": "demo.c",
"line": 8
},
"finish": {
"column": 20,
"file": "demo.c",
"line": 8
}
}
],
"escape-source": false,
"message": "\u2018struct s\u2019 has no member named ..."
}
So the fix-it hint basically says to swap out the text from "start" up to but not including "next" with the value of "string" โจ Deletions are written as an empty value for "string", and insertions are written by having "start" equal "next" ๐
If the diagnostic has a path of control-flow events attached, it gets a "path" array of objects that represent those events ๐ฆ Each event object has a "description" string, a "location" object, a "function" string, and a "depth" number, which is how interprocedural paths are represented. The "function" tells you the current function at that event, and the "depth" is the stack depth relative to some baseline: the higher the number, the more frames are on the stack ๐
For example, the intraprocedural example shown for -fdiagnostics-path-format= might have this JSON for its path:
"path": [
{
"depth": 0,
"description": "when 'PyList_New' fails, returning NULL",
"function": "test",
"location": {
"column": 10,
"file": "test.c",
"line": 25
}
},
{
"depth": 0,
"description": "when 'i < count'",
"function": "test",
"location": {
"column": 3,
"file": "test.c",
"line": 27
}
},
{
"depth": 0,
"description": "when calling 'PyList_Append', passing NULL from (1) as argument 1",
"function": "test",
"location": {
"column": 5,
"file": "test.c",
"line": 29
}
}
]
Diagnostics also have a boolean attribute called "escape-source" ๐ It hints whether non-ASCII bytes should be escaped when the relevant lines of source code get printed. It's "true" for diagnostics involving source encoding issues ๐ธ
โจ Options to Request or Suppress Warnings โจ
Warnings are diagnostic messages about constructions that aren't inherently wrong, but are risky or suggest there might have been an error ๐โ ๏ธ
These language-independent options don't turn on any specific warnings. Instead, they control the kinds of diagnostics GCC produces ๐
-fsyntax-onlyโ Checks the code for syntax errors, and that's it. It won't do anything beyond that ๐ โโ๏ธ-fmax-errors=nโ Limits the maximum number of error messages to n. When that limit is hit, GCC bails out instead of trying to keep processing the source code ๐ If n is0(the default), there's no limit on how many error messages get produced. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option ๐-wโ Inhibits all warning messages. Total silence ๐คซ-Werrorโ Turns all warnings into errors ๐-Werror=โ Turns the specified warning into an error. You append the warning's specifier to the end, so for example-Werror=switchturns the warnings controlled by-Wswitchinto errors ๐ฅ This switch also has a negative form, which negates-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐ซถ- The warning message for each controllable warning includes the option that controls it. You can then use that option with
-Werror=and-Wno-error=as described above. (Printing the option in the warning message can be turned off with the-fno-diagnostics-show-optionflag ๐) - Note that specifying
-Werror=fooautomatically implies-Wfoo. However,-Wno-error=foodoes not imply anything ๐ง
- The warning message for each controllable warning includes the option that controls it. You can then use that option with
-Wfatal-errorsโ Makes the compiler abort compilation on the first error it hits, instead of trying to keep going and printing more error messages ๐
You can request lots of specific warnings with options that start with -W. For example, -Wimplicit requests warnings on implicit declarations ๐ Each of these specific warning options also has a negative form that starts with -Wno- to turn the warnings off. For example, -Wno-implicit. This manual only lists one of the two forms, whichever one isn't the default ๐ For further language-specific options, also refer to C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. Additional warnings can be produced by enabling the static analyzer;
Some options, like -Wall and -Wextra, turn on other options, such as -Wunused, which may then turn on even more options, like -Wunused-value ๐ When you combine positive and negative forms, the more specific option wins over the less specific one, no matter where it sits on the command-line. For options of the same specificity, the last one takes effect. Options enabled or disabled via pragmas act as if they appeared at the end of the command-line ๐
When you request an unrecognized warning option (e.g., -Wunknown-warning), GCC emits a diagnostic saying the option isn't recognized ๐ญ The -Wno- form is a little different, though. No diagnostic is produced for -Wno-unknown-warning unless other diagnostics are being produced too. 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, bestie ๐ฅ. For example, -Wsuggest-final-types hits way harder with link-time optimization โจ, and some instances of other warnings won't get issued at all unless optimization is turned on. Optimization in general makes the control and data flow sensitive warnings more powerful ๐
, but in some cases it can also cause false positives ๐.
๐ -Wpedantic, -pedantic
Okay so these two are the strict-rules besties ๐. They make GCC issue all the warnings that strict ISO C and ISO C++ demand, and they reject any program using forbidden extensions, plus some other programs that don't follow ISO C and ISO C++. For ISO C, it follows whichever version of the standard you asked for with any -std option.
Valid ISO C and ISO C++ programs should compile just fine with or without this option ๐ (though a rare few need -ansi or a -std option that names the version of ISO C they require). Without this option, though, certain GNU extensions and traditional C and C++ features still get supported. With this option on, they get rejected ๐ญ.
-Wpedantic doesn't warn about the alternate keywords whose names begin and end with __. That alternate format can also turn off warnings for non-ISO __intN types, meaning __intN__ โจ. Pedantic warnings are also disabled in the expression that follows "__extension__". Real talk though: only system header files should use these escape routes, so application programs should steer clear of them ๐ซถ.
Some users try to use -Wpedantic to check their programs for strict ISO C conformance, and they quickly find it doesn't do exactly what they want ๐. It does find some non-ISO practices, but not all of them. It only catches the ones ISO C requires a diagnostic for, plus some others that diagnostics have been added for.
A feature that reports any failure to conform to ISO C might be useful in some situations, but it would take a ton of extra work and would be totally different from -Wpedantic. We don't have plans to support something like that in the near future ๐.
Where the standard set with -std is a GNU extended dialect of C, like gnu90 or gnu99, there's a corresponding base standard, which is the version of ISO C that the GNU dialect is built on. -Wpedantic gives warnings wherever the base standard requires them. (It wouldn't make sense to only warn about features outside the specified GNU C dialect, since by definition the GNU dialects include every feature the compiler supports with that option, so there'd be nothing to warn about ๐คทโโ๏ธ.)
๐ธ -pedantic-errors
Think of this one as -Wpedantic but with the drama turned all the way up ๐ค. It gives an error whenever the base standard (see -Wpedantic) requires a diagnostic. It also errors in some cases where there's undefined behavior at compile time, and in some other cases that don't stop compilation of programs that are valid according to the standard.
This is not the same as -Werror=pedantic ๐
โโ๏ธ. There are errors this option enables that -Werror=pedantic doesn't, and vice versa. Don't mix them up, bestie!
๐ -Wall
This one turns on all the warnings about constructions that some users consider questionable and that are easy to avoid (or easy to modify to prevent the warning), even when macros are involved ๐ง. It also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
-Wall turns on the following warning flags:
-Waddress
-Warray-bounds=1 (only with -O2)
-Warray-compare
-Warray-parameter=2 (C and Objective-C only)
-Wbool-compare
-Wbool-operation
-Wc++11-compat
-Wc++14-compat
-Wcatch-value (C++ and Objective-C++ only)
-Wchar-subscripts
-Wcomment
-Wdangling-pointer=2
-Wduplicate-decl-specifier (C and Objective-C only)
-Wenum-compare (in C/ObjC; this is on by default in C++)
-Wformat
-Wformat-overflow
-Wformat-truncation
-Wint-in-bool-context
-Wimplicit (C and Objective-C only)
-Wimplicit-int (C and Objective-C only)
-Wimplicit-function-declaration (C and Objective-C only)
-Winit-self (only for C++)
-Wlogical-not-parentheses
-Wmain (only for C/ObjC and unless -ffreestanding)
-Wmaybe-uninitialized
-Wmemset-elt-size
-Wmemset-transposed-args
-Wmisleading-indentation (only for C/C++)
-Wmismatched-dealloc
-Wmismatched-new-delete (only for C/C++)
-Wmissing-attributes
-Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros
-Wnarrowing (only for C++)
-Wnonnull
-Wnonnull-compare
-Wopenmp-simd
-Wparentheses
-Wpessimizing-move (only for C++)
-Wpointer-sign
-Wrange-loop-construct (only for C++)
-Wreorder
-Wrestrict
-Wreturn-type
-Wsequence-point
-Wsign-compare (only in C++)
-Wsizeof-array-div
-Wsizeof-pointer-div
-Wsizeof-pointer-memaccess
-Wstrict-aliasing
-Wstrict-overflow=1
-Wswitch
-Wtautological-compare
-Wtrigraphs
-Wuninitialized
-Wunknown-pragmas
-Wunused-function
-Wunused-label
-Wunused-value
-Wunused-variable
-Wuse-after-free=3
-Wvla-parameter (C and Objective-C only)
-Wvolatile-register-var
-Wzero-length-bounds
Note that some warning flags are not implied by -Wall ๐. Some of them warn about constructions that users generally don't consider questionable, but that you might occasionally want to check for. Others warn about constructions that are necessary or hard to avoid in some cases, and there's no simple way to change the code to suppress the warning. Some of them are enabled by -Wextra, but many of them must be enabled individually.
๐ -Wextra
This enables some extra warning flags that -Wall doesn't โจ. (This option used to be called -W. The older name is still supported, but -Wextra is more descriptive, so use that one ๐
.)
-Wclobbered
-Wcast-function-type
-Wdeprecated-copy (C++ only)
-Wempty-body
-Wenum-conversion (C only)
-Wignored-qualifiers
-Wimplicit-fallthrough=3
-Wmissing-field-initializers
-Wmissing-parameter-type (C only)
-Wold-style-declaration (C only)
-Woverride-init
-Wsign-compare (C only)
-Wstring-compare
-Wredundant-move (only for C++)
-Wtype-limits
-Wuninitialized
-Wshift-negative-value (in C++03 and in C99 and newer)
-Wunused-parameter (only with -Wunused or -Wall)
-Wunused-but-set-parameter (only with -Wunused or -Wall)
The option -Wextra also prints warning messages for the following cases ๐ง:
- A pointer is compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
- (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared
register. - (C++ only) Taking the address of a variable that has been declared
register. - (C++ only) A base class is not initialized in the copy constructor of a derived class.
๐ฆ -Wabi (C, Objective-C, C++ and Objective-C++ only)
This one warns about code affected by ABI changes ๐ฆ. That includes code that may not be compatible with the vendor-neutral C++ ABI, as well as the psABI for the particular target.
Since G++ now defaults to updating the ABI with each major release, -Wabi normally only warns about C++ ABI compatibility problems if a check was added later in a release series for an ABI issue discovered after the initial release. -Wabi warns about more things if an older ABI version is selected with -fabi-version=n.
You can also use -Wabi with an explicit version number to warn about C++ ABI compatibility with a particular -fabi-version level. For example, -Wabi=2 warns about changes relative to -fabi-version=2.
If an explicit version number is provided and -fabi-compat-version is not specified, the version number from this option is used for compatibility aliases. If no explicit version number is provided with this option, but -fabi-compat-version is specified, that version number is used for C++ ABI warnings.
Although an effort has been made to warn about all such cases, there are probably some cases that aren't warned about, even though G++ is generating incompatible code ๐ฌ. There may also be cases where warnings are emitted even though the generated code is compatible.
If you're worried that code generated by G++ might not be binary compatible with code generated by other compilers, you should rewrite your code to avoid these warnings ๐ซถ.
Known incompatibilities in -fabi-version=2 (which was the default from GCC 3.4 to 4.9) include:
- A template with a non-type template parameter of reference type was mangled incorrectly:
extern int N;
template <int &> struct S {};
void n (S<N>) {2}
This was fixed in -fabi-version=3.
- SIMD vector types declared using
__attribute ((vector_size))were mangled in a non-standard way that doesn't allow for overloading of functions taking vectors of different sizes.
The mangling was changed in -fabi-version=4.
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration was folded away.
These mangling issues were fixed in -fabi-version=5.
- Scoped enumerators passed as arguments to a variadic function are promoted like unscoped enumerators, causing
va_argto complain. On most targets this doesn't actually affect the parameter passing ABI, as there's no way to pass an argument smaller thanint.
Also, the ABI changed the mangling of template argument packs, const_cast, static_cast, prefix increment/decrement, and a class scope function used as a template argument.
These issues were corrected in -fabi-version=6.
- Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t.
These issues were corrected in -fabi-version=7.
- When mangling a function type with function-cv-qualifiers, the un-qualified function type was incorrectly treated as a substitution candidate.
This was fixed in -fabi-version=8, the default for GCC 5.1.
decltype(nullptr)incorrectly had an alignment of 1, leading to unaligned accesses. Note that this did not affect the ABI of a function with anullptr_tparameter, as parameters have a minimum alignment.
This was fixed in -fabi-version=9, the default for GCC 5.2.
- Target-specific attributes ๐ โ Stuff that changes what a type is, like the ia32 calling conventions on a function type (
stdcall,regparm, etc.), was NOT showing up in the mangled name. So you could get name collisions when function pointers were used as template arguments. Literal chaos ๐ญ
This was fixed in -fabi-version=10, which is the default for GCC 6.1. ๐
Okay so this option also turns on warnings about psABI-related changes โจ The known psABI changes at this point include:
- SysV/x86-64 unions with
long doublemembers ๐ โ these get passed in memory as the psABI specifies. Before GCC 4.4 that wasn't the case. Here's an example:
union U {
long double ld;
int i;
};
So union U is now always passed in memory. No cap, that's a big deal ๐ซถ
-Wchar-subscripts๐ธ โ Warns if an array subscript has typechar. This is a super common mistake, because programmers forget that this type is signed on some machines. This warning is enabled by-Wall.-Wno-coverage-mismatch๐ฆ โ Warns if feedback profiles don't match when you use-fprofile-use. If a source file changes between-fprofile-generateand-fprofile-use, the profile feedback files can fail to match the source, and GCC can't use the profile feedback info. By default this warning is on and treated as an error.-Wno-coverage-mismatchturns the warning off, and-Wno-error=coverage-mismatchturns off the error. Skipping the error can lead to poorly optimized code, so it's only useful for super minor changes, like bug fixes to an existing codebase. Fully disabling the warning is not recommended ๐-Wno-coverage-invalid-line-number๐ โ Warns in case a function ends earlier than it begins because of an invalid linenum macro. This warning is only emitted when--coverageis enabled.
By default this warning is on and treated as an error. -Wno-coverage-invalid-line-number can be used to turn the warning off, or -Wno-error=coverage-invalid-line-number can be used to turn off the error.
-Wno-cpp(C, Objective-C, C++, Objective-C++ and Fortran only) ๐ง โ Suppresses the warning messages emitted by#warningdirectives.-Wdouble-promotion(C, C++, Objective-C and Objective-C++ only) โจ โ Gives a warning when a value of typefloatis implicitly promoted todouble. CPUs with a 32-bit single-precision floating-point unit implementfloatin hardware but emulatedoublein software. On a machine like that, doing math withdoublevalues is way more expensive because of the software emulation overhead.
It's super easy to accidentally do double math, because floating-point literals are implicitly of type double. For example:
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) ๐ โ Warns if a declaration has a duplicateconst,volatile,restrictor_Atomicspecifier. This warning is enabled by-Wall.-Wformat,-Wformat=n๐ โ Checks calls toprintfandscanf, etc., to make sure the arguments you pass have types that match the format string, and that the conversions in the format string actually make sense. This covers standard functions, plus others specified by format attributes, in theprintf,scanf,strftimeandstrfmon(an X/Open extension, not in the C standard) families, or other target-specific families. Which functions get checked without format attributes depends on the standard version you pick, and those checks are disabled by-ffreestandingor-fno-builtin.
The formats are checked against the format features supported by GNU libc version 2.2. These include 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 -Wpedantic is used with -Wformat, you'll get warnings about format features that aren't in the selected standard version (but not for strfmon formats, since those aren't in any version of the C standard).
-Wformat=1,-Wformat๐ฆ โ-Wformatis the same as-Wformat=1, and-Wno-formatis the same as-Wformat=0. Since-Wformatalso checks for null format arguments for several functions,-Wformatalso 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.-Wformatis enabled by-Wall.-Wformat=2๐ฅ โ Enables-Wformatplus additional format checks. Right now it's equivalent to-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k.
-Wno-format-contains-nul๐ โ If-Wformatis specified, don't warn about format strings that contain NUL bytes.-Wno-format-extra-args๐ โ If-Wformatis specified, don't warn about excess arguments to aprintforscanfformat function. The C standard says those extra arguments are ignored.
If the unused arguments sit between used arguments that are specified with $ operand number specifications, warnings still happen by default, since the implementation couldn't know what type to pass to va_arg to skip the unused arguments. But 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๐ โ Warns about calls to formatted input/output functions, likesprintfandvsprintf, that might overflow the destination buffer. When the exact number of bytes written by a format directive can't be determined 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 can also cause false positives.-Wformat-overflow,-Wformat-overflow=1๐ธ โ Level 1 of-Wformat-overflowis enabled by-Wformatand takes a conservative approach, only warning about calls that most likely overflow the buffer. At this level, numeric arguments to format directives with unknown values are assumed to have the value of one, and strings of unknown length are assumed to be empty. Numeric arguments known to be bounded to a subrange of their type, or string arguments whose output is bounded either by their directive's precision or by a finite set of string literals, are assumed to take on the value within the range that produces the most bytes of output. For example, thesprintfcall below gets diagnosed, because even with bothaandbequal to zero, the terminating NUL character ('\0') appended to the destination buffer is written past its end. Making the buffer one byte bigger is enough to avoid the warning, though it may not be enough to avoid the overflow.
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
-Wformat-overflow=2๐ โ Level 2 warns about calls that might overflow the destination buffer given an argument of sufficient length or magnitude. At level 2, unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments whose length can't be assumed to be bounded, either by the directive's precision or by a finite set of string literals they may evaluate to, or by the character array they may point to, are assumed to be 1 character long.
At level 2, the call in the example above is diagnosed again, but this time it's because, with a equal to a 32-bit INT_MIN, the first %i directive will write some of its digits beyond the end of the destination buffer. To make the call safe no matter what the two variables are, the destination buffer has to be at least 34 bytes. GCC includes the minimum buffer size in an informational note after the warning.
An alternative to making the destination buffer bigger is to limit the range of the formatted values. You can bound the maximum length of string arguments by specifying a precision in the format directive. When numeric arguments of format directives can be assumed to be bounded by less than the precision of their type, picking an appropriate length modifier for the format specifier will reduce the required buffer size. For example, if a and b in the example above can be assumed to be within the precision of the short int type, then using either the %hi format directive or casting the argument to short reduces the maximum required buffer size to 24 bytes.
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
-Wno-format-zero-length๐งธ โ If-Wformatis specified, don't warn about zero-length formats. The C standard says zero-length formats are allowed.-Wformat-nonliteral๐ซง โ If-Wformatis specified, also warn if the format string is not a string literal and so can't be checked, unless the format function takes its format arguments as ava_list.-Wformat-securityโ okay so if you've got-Wformaton, this one also goes hunting for format calls that could be a security problem ๐ญ๐. Right now it side-eyesprintfandscanfcalls where the format string isn't a string literal and there aren't any format arguments, likeprintf (foo);. That can be a real security hole if the format string came from untrusted input and has%nin it ๐. (ngl this is currently just a subset of what-Wformat-nonliteralcatches, but future-Wformat-securitywarnings might cover stuff that-Wformat-nonliteraldoesn't ๐ฎ.)-Wformat-signednessโ if-Wformatis specified, this one also warns when the format string wants an unsigned argument but you gave it a signed one, and vice versa ๐งฎโจ.-Wformat-truncation,-Wformat-truncation=levelโ warns about formatted input/output calls likesnprintfandvsnprintfthat might chop your output short โ๏ธ. When the exact number of bytes a format directive writes can't be figured out at compile time, GCC guesses using heuristics that depend on the level argument and on optimization. Turning on optimization usually makes the warning more accurate, but it can also cause false positives ๐. Unless noted otherwise, this option uses the same logic as-Wformat-overflow.-Wformat-truncation,-Wformat-truncation=1โ level 1 (enabled by-Wformat) is the chill, conservative option ๐ง. It only warns about bounded function calls whose return value is unused and that will most likely end up truncating the output.-Wformat-truncation=2โ level 2 goes further and also warns about bounded function calls whose return value is used and that might truncate given an argument of sufficient length or magnitude ๐.
-Wformat-y2kโ if-Wformatis specified, also warn aboutstrftimeformats that may yield only a two-digit year ๐ .-Wnonnullโ warns when you pass a null pointer for arguments thenonnullfunction attribute says must be non-null ๐ซ. It's included in-Walland-Wformat, and you can turn it off with-Wno-nonnull.-Wnonnull-compareโ warns when you compare an argument marked with thenonnullfunction attribute against null inside the function ๐. It's included in-Walland can be disabled with-Wno-nonnull-compare.-Wnull-dereferenceโ warns if GCC detects paths that trigger erroneous or undefined behavior from dereferencing a null pointer ๐ฅ. This one is only active when-fdelete-null-pointer-checksis active, which optimizations enable on most targets. How precise the warnings are depends on the optimization options you used ๐ฏ.-Winfinite-recursionโ warns about infinitely recursive calls ๐โพ๏ธ. It's effective at all optimization levels, but you need optimization to catch infinite recursion in calls between two or more functions. It's included in-Wall.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ warns about uninitialized variables that get initialized with themselves ๐คก. Note this option can only be used with-Wuninitialized.
For example, GCC warns about "i" being uninitialized in the following snippet only when -Winit-self has been specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++.
-Wno-implicit-int(C and Objective-C only) โ controls warnings when a declaration doesn't specify a type ๐ค. This warning is enabled by default in C99 and later dialects of C, and also by-Wall.-Wno-implicit-function-declaration(C and Objective-C only) โ controls warnings when a function is used before being declared ๐ฃ. This warning is enabled by default in C99 and later dialects of C, and also by-Wall. It gets turned into an error by-pedantic-errors๐จ.-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declaration๐ฏ. This warning is enabled by-Wall.-Wimplicit-fallthroughโ the same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0๐.-Wimplicit-fallthrough=nโ warns when a switch case falls through ๐โโ๏ธ. For example:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
This warning doesn't fire when the last statement of a case can't fall through, e.g. when there's a return statement or a call to a function declared with the noreturn attribute ๐. -Wimplicit-fallthrough= also takes control flow statements, such as ifs, into account and only warns when appropriate. For example:
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Since there are occasions where a switch case fall through is desirable, GCC provides an attribute, __attribute__ ((fallthrough)), that is to be used along with a null statement to suppress this warning that would normally occur ๐ซถ:
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 provides a standard way to suppress the -Wimplicit-fallthrough warning using [[fallthrough]]; instead of the GNU attribute โจ. In C++11 or C++14, users can use [[gnu::fallthrough]];, which is a GNU extension. Instead of these attributes, it's also possible to add a fallthrough comment to silence the warning ๐ฌ. The whole body of the C or C++ style comment should match the given regular expressions listed below. The option argument n specifies what kind of comments are accepted:
-Wimplicit-fallthrough=0disables the warning altogether ๐ .-Wimplicit-fallthrough=1matches the".*"regular expression, so any comment is used as a fallthrough comment.-Wimplicit-fallthrough=2case insensitively matches the".*falls?[ \t-]*thr(ough|u).*"regular expression.-Wimplicit-fallthrough=3case sensitively matches one of the following regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s |\n|-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s |\n|-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4case sensitively matches one of the following regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5doesn't recognize any comments as fallthrough comments, so only attributes disable the warning ๐ซ๐ฌ.
The comment needs to be followed, after optional whitespace and other comments, by "case" or "default" keywords, or by a user label that precedes some "case" or "default" label ๐ท๏ธ:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is enabled by -Wextra.
-Wno-if-not-aligned(C, C++, Objective-C and Objective-C++ only) โ controls whether warnings triggered by thewarn_if_not_alignedattribute should be issued ๐. These warnings are enabled by default.-Wignored-qualifiers(C and C++ only) โ warns if the return type of a function has a type qualifier such asconst๐. For ISO C, a qualifier like that has no effect, since the value returned by a function isn't an lvalue. For C++, the warning is only emitted for scalar types orvoid. ISO C prohibits qualifiedvoidreturn types on function definitions, so those always get a warning, even without this option. This warning is also enabled by-Wextra.-Wno-ignored-attributes(C and C++ only) โ controls warnings when an attribute is ignored ๐. This is different from the-Wattributesoption, because it warns whenever the compiler decides to drop an attribute, not when the attribute is unknown, used in a wrong place, etc. This warning is enabled by default.-Wmainโ warns if the type ofmainis suspicious ๐.mainshould be a function with external linkage, returningint, taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++ and is enabled by either-Wallor-Wpedantic.-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". */
In the case of mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up (defaulting to 8) ๐.
The warning is not issued for code involving multiline preprocessor logic, such as the following example ๐ง:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
This one goes quiet after a #line directive ๐ because that usually means autogenerated code, and nobody can assume anything about the layout of the file the directive points to. โจ
This warning is enabled by -Wall in C and C++. ๐
โจ -Wmissing-attributes โจ
okay so this one checks if a function declaration is missing an attribute that a related function has, and that absence could mess with the correctness or efficiency of the generated code ๐ For example, it fires on alias declarations that use attributes to ask for less restrictive stuff than their targets. That usually means you've got a potential optimization just sitting there, bestie ๐ง
By contrast, -Wattribute-alias=2 is the one that warns when the alias is more restrictive than the target, which could lead to incorrect code generation ๐ญ Attributes this warning considers are "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc", "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull", and "returns_twice". ๐ธ
In C++, the warning kicks in when an explicit specialization of a primary template is declared without one of these attributes, if the primary template had "alloc_align", "alloc_size", "assume_aligned", "format", "format_arg", "malloc", or "nonnull". Attributes "deprecated", "error", and "warning" suppress the warning. ๐ซถ
You can use the "copy" attribute to apply the same set of attributes to a declaration as another declaration has, without explicitly listing them all. ๐ฆ This attribute works on declarations of functions, variables, or types.
-Wmissing-attributes is enabled by -Wall. ๐
Here's the vibe: the primary function template below uses both "malloc" and "alloc_size", so the explicit specialization of the template gets flagged for missing one of them ๐
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
โจ -Wmissing-braces โจ
This one warns if an aggregate or union initializer isn't fully bracketed ๐ In the example below, the initializer for a isn't fully bracketed, but the one for b is. Iykyk, the second one is the slay ๐
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall. ๐
โจ -Wmissing-include-dirs (C, C++, Objective-C, Objective-C++ and Fortran only) โจ
Warns if a user-supplied include directory doesn't exist ๐ This option is disabled by default for C, C++, Objective-C, and Objective-C++. For Fortran, it's partially enabled by default, but only for -I and -J ๐
โจ -Wno-missing-profile โจ
ngl this one's about profile feedback ๐ It controls warnings when feedback profiles are missing while you're using -fprofile-use. It's looking for cases where a new function or a new file got added between compiling with -fprofile-generate and compiling with -fprofile-use, without regenerating the profiles ๐ In those cases, the profile feedback data files don't contain any profile info for the new function or file.
Also, if profile count data (.gcda) files get removed, GCC can't use any profile feedback info at all ๐ In all of these situations, you get warnings telling you a profile generation step is due. Ignoring them can result in poorly optimized code, so be careful, bestie ๐ญ
-Wno-missing-profile can be used to turn the warning off, but that is not recommended and should only be done when the non-existent profile data is justified ๐ซถ
โจ -Wmismatched-dealloc โจ
Okay this one is so good. It warns for calls to deallocation functions that get pointer arguments returned from allocation functions where the former isn't a suitable deallocator for the latter ๐ฅ A pair of functions can be linked up as matching allocator and deallocator using the malloc attribute.
Unless you turn it off with -fno-builtin, the standard functions "calloc", "malloc", "realloc", and "free", plus the matching forms of C++ "operator new" and "operator delete", are implicitly associated as matching allocators and deallocators ๐ In the example below, mydealloc is the deallocator for pointers returned from myalloc.
void mydealloc (void*);
__attribute__ ((malloc (mydealloc, 1))) void*
myalloc (size_t);
void f (void)
{
void *p = myalloc (32);
// ...use p...
free (p); // warning: not a matching deallocator for myalloc
mydealloc (p); // ok
}
In C++, the related option -Wmismatched-new-delete diagnoses mismatches involving either "operator new" or "operator delete" ๐ฆ
Option -Wmismatched-dealloc is included in -Wall. ๐
โจ -Wmultistatement-macros โจ
This one warns about unsafe multi-statement macros that look guarded by a clause like if, else, for, switch, or while, but where only the first statement is actually guarded after the macro gets expanded ๐ญ
Here's the trap: the macro below will increment y unconditionally, not just when c holds ๐
#define DOIT x++; y++
if (c)
DOIT;
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 โจ
This one warns when parentheses are left out in certain contexts, like when there's an assignment where a truth value is expected, or when operators are nested in ways people often get confused about ๐ง
It also warns if a comparison like x<=y<=z shows up. That's equivalent to (x<=y ? 1 : 0) <= z, which is a different interpretation from ordinary math notation, so it's a whole vibe check ๐
โโ๏ธ
It also warns about dangerous uses of the GNU extension to ?: with an omitted middle operand. When the condition in the ?: operator is a boolean expression, the omitted value is always 1. Programmers often expect it to be a value computed inside the conditional expression instead, which is not it ๐
For C++, this also warns about 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 โจ
Let's talk about sequence points, the chaotic little rules that decide when stuff in an expression gets evaluated ๐ This warning flags code that may have undefined semantics because it breaks those rules in C and C++.
Basically, sequence points are a partial ordering between parts of the program: the stuff before a sequence point and the stuff after it. They happen after a full expression is evaluated, after the first operand of &&, ||, ? :, or , (comma) is evaluated, before a function is called (but after its arguments and the expression denoting the called function are evaluated), and in certain other places. Other than that, the order of evaluating subexpressions isn't specified. Even so, the standards committee has ruled that function calls don't overlap โจ
It's not specified when between sequence points changes to object values take effect. Programs that depend on this have undefined behavior. The standards say that "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored." If a program breaks these rules, the results on any particular implementation are entirely unpredictable ๐ญ๐ฅ
Examples of 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 the occasional false positive, but overall it's been found pretty effective at catching this kind of problem in programs ๐ซถ
The C++17 standard will define the order of evaluation for operands in more cases. In particular, it requires the right-hand side of an assignment to be evaluated before the left-hand side, so the examples above are no longer undefined. But this option will still warn about them, to help people avoid writing code that's undefined in C and earlier revisions of C++ ๐
The standard is worded confusingly, so there's some debate over the precise meaning of the sequence point rules in subtle cases. Links to discussions of the problem, including proposed formal definitions, can be found on the GCC readings page at https://gcc.gnu.org/readings.html ๐
This warning is enabled by -Wall for C and C++. ๐
โจ -Wno-return-local-addr โจ
Do not warn about returning a pointer (or, in C++, a reference) to a variable that goes out of scope after the function returns ๐ฆ
โจ -Wreturn-type โจ
This one warns whenever a function is defined with a return type that defaults to int ๐ It also warns about any return statement with no return value in a function whose return type isn't void. Falling off the end of the function body counts as returning without a value, so yep, that's flagged too ๐
Okay bestie, this one is C only ๐
It warns you when a return has an expression in a function whose return type is void, unless that expression is also void โจ As a GNU extension, that last case gets a pass with no warning unless you use -Wpedantic ๐ซถ
๐ญ Undefined alert: trying to use the return value of a non-voidfunction (other thanmain) that just flows off the end by reaching the closing curly brace is undefined. Do not do this bestie.
Unlike in C, in C++ flowing off the end of a non-void function (other than main) is undefined behavior even if you never use the return value ๐
This warning is on by default in C++, and in C it comes along with -Wall ๐
-Wno-shift-count-negativeโ Warns if a shift count is negative. This one is on by default, so you get it for free ๐ธ-Wno-shift-count-overflowโ Warns if a shift count is greater than or equal to the bit width of the type. Also on by default ๐-Wshift-negative-valueโ Warns when you left shift a negative value. It's turned on by-Wextrain C99 and C++11 modes (and newer) ๐ฆ-Wno-shift-overflow,-Wshift-overflow=nโ These two control warnings about left shift overflows ๐-Wshift-overflow=1โ This is the level-Wshift-overflowuses, and it's on by default in C99 and C++11 modes (and newer). It does not warn about left-shifting1into the sign bit. (In C, that overflow still gets 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 in that mode โจ-Wshift-overflow=2โ This level also warns about left-shifting1into the sign bit, unless C++14 mode (or newer) is active ๐
-Wswitchโ Warns whenever aswitchstatement has an index of enumerated type and is missing acasefor one or more of the named codes in that enum. (Adefaultlabel stops this warning from happening ๐ โโ๏ธ)caselabels outside the enum range also get flagged with this option, even if there's adefaultlabel. Enabled by-Wall๐-Wswitch-defaultโ Warns whenever aswitchstatement doesn't have adefaultcase ๐ง-Wswitch-enumโ Same vibe as-Wswitch, withcaselabels outside the enum range flagged too. The only real difference is that this one warns about an omitted enum code even if there's adefaultlabel. Main character energy ๐-Wno-switch-boolโ Doesn't warn when aswitchhas a boolean index and the case values are outside the range of a boolean. You can shush this warning by casting the controlling expression to a type other thanbool. For example:
switch ((int) (a == 4))
{
...
}
This warning is on by default for C and C++ programs ๐
-Wno-switch-outside-rangeโ Controls warnings when aswitchcasehas a value outside of its type's range. Enabled by default for C and C++ programs ๐ซง-Wno-switch-unreachableโ Doesn't warn when aswitchhas statements between the controlling expression and the firstcaselabel that will never run. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
-Wswitch-unreachable won'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 on 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. Heads up, 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 shush this one, use the unused attribute.
This warning is also turned on by -Wunused together with -Wextra โจ
-Wunused-but-set-variableโ Warns whenever a local variable gets assigned to but is otherwise unused (aside from its declaration). Enabled by-Wall๐ฆ
To shush this one, use the unused attribute.
This warning is 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. Enabled by-Wall๐-Wunused-labelโ Warns whenever a label is declared but never used. Enabled by-Wall๐ง
To shush this one, use the unused attribute.
-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ Warns when a typedef defined locally inside a function isn't used. Enabled by-Wall๐-Wunused-parameterโ Warns whenever a function parameter is unused aside from its declaration ๐
To shush this one, use the unused attribute.
-Wno-unused-resultโ Doesn'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++. Enabled by-Wallโจ
To shush this one, use the unused attribute.
-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's not an error, since const variables take the place of#defines ๐
To shush this one, use the unused attribute.
-Wunused-const-variable=1โ This is the level that-Wunused-variableenables for C. It only warns about unused static const variables defined in the main compilation unit, not about static const variables 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). It's the level of-Wunused-const-variableand must be explicitly requested, since in C++ it isn't an error and in C it might be harder to clean up every header that's included ๐งน
-Wunused-valueโ Warns whenever a statement computes a result that is explicitly not used. To shush it, cast the unused expression tovoid. This covers an expression-statement or the left-hand side of a comma expression that has no side effects. For example, an expression likex[i,j]causes a warning, whilex[(void)i,j]does not. Enabled by-Wall๐ฅ-Wunusedโ All the above-Wunusedoptions combined. ๐ซง
To get a warning about an unused function parameter, you must either specify -Wextra -Wunused (note that -Wall implies -Wunused), or separately specify -Wunused-parameter.
-Wuninitializedโ Warns if an object with automatic or allocated storage duration is used without having been initialized. In C++, it also warns if a non-static reference or non-staticconstmember appears in a class without constructors ๐ญ
Passing 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 is also diagnosed by this warning. (-Wmaybe-uninitialized is issued for ordinary functions.)
If you want to warn about code that uses the uninitialized value of a variable in its own initializer, use the -Winit-self option ๐ซถ
These warnings happen for individual uninitialized elements of structure, union or array variables, as well as for variables that are uninitialized as a whole. They do not happen 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 version of GCC you're using ๐
There may be no warning about a variable that's only used to compute a value that itself is never used, because those computations may be deleted by data flow analysis before the warnings are printed ๐
In C++, this warning also warns about using uninitialized objects in member-initializer-lists. For example, GCC warns about b being uninitialized in the following snippet:
struct A {
int a;
int b;
A() : a(b) { }
};
-Wno-invalid-memory-modelโ Controls warnings for invocations of__atomicbuilt-ins,__syncbuilt-ins, and the C11 atomic generic functions with a memory consistency argument that's either invalid for the operation or outside the range of values of thememory_orderenumeration. For example, since__atomic_storeand__atomic_store_nare only defined for the relaxed, release, and sequentially consistent memory orders, the following code is diagnosed:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
-Winvalid-memory-model is enabled by default ๐
-Wmaybe-uninitializedโ For an object with automatic or allocated storage duration: if there's a path from the function entry to a use of the object that is initialized, but there are other paths where it isn't, the compiler emits a warning if it can't prove those uninitialized paths never run at runtime ๐ฆ
Passing a pointer (or in C++, a reference) to an uninitialized object into a const-qualified function argument also gets flagged by this warning ๐. (-Wuninitialized fires for built-in functions known to read the object.) If you annotate the function with the attribute access (none), you're telling GCC the argument doesn't access the object, and the warning goes poof โจ.
These warnings only show up in optimizing compilation, because otherwise GCC doesn't keep track of the state of variables ๐ง.
They're optional because GCC sometimes can't tell that code is correct even when it looks like an error ๐ฅบ. Here's a classic example:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know that ๐. To shush the warning, add 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. It can't know where longjmp will be called, and honestly, a signal handler could call it at any point in the code ๐. So you might get a warning even when there's no real problem, because longjmp can't actually be called at the place that would cause one.
Some spurious warnings can be avoided if you declare every function you use that never returns as noreturn ๐ซถ.
This warning is enabled by -Wall or -Wextra โจ.
-Wunknown-pragmasโ Warns when GCC runs into a#pragmadirective it doesn't understand ๐. If you turn this on from the command line, you'll even get warnings for unknown pragmas hiding in system header files. That doesn't happen if it's only enabled by the-Wallcommand-line option.-Wno-pragmasโ Chill, GCC, no warnings about pragma misuse ๐ธ. That covers incorrect parameters, invalid syntax, or pragmas clashing with each other. See also-Wunknown-pragmas.-Wno-prio-ctor-dtorโ Don't warn if a priority from 0 to 100 is used for a constructor or destructor ๐. Constructor and destructor attributes let you set a priority to control their order of execution beforemainis called or after it returns. Priority values have to be greater than100, because the compiler reserves0--100for its own implementation โญ.-Wstrict-aliasingโ This one only works 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โ Also only active when-fstrict-aliasingis active ๐. It warns about code that might break the strict aliasing rules used for optimization. Higher levels mean higher accuracy (fewer false positives), but also 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 the code, since it has very few false negatives. The catch is it has many false positives. It warns for all pointer conversions between possibly incompatible types, even if the pointer is never dereferenced. It runs in the front end only. - Level 2 โ Aggressive and quick, but not too precise ๐. It may still have many false positives (not as many as level 1, though) and few false negatives (possibly more than level 1). Unlike level 1, it only warns when an address is taken. It warns about incomplete types. It runs in the front end only.
- Level 3 (default for
-Wstrict-aliasing) โ The main character of levels ๏ฟฝรซ๏ฟฝ. It should have very few false positives and few false negatives. It's slightly slower than levels 1 or 2 when optimization is enabled. It handles the common pun+dereference pattern in the front end, like*(int*)&some_float. If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. It only warns when the converted pointer is dereferenced, and it doesn't warn about incomplete types.
- Level 1 โ Most aggressive, quick, and least accurate ๐ต. It's possibly useful when higher levels don't warn but
-Wstrict-overflow,-Wstrict-overflow=nโ 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 place the code might overflow, only where the compiler actually implements some optimization, so this warning depends on the optimization level.
An optimization that assumes 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 undefined signed overflow when estimating how many iterations a loop needs, particularly when figuring out whether a loop runs at all.
-Wstrict-overflow=1โ Warns about cases that are both questionable and easy to avoid ๐งน. For example, the compiler simplifiesx + 1 > xto1. This level is enabled by-Wall. Higher levels aren't, so you have to request them explicitly.-Wstrict-overflow=2โ Also warns about other cases where a comparison gets simplified to a constant ๐ง . For example:abs (x) >= 0. That can only be simplified when signed integer overflow is undefined, becauseabs (INT_MIN)overflows toINT_MIN, which is less than zero.-Wstrict-overflowwith no level is the same as-Wstrict-overflow=2.-Wstrict-overflow=3โ Also warns about other cases where a comparison is simplified ๐. For example:x + 1 > 1is simplified tox > 0.-Wstrict-overflow=4โ Also warns about other simplifications that aren't covered by the cases above ๐. For example:(x * 10) / 5is simplified tox * 2.-Wstrict-overflow=5โ Also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison ๐ญ. For example:x + 2 > yis simplified tox + 1 >= y. This is only reported at the highest warning level, because this simplification applies to so many comparisons that this level gives a very large number of false positives.
-Wstring-compareโ Warns for calls tostrcmpandstrncmpwhose result gets determined to be always zero or always non-zero in equality tests. That happens because the length of one argument is greater than the size of the array the other argument is stored in (or the bound, in the case ofstrncmp) ๐งต. Such calls could be mistakes. Here's an example:
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");
}
The strcmp call in that example gets diagnosed, because its result is necessarily non-zero no matter what the contents of the array a are ๐ซ. -Wstring-compare is enabled by -Wextra.
-Wno-stringop-overflow,-Wstringop-overflow,-Wstringop-overflow=typeโ Warns for calls to string manipulation functions likememcpyandstrcpythat would overflow the destination buffer ๐ฅ. The optional argument is one greater than the type of Object Size Checking to perform when determining the size of the destination. That argument only matters for functions that operate on character arrays, not raw memory functions likememcpy, which always use Object Size type-0. The option also warns for calls that specify a size bigger than the largest possible object, or at mostSIZE_MAX / 2bytes. It gets the best results with optimization enabled, but it can also catch a small subset of simple buffer overflows without optimization, in calls to GCC built-in functions like__builtin_memcpythat match the standard functions ๐ซถ. Either way, it only warns about a subset of the buffer overflows the matching overflow-checking built-ins detect.
For example, this option warns about the strcpy call below, because it copies at least 5 characters (the string "blue" including the terminating NUL) into a buffer of size 4 ๐.
enum Color { blue, purple, yellow };
const char* f (enum Color clr)
{
static char buf [4];
const char *str;
switch (clr)
{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
}
return strcpy (buf, str); // warning here
}
-Wstringop-overflow=2 is enabled by default ๐.
-Wstringop-overflow,-Wstringop-overflow=1โ This one uses type-zero Object Size Checking to determine the sizes of destination objects ๐ฆ. At this setting, it doesn't warn for writes past the end of subobjects of larger objects accessed by pointers, unless the size of the largest surrounding object is known. When the destination might be one of several objects, it's assumed to be the largest one of them. On Linux systems, when optimization is enabled at this setting, the option warns for the same code as when the_FORTIFY_SOURCEmacro is defined to a non-zero value ๐.
-Wstringop-overflow=2โ ๐ okay so this level uses type-one Object Size Checking to figure out how big the destination objects are. At this setting it warns about overflows when writing to members of the largest complete objects whose exact size is known. It does not warn for excessive writes to the same members of unknown objects referenced by pointers, since those pointers might point to arrays with unknown numbers of elements ๐. This is the default setting of the option โจ.-Wstringop-overflow=3โ ๐ this one switches to type-two Object Size Checking for the destination sizes. It warns about overflowing the smallest object or data member. It's the most restrictive setting that can still warn on code that's actually safe, so ngl it can be a little dramatic ๐ .-Wstringop-overflow=4โ ๐ฆ type-three Object Size Checking is the next level up. It warns about overflowing any data members, and when the destination is one of several objects, it uses the size of the largest one to decide whether to warn. Just like-Wstringop-overflow=3, this setting may also warn about benign code ๐ธ.-Wno-stringop-overreadโ ๐ง warns for calls to string manipulation functions such asmemchrorstrcpythat are determined to read past the end of the source sequence.
Option -Wstringop-overread is enabled by default โจ.
-Wno-stringop-truncationโ ๐ do not warn for calls to bounded string manipulation functions such asstrncat,strncpy, andstpncpythat may either truncate the copied string or leave the destination unchanged.
Here's a little example. The call to strncat sets a bound that's smaller than the length of the source string, so the copy gets truncated and the call is diagnosed ๐. To avoid the warning, use bufsize - strlen (buf) - 1) as the bound.
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Another one: this strncpy call copies just the characters before the terminating NUL, so the result never gets a NUL at the end. Assuming the result of strncpy is always NUL-terminated is a super common mistake, so the call gets diagnosed ๐. To avoid the warning when the result isn't supposed to be NUL-terminated, call memcpy instead.
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
And here the call to strncpy uses the size of the destination buffer as the bound. If the source string's length is equal to or greater than that size, the copy won't be NUL-terminated, so yep, it's diagnosed too ๐. To avoid it, 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 skip this warning ๐ซถ. Just know that these arrays aren't suitable for functions that expect NUL-terminated strings. To help catch accidental misuse, GCC still issues warnings for them unless it can prove the use is safe.
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]โ ๐ warns for cases where adding an attribute might be beneficial. The attributes currently supported are listed below.-Wsuggest-attribute=pure,-Wsuggest-attribute=const,-Wsuggest-attribute=noreturn,-Wmissing-noreturn,-Wsuggest-attribute=mallocโ ๐ฅ warns about functions that might be good candidates for the attributespure,const,noreturn, ormalloc. The compiler only warns for functions that are visible in other compilation units, or (forpureandconst) if it can't prove the function returns normally. A function returns normally if it doesn't contain an infinite loop and doesn't return abnormally by throwing, callingabort, or trapping. This analysis requires option-fipa-pure-const, which is enabled by default at-Oand higher. Higher optimization levels make the analysis more accurate โจ.-Wsuggest-attribute=format,-Wmissing-format-attributeโ ๐ธ warns about function pointers that might be candidates forformatattributes. These are only possible candidates, not absolute ones. GCC guesses that function pointers withformatattributes that get used in assignment, initialization, parameter passing, or return statements should have a matchingformatattribute in the resulting type. In other words, the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function should also have aformatattribute to avoid the warning.
GCC also warns about function definitions that might be candidates for format attributes, and again, these are only possible candidates ๐ง . GCC guesses that format attributes might be appropriate for any function that calls a function like vprintf or vscanf. That's not always the case though, and some functions that really should have format attributes may not get detected.
-Wsuggest-attribute=coldโ ๐ง warns about functions that might be candidates for thecoldattribute. This is based on static detection, and it generally only warns about functions that always lead to a call to anothercoldfunction, like wrappers of C++throwor fatal error reporting functions that lead toabort.
-Walloc-zeroโ ๐ 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.
Heads up bestie: the behaviour of these functions when called with a zero size differs between implementations (and realloc has been deprecated for this). Relying on it can cause sneaky portability bugs, so it's best to avoid it ๐ซ.
-Walloc-size-larger-than=byte-sizeโ ๐ warns about calls to functions decorated with the attributealloc_sizethat try to allocate objects larger than the specified number of bytes. It also warns when the result of the size computation, done in an integer type with infinite precision, would exceed the value ofPTRDIFF_MAXon the target.-Walloc-size-larger-than=PTRDIFF_MAXis enabled by default ๐. You can disable the warnings controlled by this option either by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-alloc-size-larger-than.-Wno-alloc-size-larger-thanโ ๐ disables-Walloc-size-larger-than=warnings. This option is equivalent to-Walloc-size-larger-than=SIZE_MAXor larger.-Wallocaโ ๐ warns on all uses ofallocain the source. No exceptions, no cap ๐งข.-Walloca-larger-than=byte-sizeโ ๐ช warns on calls toallocawith an integer argument whose value is either zero, or that isn't bounded by a controlling predicate limiting it to at most byte-size. It also warns for calls toallocawhere the bound value is unknown. Arguments of non-integer types are treated as unbounded, even if they look like they're constrained to the expected range.
Here's a bounded use of alloca:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
In this example, passing -Walloca-larger-than=1000 won't issue a warning, because the call to alloca is known to be at most 1000 bytes. But if -Walloca-larger-than=500 were passed, the compiler would emit a warning ๐ค.
Unbounded uses are the ones where alloca has no controlling predicate constraining its integer argument. For example:
void func ()
{
void *p = alloca (n);
f (p);
}
If -Walloca-larger-than=500 were passed, the code above would trigger a warning, this time because there's no bounds checking at all ๐.
Note that even seemingly correct code involving signed integers can cause a warning:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
In this example, n could be negative, which would cause a larger than expected argument to be implicitly cast into the alloca call. Rude ๐ญ.
This option also warns when alloca is used in a loop ๐.
-Walloca-larger-than=PTRDIFF_MAX is enabled by default, but it's usually only effective when -ftree-vrp is active (the default for -O2 and above) ๐.
See also -Wvla-larger-than=byte-size.
-Wno-alloca-larger-thanโ ๐ซ disables-Walloca-larger-than=warnings. This option is equivalent to-Walloca-larger-than=SIZE_MAXor larger.-Warith-conversionโ ๐ข do warn about implicit conversions from arithmetic operations, even when converting the operands to the same type can't change their values. This affects warnings from-Wconversion,-Wfloat-conversion, and-Wsign-conversion.
void f (char c, int i)
{
c = c + i; // warns with -Wconversion
c = c + 1; // only warns with -Warith-conversion
}
-Warray-bounds,-Warray-bounds=nโ ๐ warns about out-of-bounds subscripts or offsets into arrays. This warning is enabled by-Wallโจ. It's more effective when-ftree-vrpis active (the default for-O2and above), but a subset of instances are issued even without optimization ๐ .
- -Warray-bounds=1 โ okay bestie, this is the default level of -Warray-bounds, and it's already switched on by -Wall โจ Higher levels are NOT on by default, so you have to ask for them explicitly ๐
-Warray-bounds=2โ this stricter level also catches out of bounds accesses to trailing struct members of one-element array types, plus intermediate results of pointer arithmetic that might land out of bounds ๐ It can throw a bigger pile of false positives, so it's deactivated by default ๐-Warray-compareโ warns about equality and relational comparisons between two operands of array type ๐ This comparison got deprecated in C++20, so be careful, babe ๐ Here's the vibe:
int arr1[5];
int arr2[5];
bool same = arr1 == arr2;
-Warray-compare is enabled by -Wall ๐
-Warray-parameter,-Warray-parameter=nโ this one warns about redeclarations of functions where the array or pointer arguments are inconsistent in kind or form ๐ฆ It also turns on detection of out-of-bounds accesses to those parameters, caught by warnings like-Warray-bounds๐ฅ
If the first function declaration uses the array form, the bound in the array is treated as the minimum number of elements you must pass in, and the maximum number of elements the function touches. So passing too-small arrays or accessing more than that max might get flagged by warnings like -Warray-bounds ๐ซถ At level 1, the warning catches inconsistencies involving array parameters declared with the "T[static N]" form ๐ธ
Here's why the warning fires in this example: the first declaration lets an array of any size get passed to f, but the second one uses the keyword static to demand 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, so they don't trigger a warning ๐ง
void g (int*);
void g (int[]); // no warning
void g (int[8]); // warning (inconsistent array bound)
-Warray-parameter=2 is included in -Wall โจ And the -Wvla-parameter option does the same kind of thing, but for Variable Length Array arguments ๐
-Wattribute-alias=n,-Wno-attribute-aliasโ warns about declarations using the"alias"and similar attributes whose target doesn't match the type of the alias ๐-Wattribute-alias=1โ this is the default level, and it diagnoses type incompatibilities between the alias declaration and its target ๐ These are usually signs of bugs, so don't ignore them, bestie ๐ค-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 ๐ These mismatches can lead to incorrect code generation ๐ Sometimes they're harmless and you can fix them just by adding the missing attribute to the target. For comparison, check out-Wmissing-attributes, which covers the opposite situation, where the alias is less restrictive than the target ๐ฆ
Attributes considered here 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, and that's the default ๐
You can turn these warnings off with either -Wno-attribute-alias or -Wattribute-alias=0 ๐ซถ
-Wbidi-chars=[none|unpaired|any|ucn]โ warns about possibly misleading UTF-8 bidirectional control characters in comments, string literals, character constants, and identifiers ๐ These can flip the writing direction from left-to-right to right-to-left (and back), which causes confusion between logical order and visual order ๐ต This can be seriously dangerous, because it might look like a chunk of code is commented out when it actually isn't ๐
GCC has three warning levels. The default is -Wbidi-chars=unpaired, which warns about improperly terminated bidi contexts ๐ธ -Wbidi-chars=none turns the warning off ๐
โโ๏ธ -Wbidi-chars=any warns about any use of bidirectional control characters ๐ฅ
By default, this warning skips UCNs ๐ If you want that checking too, use -Wbidi-chars=unpaired,ucn or -Wbidi-chars=any,ucn. Using -Wbidi-chars=ucn is valid and works the same as -Wbidi-chars=unpaired,ucn, as long as no earlier -Wbidi-chars=any was specified ๐ง
-Wbool-compareโ warns when a boolean expression gets compared with an integer value that's different from"true"/"false"๐ For example, this comparison is always false, so it's a mess:
int n = 5;
...
if ((n > 1) == 2) { ... }
This warning is enabled by -Wall โจ
-Wbool-operationโ warns about sus operations on expressions of boolean type ๐คจ For instance, bitwise negation of a boolean is very likely a bug ๐ In C, this also warns about incrementing or decrementing a boolean, which almost never makes sense ๐ โโ๏ธ (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++17 and deprecated otherwise.)
This warning is enabled by -Wall ๐
-Wduplicated-branchesโ warns when an if-else has identical branches ๐ฏ It catches stuff like this:
if (p != NULL)
return 0;
else
return 0;
It won't warn when both branches contain just a null statement ๐ซถ It 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 about this one:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ warns when__builtin_frame_addressor__builtin_return_addressgets called with an argument greater than 0 ๐ฑ These calls might return indeterminate values or crash the program ๐ This warning is included in-Wallโจ-Wno-discarded-qualifiers(C and Objective-C only) โ stops the warning about type qualifiers on pointers being discarded ๐ธ Normally, the compiler warns if a"const char *"variable gets passed to a function that takes a"char *"parameter. This option shuts that down ๐-Wno-discarded-array-qualifiers(C and Objective-C only) โ same deal, but for type qualifiers on arrays that are pointer targets ๐ Normally, the compiler warns if a"const int (*)[]"variable gets passed to a function taking a"int (*)[]"parameter. This option silences that warning ๐ง-Wno-incompatible-pointer-types(C and Objective-C only) โ skips the warning when there's a conversion between pointers with incompatible types ๐ฆ This is for 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 one is about implicit conversions. For explicit ones, you can use-Wno-int-to-pointer-castand-Wno-pointer-to-int-cast๐ซถ-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
In the example below, the first two stores in function bad get flagged, because those array elements overlap the members b and c ๐ The third store is caught by -Warray-bounds because it's past the end of the enclosing object ๐
struct X { int a[0]; int b, c; };
struct X x;
void bad (void)
{
x.a[0] = 0; // -Wzero-length-bounds
x.a[1] = 1; // -Wzero-length-bounds
x.a[2] = 2; // -Warray-bounds
}
-Wzero-length-bounds is enabled by -Warray-bounds โจ
-Wno-div-by-zeroโ no warnings about compile-time integer division by zero ๐ โโ๏ธ Floating-point division by zero doesn't get warned about either, since it can be a legit way to get infinities and NaNs ๐ธ-Wsystem-headersโ prints warning messages for constructs found in system header files ๐ฅ Warnings from system headers are normally hidden, on the assumption that they usually aren't real problems and would just make the compiler output harder to read ๐ค This flag tells GCC to show warnings from system headers as if they came from user code ๐ Heads up, though: using-Wallwith this option still won't warn about unknown pragmas in system headers. For that,-Wunknown-pragmasmust also be used ๐ซถ-Wtautological-compareโ warns if a self-comparison always evaluates to true or false ๐ง This catches mistakes like:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always evaluate to true or false, like this one:
if ((a & 16) == 10) { ... }
That will always be false, so it's a no-go ๐ This warning is enabled by -Wall ๐
-Wtrampolinesโ okay bestie, this one is a heads-up about trampolines ๐คธ that get generated for pointers to nested functions. A trampoline is a small piece of data or code created at run time on the stack when the address of a nested function is taken, and it's used to call that nested function indirectly. For some targets it's only data, so no special treatment is needed โจ. For most targets, though, it's code, which means the stack has to be made executable for the program to work properly ๐.
Heads up, bestie: on most targets the stack has to be made executable, so don't sleep on this warning ๐
-Wfloat-equalโ warns if floating-point values are used in equality comparisons ๐งฎ
The vibe here is that sometimes it's convenient for you as the programmer to treat floating-point values as approximations to infinitely precise real numbers. If that's your move, you need to figure out (by analyzing the code, or some other way) the maximum or likely maximum error the computation introduces, and allow for it when doing comparisons (and when producing output, but that's a different problem ๐ ).
In particular, instead of testing for equality, you should check whether the two values have ranges that overlap. That's done with the relational operators, so equality comparisons are probably mistaken ๐
-Wtraditional(C and Objective-C only) โ warns about certain constructs that behave differently in traditional C and ISO C. It also warns about ISO C constructs that have no traditional C equivalent, and/or problematic constructs you should avoid ๐ง- Macro parameters that show up inside string literals in the macro body. In traditional C, macro replacement happens inside string literals, but in ISO C it doesn't ๐
- In traditional C, some preprocessor directives didn't exist. Traditional preprocessors only treated a line as a directive if the
#appeared in column 1. So-Wtraditionalwarns about directives that traditional C understands but ignores because the#isn't the first character on the line. It also suggests you hide directives like"#pragma"that 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.) Note, these suffixes appear in macros defined in the system headers of most modern systems, e.g. the_MIN/_MAXmacros in"<limits.h>". Use of these macros in user code might normally lead to spurious warnings, however GCC's integrated preprocessor has enough context to avoid warning in these cases. - A function declared external in one block and then used after the end of the block.
- A
"switch"statement has an operand of type"long". - A non-
"static"function declaration follows a"static"one. This construct is not accepted by some traditional C compilers. - 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. I.e. hexadecimal or octal values, which typically represent bit patterns, are not warned about.
- Usage of ISO string concatenation is detected.
- Initialization of automatic aggregates.
- Identifier conflicts with labels. Traditional C lacks a separate namespace for labels.
- Initialization of unions. If the initializer is zero, the warning is omitted. This is done under the assumption that the zero initializer in user code appears conditioned on e.g.
"__STDC__"to avoid missing initializer warnings and relies on default initialization to zero in the traditional C case. - Conversions by prototypes between fixed/floating-point values and vice versa. The absence of these prototypes when compiling with traditional C causes serious problems. This is a subset of the possible conversion warnings; for the full set use
-Wtraditional-conversion. - Use of ISO C style function definitions. This warning intentionally is not issued for prototype declarations or variadic functions, because these ISO C features appear in your code when using libiberty's traditional C compatibility macros,
"PARAMS"and"VPARAMS". This warning is also bypassed for nested functions, because that feature is already a GCC extension and thus not 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 and vice versa, and conversions changing the width or signedness of a fixed-point argument, except when it's the same as the default promotion.-Wdeclaration-after-statement(C and Objective-C only) โ warns when a declaration is found after a statement in a block ๐. This construct is known from C++, was introduced with ISO C99, and is allowed by default in GCC. It is 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 is shadowed ๐. Note that 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. This means that-Wno-shadow=localand-Wno-shadow=compatible-localare ignored when-Wshadowis used. Same as-Wshadow=global.-Wno-shadow-ivar(Objective-C only) โ no warnings when a local variable shadows an instance variable in an Objective-C method ๐-Wshadow=globalโ warns for any shadowing. Same as-Wshadow.-Wshadow=localโ warns when a local variable shadows another local variable or parameter.-Wshadow=compatible-localโ warns when a local variable shadows another local variable or parameter whose type is compatible with that of the shadowing variable โจ. In C++, type compatibility here means the type of the shadowing variable can be converted to that of the shadowed variable. This flag (in addition to-Wshadow=local) exists because when a local variable shadows another one of incompatible type, it's most likely intentional, not a bug or typo, as shown in the following example:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two variable "i" in the example above have incompatible types, enabling only -Wshadow=compatible-local does not emit a warning. Because their types are incompatible, if a programmer accidentally uses one in place of the other, type checking is expected to catch that and emit an error or warning. Using this flag instead of -Wshadow=local can possibly reduce the number of warnings triggered by intentional shadowing. Note that this also means 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 exceeds byte-size ๐.-Wlarger-than=PTRDIFF_MAXis enabled by default. Warnings controlled by this option can be disabled either by specifying a byte-size ofSIZE_MAXor more, or by-Wno-larger-than.
Also warns for calls to bounded functions such as "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. The option is equivalent to-Wlarger-than=SIZE_MAXor larger ๐ซ-Wframe-larger-than=byte-size โ warns if the size of a function frame exceeds byte-size ๐ผ๏ธ. The computation done to determine the stack frame size is approximate and not conservative, so the actual requirements may be somewhat greater than byte-size even if you don't get a warning. Also, any space allocated via"alloca", variable-length arrays, or related constructs is not included by the compiler when deciding whether to issue a warning.-Wframe-larger-than=PTRDIFF_MAXis enabled by default. Warnings controlled by this option can be disabled either by specifying a byte-size ofSIZE_MAXor more, or by-Wno-frame-larger-than.-Wno-frame-larger-thanโ disables-Wframe-larger-than=warnings. The option is equivalent to-Wframe-larger-than=SIZE_MAXor larger ๐ซ-Wfree-nonheap-objectโ warns when you try to deallocate an object that was either not allocated on the heap, or that was reached through a pointer not returned from a prior call to the matching allocation function ๐จ. For example, because the call to"stpcpy"returns a pointer to the terminating nul character and not to the beginning of the object, the call to"free"below gets diagnosed:
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wfree-nonheap-object is included in -Wall.
-Wstack-usage=byte-size โ warns if the stack usage of a function might exceed byte-size ๐ฅ. The computation done to determine stack usage is conservative. Any space allocated via"alloca", variable-length arrays, or related constructs is included by the compiler when deciding whether to issue a warning.
The message matches the output of -fstack-usage.
If the stack usage is fully static but exceeds the specified amount, it looks like this:
warning: stack usage is 1120 bytes
If the stack usage is (partly) dynamic but bounded, it looks like this:
warning: stack usage might be 1648 bytes
- If the stack usage is (partly) dynamic and not bounded, it's:
warning: stack usage might be unbounded
okay so -Wstack-usage=PTRDIFF_MAX is on by default, bestie ๐
You can silence these warnings by setting a byte-size of SIZE_MAX or more, or just use -Wno-stack-usage ๐
-Wno-stack-usageโ No more-Wstack-usage=warnings ๐ It's the same as-Wstack-usage=SIZE_MAXor larger, so GCC gets to chill.-Wunsafe-loop-optimizationsโ Warns if a loop can't be optimized ๐ฅ That happens when the compiler can't assume anything about the bounds of the loop indices. Add-funsafe-loop-optimizationsand it'll warn you whenever the compiler makes those assumptions instead ๐-Wno-pedantic-ms-format(MinGW targets only) โ When you use it with-Wformatand-pedantic(without GNU extensions), it turns off the warnings about non-ISOprintfandscanfwidth specifiersI32,I64, andIon Windows targets. Those depend on the MS runtime, so this one's a lifesaver ๐-Wpointer-arithโ Warns about anything that depends on the "size of" a function type or ofvoid๐ฆ GNU C gives those types a size of 1, which is super handy for math withvoid *pointers and pointers to functions. In C++, it also warns when an arithmetic operation involvesNULL. This one's also turned on by-Wpedanticโจ-Wno-pointer-compareโ Don't warn when a pointer gets compared with a zero character constant. That usually means the pointer was supposed to be dereferenced ๐ Check out this example:
const char *p = foo ();
if (p == '\0')
return 42;
The code above is invalid in C++11, so be careful ๐ญ
This warning is enabled by default.
-Wtsanโ Warns about unsupported features in ThreadSanitizer ๐ง ThreadSanitizer doesn't supportstd::atomic_thread_fence, and it can report false positives.
This warning is enabled by default.
-Wtype-limitsโ Warns if a comparison is always true or always false because of the limited range of the data type ๐ Constant expressions don't get flagged, though. For example, it'll warn if an unsigned variable gets compared against zero with<or>=. This one's also turned on by-Wextra๐-Wabsolute-value(C and Objective-C only) โ Warns when you call a standard absolute-value function and there's a better one available ๐ซถ For example,abs(3.14)triggers it, because a double argument should go tofabs. It also warns when the argument to one of those calls has an unsigned type. You can shut it up with an explicit type cast, and it's also enabled by-Wextra๐-Wcomment,-Wcommentsโ Warns whenever a comment-start sequence/*shows up inside a/*comment, or whenever a backslash-newline shows up in a//comment ๐ This warning is enabled by-Wall.-Wtrigraphsโ Warns about trigraphs that might change what your program means โจ Trigraphs inside comments don't get flagged, except the ones that would form escaped newlines. This option is implied by-Wall. If you don't pass-Wall, it's still on unless trigraphs are enabled. Want trigraph conversion without the warnings but still all the other-Wallwarnings? Use-trigraphs -Wall -Wno-trigraphs๐-Wundefโ Warns if an undefined identifier gets evaluated in an#ifdirective ๐ธ Those identifiers get replaced with zero.-Wexpansion-to-definedโ Warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective ๐ That kind of usage isn't portable. This warning is also enabled by-Wpedanticand-Wextra.-Wunused-macrosโ Warns about macros defined in the main file that are never used ๐ A macro counts as used if it gets expanded or tested for existence at least once. The preprocessor also warns if the macro hasn't been used by the time it gets redefined or undefined.
Built-in macros, macros defined on the command line, and macros defined in include files don't get warned about ๐
Note: If a macro is used, but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐ญ To dodge the warning, you could improve the scope of the macro's definition, for example by moving it into the first skipped block. Or you could give it a dummy use, 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 sometimes happens in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should be in comments. This warning is on by default.
-Wbad-function-cast(C and Objective-C only) โ Warns when a function call gets cast to a non-matching type ๐ฆ For example, it warns if a call to a function that returns an integer type gets cast to a pointer type.-Wc90-c99-compat(C and Objective-C only) โ Warns about features that exist in ISO C99 but not in ISO C90 ๐ Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. This option doesn't depend on the standards mode. Warnings are turned off in the expression that follows__extension__.-Wc99-c11-compat(C and Objective-C only) โ Warns about features that exist in ISO C11 but not in ISO C99 โจ That includes anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. This option doesn't depend on the standards mode either. Warnings are turned off in the expression that follows__extension__.-Wc11-c2x-compat(C and Objective-C only) โ Warns about features that exist in ISO C2X but not in ISO C11 ๐ง That includes leaving out the string in_Static_assert, using[[]]attribute syntax, using decimal floating-point types, and so on. Once again, this option doesn't depend on the standards mode, and warnings are turned off in the expression that follows__extension__.-Wc++-compat(C and Objective-C only) โ Warns about ISO C constructs that sit outside the common subset of ISO C and ISO C++ ๐ซถ For example, it'll flag implicit conversion fromvoid *to a pointer to a non-voidtype.-Wc++11-compat(C++ and Objective-C++ only) โ Warns about C++ constructs whose meaning changed between ISO C++ 1998 and ISO C++ 2011 ๐ For example, identifiers that were fine in ISO C++ 1998 but are keywords in ISO C++ 2011. This warning turns on-Wnarrowingand is enabled by-Wall.-Wc++14-compat(C++ and Objective-C++ only) โ Warns about C++ constructs whose meaning changed between ISO C++ 2011 and ISO C++ 2014 ๐ธ This warning is enabled by-Wall.-Wc++17-compat(C++ and Objective-C++ only) โ Warns about C++ constructs whose meaning changed between ISO C++ 2014 and ISO C++ 2017 ๐ This warning is enabled by-Wall.-Wc++20-compat(C++ and Objective-C++ only) โ Warns about C++ constructs whose meaning changed between ISO C++ 2017 and ISO C++ 2020 ๐ฅ This warning is enabled by-Wall.-Wno-c++11-extensions(C++ and Objective-C++ only) โ Don't warn about C++11 constructs when you're compiling with an older C++ standard ๐ Even without this option, some C++11 constructs only get diagnosed if you use-Wpedantic.-Wno-c++14-extensions(C++ and Objective-C++ only) โ Don't warn about C++14 constructs when you're compiling with an older C++ standard ๐ Even without this option, some C++14 constructs only get diagnosed if you use-Wpedantic.-Wno-c++17-extensions(C++ and Objective-C++ only) โ Don't warn about C++17 constructs when you're compiling with an older C++ standard ๐ Even without this option, some C++17 constructs only get diagnosed if you use-Wpedantic.-Wno-c++20-extensions(C++ and Objective-C++ only) โ Don't warn about C++20 constructs when you're compiling with an older C++ standard ๐ฆ Even without this option, some C++20 constructs only get diagnosed if you use-Wpedantic.-Wno-c++23-extensions(C++ and Objective-C++ only) โ Don't warn about C++23 constructs when you're compiling with an older C++ standard โจ Even without this option, some C++23 constructs only get diagnosed if you use-Wpedantic.
-Wcast-qualโ Warns whenever a pointer gets cast in a way that removes a type qualifier from the target type ๐ For example, it warns if aconst char *gets cast to an ordinarychar *.
It also warns when a cast introduces a type qualifier in an unsafe way. Casting char ** to const char ** is unsafe, as in this example:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ Warns whenever a pointer 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โ Same idea as-Wcast-align, but stricter ๐ It warns whenever a pointer gets cast so the required alignment of the target goes up, no matter what the target machine is. For example, it warns if achar *gets cast to anint *regardless of the target machine.-Wcast-function-typeโ Warns when a function pointer gets cast to an incompatible function pointer ๐ฅ When it comes to function types with a variable argument list, only the types of the initial arguments that are actually provided get considered. Any parameter of pointer-type matches any other pointer-type. Harmless differences in integral types are ignored, likeintvs.longon ILP32 targets, and type qualifiers are ignored too. The function typevoid (*) (void)is special and matches everything, so you can use it to suppress this warning ๐ For pointer to member types, this warning fires whenever the cast changes the pointer to member type. This warning is enabled by-Wextra๐ธ-Wwrite-stringsโ okay bestie, when you're compiling C, this gives string constants the typeconst char[length], so copying one into a non-constchar *pointer gets you a warning ๐ซถ These are super helpful for catching code that might try to write into a string constant at compile time, but only if you've been really careful withconstin your declarations and prototypes. Otherwise they're just a nuisance ๐ which is exactly why-Walldoesn't ask for them ๐
When you're compiling C++, it warns about the deprecated conversion from string literals to char *, and this one is switched on by default for C++ programs โจ
-Wclobberedโ warns about variables thatlongjmporvforkmight change behind your back ๐ It's also turned on by-Wextra.-Wconversionโ warns about implicit conversions that might mess with a value ๐ฅ That includes real โ integer swaps, likeabs (x)whenxisdouble; signed โ unsigned swaps, likeunsigned ui = -1; and squishing into smaller types, likesqrtf (M_PI). It won't nag you about explicit casts likeabs ((int) x)orui = (unsigned) -1, or about conversions that don't actually change the value, likeabs (2.0). If the signed/unsigned stuff is too much, you can silence it with-Wno-sign-conversion๐
For C++, it also warns about confusing overload resolution for user-defined conversions, plus conversions that never use a type conversion operator: conversions to void, to the same type, to a base class, or to a reference to any of those. In C++, the signed/unsigned warnings are off by default unless you explicitly turn on -Wsign-conversion ๐ธ
Warnings about conversions from arithmetic on a small type back to that same type only show up with -Warith-conversion ๐ฆ
-Wdangling-elseโ warns about code where it's unclear whichifanelsebelongs to ๐ Here's a sneaky example:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C and C++, every else attaches to the innermost possible if, which here is if (b). That's often not what you meant, especially when your indentation says otherwise ๐ญ When this confusion is possible, GCC warns you if this flag is on. To kill the warning, wrap the innermost if in explicit braces so the else can't possibly belong to the outer one โจ Like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses ๐
-Wdangling-pointer,-Wdangling-pointer=nโ okay this one is lowkey iconic ๐ It warns about using pointers (or C++ references) to objects with automatic storage duration after their lifetime has already ended. That covers locals declared in nested blocks, compound literals, and other unnamed temporary objects. It also warns about stashing the address of those objects in escaped pointers ๐ซฃ It's on at every optimization level, but the results might look different with optimization than without.-Wdangling-pointer=1โ at level 1, you only get warnings for unconditional uses of dangling pointers ๐ For example:
int f (int c1, int c2, x)
{
char *p = strchr ((char[]){ c1, c2 }, c3);
return p ? *p : 'x'; // warning: dangling pointer to a compound literal
}
In the next function, storing the address of the local variable x into the escaped pointer *p also triggers the warning ๐
void g (int **p)
{
int x = 7;
*p = &x; // warning: storing the address of a local variable in *p
}
-Wdangling-pointer=2โ level 2 does everything level 1 does, plus conditional uses of dangling pointers ๐ง In this function, the arrayais out of scope by the time the pointersgets used, so this level catches it:
void f (char *s)
{
if (!s)
{
char a[12] = "tmpname";
s = a;
}
strcat (s, ".tmp"); // warning: dangling pointer to a may be used
...
}
-Wdangling-pointer=2is already included in-Wall, so you get it for free ๐
-Wdate-timeโ warns whenever the__TIME__,__DATE__or__TIMESTAMP__macros show up, since they can stop your builds from being bit-wise identical and reproducible โฐ-Wempty-bodyโ warns if there's an empty body in anif,elseordo whilestatement ๐ซฅ It's also enabled by-Wextra.-Wno-endif-labelsโ don't warn about stray tokens after#elseand#endif๐-Wenum-compareโ warns about comparing values from different enumerated types ๐ In C++, enum mismatches in conditional expressions are also flagged, and this one is on by default there. In C, it's turned on by-Wall.-Wenum-conversionโ warns when a value of one enumerated type gets implicitly converted into a different enumerated type ๐ In C, it's 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 that comes after the variable was already initialized ๐ It only cares about variables that get initialized right when they're declared. This warning is only supported for C and Objective-C, because in C++ this kind of jump is already an error anyway ๐ โโ๏ธ
-Wjump-misses-init is included in -Wc++-compat, and you can turn it off with the -Wno-jump-misses-init option ๐ซถ
-Wsign-compareโ warns when comparing signed and unsigned values could give you a wrong answer, because the signed value gets converted to unsigned first ๐ฌ In C++, it's also enabled by-Wall. In C, it's enabled by-Wextra.-Wsign-conversionโ warns about implicit conversions that might change the sign of an integer value, like assigning a signed integer expression to an unsigned integer variable ๐ An explicit cast will shut it up. In C, this option is also turned on by-Wconversion.-Wfloat-conversionโ warns about implicit conversions that lose precision in a real value โ๏ธ That includes real-to-integer conversions, and conversions from a higher-precision real to a lower-precision one. This option is also turned on by-Wconversion.-Wno-scalar-storage-orderโ don't warn about suspicious constructs involving reverse scalar storage order ๐คทโโ๏ธ-Wsizeof-array-divโ warns about dividing twosizeofoperators when the first one is applied to an array and the divisor isn't the size of an array element ๐งฎ In that case, the math won't give you the number of elements in the array, which is probably not what you wanted. This warning 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 trick for computing an array's size, but it won't work 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 things likememset (ptr, 0, sizeof (ptr));whenptris a pointer and not an array, and it even suggests a possible fix. It also triggers for stuff likememcpy (&foo, ptr, sizeof (&foo));.
-Wsizeof-pointer-memaccess also warns about calls to bounded string copy functions like strncat or strncpy that use the sizeof of the source array as the bound. In this function, the strncat call uses the size of the source string as its bound, which is almost certainly a mistake, so it gets flagged:
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall ๐ฅ
-Wno-sizeof-array-argumentโ don't warn whensizeofis applied to a parameter that's declared as an array in a function definition ๐ซถ This warning is enabled by default for C and C++ programs.-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function ๐ง It fires when the first argument references an array, and the third argument is a number equal to the number of elements, but not equal to the size of the array in memory. That usually means you forgot to multiply by the element size. This warning is enabled by-Wall.-Wmemset-transposed-argsโ warns about suspiciousmemsetcalls where the second argument isn't zero and the third argument is zero ๐ For example,memset (buf, sizeof buf, 0)gets flagged, becausememset (buf, 0, sizeof buf)was what you meant. The diagnostic only shows up if the third argument is a literal zero. If it's an expression that folds down to zero, or a cast of zero to some type, the arguments are much less likely to have been swapped by mistake, so no warning is emitted. This warning is enabled by-Wall๐ธ-Waddressโ warns about suspicious uses of address expressions ๐ These include comparing the address of a function or a declared object against the null pointer constant, such as in
Okay so the rest of -Waddress is giving sneaky ๐ซฃ Checking whether a function is "there" in a condition gets flagged, bestie:
void f (void);
void g (void)
{
if (!func) // warning: expression evaluates to false
abort ();
}
Comparing a pointer to a string literal gets flagged too ๐
void f (const char *x)
{
if (x == "abc") // warning: expression evaluates to false
puts ("equal");
}
And testing the result of pointer addition or subtraction against null for equality is flagged as well:
void f (const int *p, int i)
{
return p + i == NULL;
}
Honestly these almost always mean a programmer error ๐ The address of most functions and objects is basically always true (except weak symbols ๐ฆ), so putting one in a condition might mean you forgot parentheses in a function call, or you're missing a dereference in an array expression.
The object-pointer part of the warning can be silenced by casting the pointer operand to an integer type like inptr_t or uinptr_t. String literal comparisons give unspecified behavior and aren't portable, and they're a hint you meant to call strcmp. The warning also gets suppressed if the sus expression came from macro expansion. -Waddress is enabled by -Wall โจ
-Wno-address-of-packed-memberโ don't warn when you take the address of a packed member of a struct or union, since that usually gives you an unaligned pointer value ๐ This one is on by default.-Wlogical-opโ warns about suspicious logical operators in expressions, especially when a bitwise operator is probably what you wanted. It also warns when both operands of a logical operator are the same:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns when a logical not is on the left side of a comparison ๐ง It won't warn if the right operand is a boolean expression. It's there to catch stuff like this:
int a;
...
if (!a > 1) { ... }
You can shut it up by wrapping the LHS in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall.
-Waggregate-returnโ warns if any functions that return structs or unions are defined or called. (In languages where you can return an array, this also gets a warning ๐ )-Wno-aggressive-loop-optimizationsโ warns if, in a loop with a constant number of iterations, the compiler detects undefined behavior in some statement during one or more of the iterations.-Wno-attributesโ don't warn if an unexpected__attribute__shows up, like unrecognized attributes or function attributes slapped onto variables. This doesn't stop errors for incorrect use of supported attributes.
Also, using -Wno-attributes= lets you suppress warnings about unknown scoped attributes (in C++11 and C2X) โจ For example, -Wno-attributes=vendor::attr disables the warning for this declaration:
[[vendor::attr]] void f();
You can disable warnings about all attributes in a namespace with -Wno-attributes=vendor::, which stops warnings for both of these:
[[vendor::safe]] void f();
[[vendor::unsafe]] void f2();
Note that -Wno-attributes= does not imply -Wno-attributes.
-Wno-builtin-declaration-mismatchโ warns if a built-in function is declared with an incompatible signature or as a non-function, or when a built-in function declared with a type that has no prototype is called with arguments whose promoted types don't match what it expects ๐ฅ With-Wextra, it also warns when a built-in function that takes arguments is declared without a prototype. The-Wbuiltin-declaration-mismatchwarning is enabled by default. To avoid it, include the right header to bring the built-in prototypes into scope.
For example, the memset call below gets diagnosed because the function expects a size_t argument but 32 is an int. With -Wextra, the declaration itself gets diagnosed 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 suppresses warnings for redefinitions of__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__๐ฐ๏ธ-Wstrict-prototypes(C and Objective-C only) โ warns if a function is declared or defined without specifying its argument types. (An old-style function definition is allowed without a warning if it's preceded by a declaration that specifies the argument types.)-Wold-style-declaration(C and Objective-C only) โ warns about obsolescent usages in a declaration, according to the C Standard ๐ For example, it warns if storage-class specifiers likestaticaren't the first things in a declaration. This warning is also enabled by-Wextra.-Wold-style-definition(C and Objective-C only) โ warns if an old-style function definition is used, even if there's a previous prototype. A definition using()is not considered old-style in C2X mode, because 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:
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. It warns even if the definition itself provides a prototype ๐ Use this to catch global functions that don't have a matching prototype in a header file. This option isn't valid for C++, because all function declarations there provide prototypes, and a non-matching declaration declares an overload rather than conflicting with an earlier one. For missing declarations in C++, use-Wmissing-declarations.-Wmissing-declarationsโ warns if a global function is defined without a previous declaration, even if the definition itself provides a prototype. Use this to find global functions that aren't declared in header files. In C, no warnings are issued for functions with previous non-prototype declarations, so use-Wmissing-prototypesfor those. In C++, no warnings are issued for function templates, inline functions, or functions in anonymous namespaces ๐ธ-Wmissing-field-initializersโ warns if a struct's initializer is missing some fields. This code causes the warning, becausex.his implicitly zero:
struct s { int f, g, h; };
struct s x = { 3, 4 };
This option doesn't warn about designated initializers, so this change won't trigger it:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, this option doesn't warn about the universal zero initializer { 0 }:
struct s { int f, g, h; };
struct s x = { 0 };
Likewise, in C++ this option doesn't warn about the empty { } initializer:
struct s { int f, g, h; };
s x = { };
This warning is included in -Wextra. To get the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers.
-Wno-missing-requiresโ by default, the compiler warns about a concept-id showing up as a C++20 simple-requirement ๐ง
bool satisfied = requires { C<T> };
Here satisfied will be true if C<T> is a valid expression, which it is for all T. Presumably the user meant this:
bool satisfied = requires { requires C<T> };
so satisfied is only true if concept C is satisfied for type T.
This warning can be disabled with -Wno-missing-requires.
-Wno-missing-template-keywordโ the member access tokens.,->and::must be followed by thetemplatekeyword if the parent object is dependent and the member being named is a template ๐
template <class X>
void DoStuff (X x)
{
x.template DoSomeOtherStuff<X>(); // Good.
x.DoMoreStuff<X>(); // Warning, x is dependent.
}
In rare cases you can get false positives. To silence them, wrap the expression in parentheses. For example, the following is treated as a template, even where m and N are integers:
void NotATemplate (my_class t)
{
int N = 5;
bool test = t.m < N > (0); // Treated as a template.
test = (t.m < N) > (0); // Same meaning, but not treated as a template.
}
This warning can be disabled with -Wno-missing-template-keyword.
-Wno-multicharโ don't warn if a multicharacter constant ('FOOF') is used. These usually mean a typo in your code, since they have implementation-defined values and shouldn't be used in portable code ๐ซ-Wnormalized=[none|id|nfc|nfkc]โ in ISO C and ISO C++, two identifiers are different if they're different sequences of characters. But when non-ASCII characters are involved, you can get two different sequences that look exactly the same ๐ต To avoid that confusion, the ISO 10646 standard defines normalization rules that turn look-alike sequences into the same sequence. GCC can warn you if you use identifiers that haven't been normalized, and this option controls that warning.
Okay so bestie, GCC has FOUR levels of normalization warnings ๐
The default is -Wnormalized=nfc, which yells at you about any identifier that isn't in the ISO 10646 "C" normalized form, NFC ๐ซถ NFC is the recommended vibe for most uses, and -Wnormalized means the exact same thing.
Unfortunately โจ some characters that ISO C and ISO C++ let you use in identifiers stop being allowed once they get turned into NFC ๐ญ So there's literally no way to write portable ISO C or C++ and keep every identifier in NFC. -Wnormalized=id silences the warning for just those characters ๐ฆ The standards folks are hoping future versions fix this, which is why it isn't the default.
You can switch the warning off for every character with -Wnormalized=none or -Wno-normalized. Only do this if you're using some other normalization scheme (like "D") ๐ Otherwise you can super easily create bugs that are literally impossible to see.
Some ISO 10646 characters mean totally different things but look identical in some fonts or display setups, especially once formatting gets applied ๐ Like "\u207F", which is "SUPERSCRIPT LATIN SMALL LETTER N", and it looks exactly like a regular n that got bumped into a superscript. ISO 10646 also defines the NFKC normalization scheme to turn all of these into one standard form, and GCC will warn if your code isn't NFKC when you use -Wnormalized=nfkc ๐ฅ This is kind of like warning about every identifier with the letter O in it because it might get mixed up with the digit 0 ๐ So it's not the default, but it can be a useful local coding convention if your programming environment can't be fixed to display these characters differently.
-Wno-attribute-warningโ ๏ธ โ Don't warn about using functions declared with the "warning" attribute. This warning is on by default. You can use-Wno-attribute-warningto turn the warning off, or-Wno-error=attribute-warningto turn off the error when you're compiling with the-Werrorflag ๐-Wno-deprecated๐ โโ๏ธ โ Don't warn about using 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๐ง โ Warn about One Definition Rule violations during link-time optimization. This is enabled by default. ngl the name starts with-Wno-but this one actually WARNS, so read it carefully bestie ๐-Wopenacc-parallelism๐ง โ Warn about potentially suboptimal choices related to OpenACC parallelism.-Wopenmp-simdโจ โ Warn if the vectorizer cost model overrides the OpenMP simd directive that the user set. You can use-fsimd-cost-model=unlimitedto relax the cost model.-Woverride-init(C and Objective-C only) ๐ โ Warn if an initialized field without side effects gets overridden when you're using designated initializers. This warning is included in-Wextra. If you want 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 you're using designated initializers. This warning is enabled by default.-Wpacked๐ โ Warn if a structure gets the packed attribute but the packed attribute has no effect on the layout or size of the structure. Structures like that may end up misaligned for basically no benefit. For example, in this code the variablef.xinsidestruct baris misaligned, even thoughstruct bardoesn't have the packed attribute itself:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wnopacked-bitfield-compat๐ฆ โ The 4.1, 4.2 and 4.3 series of GCC ignored the "packed" attribute on bit-fields of type "char". That got fixed in GCC 4.4, but the change can lead to differences in structure layout. GCC tells you when the offset of such a field has changed in GCC 4.4. For example, there's no longer a 4-bit padding between field "a" and "b" in this structure:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default. Use -Wno-packed-bitfield-compat to disable it.
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) ๐ โ Warn if a structure field with explicitly specified alignment, inside a packed struct or union, is misaligned. For example, a warning gets issued on "struct S" that says something like "warning: alignment 1 of 'struct S' is less than 8" in this code:
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall.
-Wpadded๐๏ธ โ Warn if padding gets included in a structure, either to align one of its elements or to align the whole structure. Sometimes when this happens you can rearrange the fields to reduce the padding and make the structure smaller ๐ง-Wredundant-decls๐ฏ โ Warn if anything gets declared more than once in the same scope, even when multiple declarations are valid and change nothing.-Wrestrict๐ซ โ Warn when an object referenced by a "restrict"-qualified parameter (or, in C++, a "__restrict"-qualified parameter) is aliased by another argument, or when copies between those objects overlap. For example, thestrcpycall below tries to truncate the string by replacing its first characters with the last four. But because the call writes the terminating NUL intoa[4], the copies overlap and the call gets flagged ๐
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
-Wrestrict catches some simple overlaps even without optimization, but it works best at -O2 and above. It's included in -Wall.
-Wnested-externs(C and Objective-C only) ๐จ โ Warn if an "extern" declaration shows up inside a function.-Winline๐ โ Warn if a function declared as inline can't be inlined. Even with this option on, the compiler won't warn about failures to inline functions declared in system headers.
The compiler uses a bunch of heuristics to decide whether to inline a function ๐งฎ For example, it looks at how big the function being inlined is and how much inlining has already been done in the current function. So seemingly tiny changes in your source can make the -Winline warnings show up or disappear, lol ๐
-Winterference-size๐ โ Warn about using C++17std::hardware_destructive_interference_sizewithout specifying its value with--param destructive-interference-size. It also warns about questionable values for that option.
This one is for controlling class layout so you don't get false sharing in concurrent code โจ Here's the vibe:
struct independent_fields {
alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
};
The idea is that one and two end up far enough apart that stores to one won't force accesses to two to reload the cache line ๐ง
By default, --param destructive-interference-size and --param constructive-interference-size are set based on the current -mtune option. That's usually the L1 cache line size for the target CPU, and sometimes it's a range if you're tuning for a generic target ๐ซ So every translation unit that depends on ABI compatibility for these variables has to be compiled with the same -mtune (or -mcpu).
If ABI stability matters, like if the use is in a header for a library, you should probably not use the hardware interference size variables at all ๐ฌ Or you can force a specific value with --param. And if you're confident your use of the variable doesn't affect ABI outside a single build of your project, you can turn off the warning with -Wno-interference-size.
-Wint-in-bool-context๐ง โ Warn about suspicious use of integer values where booleans are expected. Think conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). Or left shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. Same goes for all kinds of multiplications, regardless of data type. This warning is enabled by-Wall.-Wno-int-to-pointer-cast๐ โ Suppress warnings about casts to a pointer type from an integer of a different size. In C++, casting to a pointer type of smaller size is an error.Wint-to-pointer-castis enabled by default.-Wno-pointer-to-int-cast(C and Objective-C only) ๐ญ โ Suppress warnings about casts from a pointer to an integer type of a different size.-Winvalid-pch๐ โ Warn if a precompiled header is found in the search path but can't be used.-Wlong-long๐ โ Warn if thelong longtype is used. This is enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. To shush the warning messages, use-Wno-long-long.-Wvariadic-macros๐ โ Warn if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode. This is enabled by either-Wpedanticor-Wtraditional. To inhibit the warning messages, use-Wno-variadic-macros.-Wno-varargs๐ โ Don't warn about questionable usage of the macros used to handle variable arguments, likeva_start. These warnings are enabled by default.-Wvector-operation-performanceโ okay so this one warns you if a vector operation isn't using the architecture's SIMD superpowers ๐. It's mainly for performance tuning, bestie. A vector op can get done three ways: "piecewise" runs the scalar op on every single vector element ๐งฉ, "in parallel" builds the vector op out of scalars of a wider type, which is usually way more performance efficient ๐๏ธ, and "as a single scalar" means the vector fits into one scalar type ๐.-Wvlaโ warns you if a variable-length array shows up anywhere in your code ๐. And-Wno-vlastops the-Wpedanticwarning about variable-length arrays, so you can quiet that one specifically ๐คซ.-Wvla-larger-than=byte-sizeโ if you turn this on, the compiler warns about VLA declarations whose size is either unbounded, or bounded by an argument that lets the array grow past byte-size bytes ๐. It's basically the VLA version of-Walloca-larger-than=byte-size๐ฏ.
Heads up ๐ : GCC might optimize small VLAs with a known value into plain arrays, so this warning might not fire for those.
-Wvla-larger-than=PTRDIFF_MAX is on by default, but it's usually only actually effective when -ftree-vrp is active, which is the default for -O2 and up โจ.
See also -Walloca-larger-than=byte-size ๐ฆ.
-Wno-vla-larger-thanโ turns off the-Wvla-larger-than=warnings ๐ . It's the same as-Wvla-larger-than=SIZE_MAXor anything bigger.-Wvla-parameterโ warns about redeclarations of functions with VLA-type arguments whose kinds or forms don't match ๐คจ, and turns on detection of out-of-bounds accesses to those parameters through warnings like-Warray-bounds๐.
Here's the tea โ: if the first declaration uses the VLA form, the bound in the array is treated as the minimum number of elements callers have to provide, and the maximum number the function will access. Not giving enough, or accessing more than that max, might get flagged ๐ฉ.
The warning triggers for the redeclarations below, because the first one lets an array of any size get passed to f, while the second one says the array argument needs at least n elements. Calling f with the associated VLA bound parameter bigger than the actual VLA bound also triggers a warning ๐.
void f (int n, int[n]);
void f (int, int[]); // warning: argument 2 previously declared as a VLA
void g (int n)
{
if (n > 4)
return;
int a[n];
f (sizeof a, a); // warning: access to a by f may be out of bounds
...
}
-Wvla-parameter is included in -Wall ๐. The -Warray-parameter option handles similar problems with ordinary array arguments ๐งบ.
-Wvolatile-register-varโ warns if a register variable gets declaredvolatile๐ซ . Just know thatvolatiledoesn'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 ๐ฌ. Don't spiral though, bestie, this doesn't generally mean your code is wrong ๐ซถ. It just means GCC's optimizers can't handle the code effectively. Often the code is too big or too complex, and GCC refuses to optimize programs when the optimization would likely take an inordinate amount of time โณ.-Wpointer-sign(C and Objective-C only) โ warns for pointer argument passing or assignment with different signedness ๐ข. It's only supported for C and Objective-C. It's implied by-Walland by-Wpedantic, and you can disable it with-Wno-pointer-sign๐ .-Wstack-protectorโ only active when-fstack-protectoris active ๐ก๏ธ. It warns about functions that aren't protected against stack smashing ๐ฅ.-Woverlength-stringsโ warns about string constants longer than the "minimum maximum" length the C standard specifies ๐. Modern compilers are chill and allow string constants way longer than the standard's minimum, but very portable programs should still avoid super long 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 bumped up to 4095 ๐. C++98 doesn't specify a normative minimum maximum, so overlength strings aren't diagnosed in C++ ๐.
This option is implied by -Wpedantic, and you can disable it with -Wno-overlength-strings ๐ซก.
-Wunsuffixed-float-constants(C and Objective-C only) โ warns for any floating constant that doesn't have a suffix ๐ค. Pair it with-Wsystem-headersand 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, this stops warnings about type mismatches in global declarations from different compilation units ๐ค. It requires-fltoto be enabled, and it's on by default โจ.-Wno-designated-init(C and Objective-C only) โ suppresses warnings when a positional initializer is used to initialize a struct marked with thedesignated_initattribute ๐งธ.
โจ Options That Control Static Analysis โจ
-fanalyzerโ enables static analysis of program flow ๐ฌ. It hunts for "interesting" interprocedural paths through your code and warns about problems it finds along them ๐ต๏ธโโ๏ธ. Fair warning, bestie: this analysis is way more expensive than other GCC warnings ๐ธ.
Turning this on effectively enables the following warnings ๐:
-Wanalyzer-double-fclose -Wanalyzer-double-free
-Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak
-Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak
-Wanalyzer-mismatching-deallocation
-Wanalyzer-possible-null-argument
-Wanalyzer-possible-null-dereference -Wanalyzer-null-argument
-Wanalyzer-null-dereference -Wanalyzer-shift-count-negative
-Wanalyzer-shift-count-overflow -Wanalyzer-stale-setjmp-buffer
-Wanalyzer-tainted-allocation-size -Wanalyzer-tainted-array-index
-Wanalyzer-tainted-divisor -Wanalyzer-tainted-offset
-Wanalyzer-tainted-size -Wanalyzer-unsafe-call-within-signal-handler
-Wanalyzer-use-after-free -Wanalyzer-use-of-uninitialized-value
-Wanalyzer-use-of-pointer-in-stale-stack-frame
-Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal
This option is only available if GCC was configured with analyzer support enabled. ๐จ
-Wanalyzer-too-complexโ if-fanalyzeris on, the analyzer uses a bunch of heuristics to explore control flow and data flow ๐งญ. Sufficiently complicated code can defeat them though ๐ตโ๐ซ. By default, the analysis quietly stops when code is too complicated and it hits an internal limit ๐คซ.-Wanalyzer-too-complexwarns you when that happens ๐จ.-Wno-analyzer-double-fcloseโ this one requires-fanalyzer, which turns it on, and you can switch it off with-Wno-analyzer-double-fclose๐ . It flags paths where aFILE *can havefclosecalled on it more than once ๐.-Wno-analyzer-double-freeโ needs-fanalyzerto be enabled, and you can disable it with-Wno-analyzer-double-free๐ . It flags paths where a pointer can have a deallocator called on it more than once, eitherfree, or a deallocator referenced by attributemalloc๐.-Wno-analyzer-exposure-through-output-fileโ needs-fanalyzer, and you disable it with-Wno-analyzer-exposure-through-output-file๐ . It flags paths where a security-sensitive value gets written to an output file, like dumping a password into a log file ๐.-Wno-analyzer-file-leakโ needs-fanalyzer, and disable it with-Wno-analyzer-file-leak๐ . It flags paths where a<stdio.h>FILE *stream object gets leaked ๐ซ.-Wno-analyzer-free-of-non-heapโ needs-fanalyzer, and disable it with-Wno-analyzer-free-of-non-heap๐ . It flags paths wherefreegets called on a non-heap pointer, like an on-stack buffer or a global ๐๏ธ.-Wno-analyzer-malloc-leakโ needs-fanalyzer, and disable it with-Wno-analyzer-malloc-leak๐ . It flags paths where a pointer allocated through an allocator gets leaked: eithermalloc, or a function marked with attributemalloc๐ง.-Wno-analyzer-mismatching-deallocationโ needs-fanalyzer, and disable it with-Wno-analyzer-mismatching-deallocation๐ . It flags paths where the wrong deallocation function gets called on a pointer, based on which function allocated it ๐. That covers mismatches betweenfree, scalardeleteand vectordelete[], plus anything marked as allocator/deallocator pairs using attributemalloc๐ฏ.-Wno-analyzer-possible-null-argumentโ needs-fanalyzer, and disable it with-Wno-analyzer-possible-null-argument๐ . It flags paths where a possibly-NULL value gets passed to a function argument marked with__attribute__((nonnull))as requiring a non-NULL value ๐ซ.-Wno-analyzer-possible-null-dereferenceโ needs-fanalyzer, and disable it with-Wno-analyzer-possible-null-dereference๐ . It flags paths where a possibly-NULL value gets dereferenced ๐.-Wno-analyzer-null-argumentโ this warning requires-fanalyzer, which enables it, and you can disable it with-Wno-analyzer-null-argument๐ .
Okay so this one is the warning for when a value we know is NULL gets passed into a function argument that's marked __attribute__((nonnull)), which means it needs a real, non-NULL value ๐
โโ๏ธ๐ This diagnostic warns for paths through the code where that happens.
-Wno-analyzer-null-dereferenceโ bestie, this one needs-fanalyzerto be turned on, and you can switch it off with-Wno-analyzer-null-dereference๐ It warns for paths through the code where a value known to be NULL gets dereferenced ๐-Wno-analyzer-shift-count-negativeโ this one also needs-fanalyzerto run, and-Wno-analyzer-shift-count-negativeturns it off ๐ฆ It warns for paths where a shift happens with a negative count. It's the analyzer's version of-Wshift-count-negativefrom the C/C++ front ends, except it looks at interprocedural paths instead of just parsing the syntax tree. The analyzer doesn't prioritize catching these, so false negatives are more likely than with other warnings ๐-Wno-analyzer-shift-count-overflowโ needs-fanalyzer, and you turn it off with-Wno-analyzer-shift-count-overflowโจ It warns for paths where a shift is attempted with a count greater than or equal to the precision of the operand's type. It's the sibling of-Wshift-count-overflowin the C/C++ front ends, but again it's built on analyzing interprocedural paths rather than the syntax tree. Same deal: the analyzer doesn't prioritize these, 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 for paths wherelongjmpis called to rewind to ajmp_buftied to asetjmpcall in a function that has already returned. Whensetjmpis called on ajmp_buf, it records the stack frame. That frame becomes invalid once the function with thesetjmpcall returns, so rewinding to it vialongjmpwould reference a stack frame that doesn't exist anymore. That's likely to lead to a crash, or worse ๐๐ฅ-Wno-analyzer-tainted-allocation-sizeโ this one needs both-fanalyzerand-fanalyzer-checker=taintto be enabled, and-Wno-analyzer-tainted-allocation-sizeturns it off ๐ซถ It warns for paths where a value an attacker could control gets used as the size of an allocation without being sanitized. That means an attacker could inject a huge allocation and maybe cause a denial of service attack ๐จ See CWE-789: Memory Allocation with Excessive Size Value, athttps://cwe.mitre.org/data/definitions/789.html๐-Wno-analyzer-tainted-array-indexโ needs both-fanalyzerand-fanalyzer-checker=taint, and you disable it with-Wno-analyzer-tainted-array-index๐ It warns for paths where an attacker-controllable value is used as an array index without being sanitized, which could let an attacker inject an out-of-bounds access ๐ See CWE-129: Improper Validation of Array Index, athttps://cwe.mitre.org/data/definitions/129.html๐-Wno-analyzer-tainted-divisorโ needs both-fanalyzerand-fanalyzer-checker=taint, and-Wno-analyzer-tainted-divisorshuts it off ๐ โโ๏ธ It warns for paths where an attacker-controllable value is used as the divisor in a division or modulus operation without being sanitized, so an attacker could inject a division-by-zero ๐-Wno-analyzer-tainted-offsetโ needs both-fanalyzerand-fanalyzer-checker=taint, and you can turn it off with-Wno-analyzer-tainted-offset๐ฆ It warns for paths where an attacker-controllable value is used as a pointer offset without being sanitized, which could let an attacker inject an out-of-bounds access. See CWE-823: Use of Out-of-range Pointer Offset, athttps://cwe.mitre.org/data/definitions/823.html๐-Wno-analyzer-tainted-sizeโ needs both-fanalyzerand-fanalyzer-checker=taint, and-Wno-analyzer-tainted-sizedisables it ๐ It warns for paths where an attacker-controllable value is used as the size of an operation likememsetwithout being sanitized, so an attacker could inject an out-of-bounds access ๐ค-Wno-analyzer-unsafe-call-within-signal-handlerโ needs-fanalyzer, and-Wno-analyzer-unsafe-call-within-signal-handlerturns it off โญ It warns for paths where a function known to be async-signal-unsafe, likefprintf, gets called from inside a signal handler ๐ซ-Wno-analyzer-use-after-freeโ needs-fanalyzer, and you disable it with-Wno-analyzer-use-after-free๐ฅ It warns for paths where a pointer gets used after a deallocator has been called on it. That deallocator is eitherfree, or a deallocator referenced by attribute "malloc" ๐-Wno-analyzer-use-of-pointer-in-stale-stack-frameโ needs-fanalyzer, and-Wno-analyzer-use-of-pointer-in-stale-stack-frameswitches it off ๐ง It warns for paths where a pointer gets dereferenced and it points to a variable in a stale stack frame ๐-Wno-analyzer-write-to-constโ needs-fanalyzer, and-Wno-analyzer-write-to-constturns it off ๐ซถ It warns for paths where the analyzer detects an attempt to write through a pointer to aconstobject. Heads up, though: the analyzer doesn't prioritize these, so false negatives are more likely relative to other warnings ๐-Wno-analyzer-write-to-string-literalโ needs-fanalyzer, and you can disable it with-Wno-analyzer-write-to-string-literal๐ It warns for paths where the analyzer detects an attempt to write through a pointer to a string literal. Same vibe as before: the analyzer doesn't prioritize these, so false negatives are more likely relative to other warnings ๐ธ-Wno-analyzer-use-of-uninitialized-valueโ needs-fanalyzer, and-Wno-analyzer-use-of-uninitialized-valueshuts it down โจ It warns for paths where an uninitialized value gets used ๐ญ
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โ okay this one is a whole glow-up for interprocedural analysis โจ Instead of exploring every path through the function from the callsite to each possible return, it computes the effect of certain calls and simplifies things for you. If it's enabled, call summaries only get used for functions with more than one call site, and that are sufficiently complicated (per--param analyzer-min-snodes-for-call-summary=value) ๐ง-fanalyzer-checker=nameโ this one restricts the analyzer to run just the named checker, and it also enables that checker ๐ฏ Some checkers are disabled by default, even with-fanalyzer. The "taint" checker that implements-Wanalyzer-tainted-array-indexis one of them, and this option is required to turn those on ๐ฆ-fno-analyzer-feasibilityโ this one is for analyzer developers, not us mortals ๐งโ๐ป By default, the analyzer checks that there's a feasible control flow path for each diagnostic it emits, meaning the conditions that hold aren't mutually exclusive. Diagnostics with no feasible path get rejected. This filtering can be suppressed with-fno-analyzer-feasibility, which is handy for debugging issues in this code ๐-fanalyzer-fine-grainedโ another developer-only option ๐ ๏ธ Internally, the analyzer builds an "exploded graph" that combines control flow graphs with data flow information. By default, an edge in this graph can hold the effects of a run of multiple statements within a basic block. With-fanalyzer-fine-grained, each statement gets its own edge ๐-fanalyzer-show-duplicate-countโ developer-only, and honestly kinda iconic ๐ If multiple diagnostics are detected as duplicates of each other, this emits a note when reporting the best diagnostic, telling you how many additional diagnostics were suppressed by the deduplication logic ๐-fno-analyzer-state-mergeโ developer-only ๐งช By default, the analyzer simplifies things by merging sufficiently similar states at each program point while it builds its "exploded graph". With-fno-analyzer-state-merge, that merging gets suppressed, which is useful for debugging state-handling issues ๐ง-fno-analyzer-state-purgeโ developer-only ๐งน By default, the analyzer purges aspects of state at a program point that seem no longer relevant. For example, the values of locals that aren't accessed later in the function and aren't relevant to leak analysis. With-fno-analyzer-state-purge, that purging gets suppressed, for debugging state-handling issues ๐-fanalyzer-transitivityโ this one enables transitivity of constraints within the analyzer ๐-fanalyzer-verbose-edgesโ developer-only, and it's all about detail ๐ค It turns on more verbose, lower-level info in the descriptions of control flow within diagnostic paths ๐ธ-fanalyzer-verbose-state-changesโ developer-only too ๐ง It enables more verbose, lower-level detail in the descriptions of events relating to state machines within diagnostic paths ๐ฆ-fanalyzer-verbosity=levelโ this one controls how complex the control flow paths are that get emitted for analyzer diagnostics ๐
The level can be one of these, bestie ๐ โจ
0โ ๐ฆ At this level, the analyzer shows interprocedural call and return events, along with the most pertinent state-change events for a diagnostic. Like, for a double-"free" diagnostic, both calls to "free" will show up so you can see exactly what happened ๐1โ ๐ธ Same as level0, but it also shows events for the entry to each function. Main character energy ๐2โ ๐ Same as level1, but it also shows control flow events that matter for triggering the issue, like "true path taken" at a conditional. This is the default level, so you're already getting this one ๐ซถ3โ ๐ง Same as level2, but now it shows all control flow events, not just the significant ones. It's a lot, but it's thorough ๐ญ4โ ๐ง This one is for analyzer developers. It adds a bunch of extra events meant for debugging the analyzer itself, so unless you're the analyzer dev, maybe skip it ๐-fdump-analyzerโ ๐ Dumps internal details about what the analyzer is doing tofile.analyzer.txt. This option gets overridden by-fdump-analyzer-stderr, so keep that in mind ๐-fdump-analyzer-stderrโ ๐ฅ๏ธ Dumps the same internal details, but to stderr instead. This one overrides-fdump-analyzer, so if you use both, this one wins ๐-fdump-analyzer-callgraphโ ๐ธ๏ธ Dumps a representation of the call graph that's suitable for viewing with GraphViz, written tofile.callgraph.dot-fdump-analyzer-exploded-graphโ ๐ Dumps a representation of the "exploded graph" for GraphViz, written tofile.eg.dot. The nodes are color-coded based on state-machine states so state changes really pop out ๐-fdump-analyzer-exploded-nodesโ ๐ฏ Emits diagnostics showing where the nodes in the "exploded graph" sit in relation to the program source-fdump-analyzer-exploded-nodes-2โ ๐ Dumps a textual representation of the "exploded graph" tofile.eg.txt-fdump-analyzer-exploded-nodes-3โ ๐๏ธ Dumps a textual representation of the "exploded graph", but one dump file per node, namedfile.eg-id.txt. Heads up, this is typically a huge number of dump files ๐-fdump-analyzer-exploded-pathsโ ๐ค๏ธ Dumps a textual representation of the "exploded path" for each diagnostic tofile.idx.kind.epath.txt-fdump-analyzer-feasibilityโ ๐ Dumps internal details about the analyzer's search for feasible paths. The details are written in a form suitable for GraphViz, to filenames of the formfile.*.fg.dotandfile.*.tg.dot-fdump-analyzer-jsonโ ๐ฆ Dumps a compressed JSON representation of analyzer internals tofile.analyzer.json.gz. Just a heads up that the precise format is subject to change, so don't build your whole life on it ๐ซ-fdump-analyzer-state-purgeโ ๐งน Same idea as-fdump-analyzer-supergraph, dumping a GraphViz-friendly "supergraph", but annotated with what state will be purged at each node. It's written tofile.state-purge.dot-fdump-analyzer-supergraphโ ๐บ๏ธ Dumps representations of the "supergraph" for GraphViz, tofile.supergraph.dotandfile.supergraph-eg.dot. These show every control flow graph in the program, with interprocedural edges for calls and returns. The second dump has annotations showing the "exploded graph" nodes and the diagnostics attached to them โจ
๐ Options for Debugging Your Program
To tell GCC to emit extra info for a debugger, you almost always just need to add -g to your other options ๐. Some debug formats can co-exist (like DWARF with CTF) when each one is enabled explicitly by adding its own command line option alongside your other options.
GCC lets you use -g with -O. Fair warning though, the shortcuts optimized code takes can be surprising ๐ญ: some variables you declared may not exist at all, flow of control may briefly jump somewhere you didn't expect, some statements may not run because they compute constant results or their values are already at hand, and some statements may run 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 debugging-friendly info don't run at all, so -Og may give you a better debugging experience ๐
-gโ ๐ Produces debugging info in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this info.
On most systems that use stabs format, -g turns on extra debugging info that only GDB can use. That makes debugging nicer in GDB, but it probably makes other debuggers crash or refuse to read the program ๐. If you want to be certain about whether the extra info gets generated, use -gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below) ๐ซถ
-ggdbโ ๐ฏ Produces debugging info for GDB. It uses the most expressive format available (DWARF, stabs, or the native format if neither of those is supported), including GDB extensions if at all possible ๐-gdwarf,-gdwarf-versionโ ๐งฉ Produces debugging info in DWARF format (if that's supported). The value ofversionmay be 2, 3, 4 or 5. The default version for most targets is 5, with the exceptions of VxWorks, TPF and Darwin/Mac OS X, which default to version 2, and AIX, which defaults to version 4 ๐
Note that 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 ๐ฆ
-gbtfโ ๐ชฒ Requests BTF debug info. BTF is the default debugging format for the eBPF target. On other targets, like x86, BTF debug info can be generated along with DWARF debug info when both formats are enabled explicitly through their respective command line options ๐-gctf,-gctflevelโ ๐งพ Requests CTF debug info, andlevelcontrols how much CTF debug info gets produced. If you use-gctfwithout a value forlevel, the default level is 2 โจ
CTF debug info can be generated along with DWARF debug info when both formats are enabled explicitly through their respective command line options.
Level 0 produces no CTF debug info at all, so -gctf0 negates -gctf ๐
โโ๏ธ
Level 1 produces CTF info for tracebacks only. This includes callsite info, but not type info.
Level 2 produces type info for entities (functions, data objects, etc.) at file scope or global scope only.
-gstabsโ ๐ Produces debugging info 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 info in stabs format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands. Using these extensions will likely make other debuggers crash or refuse to read the program ๐-gxcoffโ ๐๏ธ Produces debugging info in XCOFF format (if that's supported). This is the format the DBX debugger uses on IBM RS/6000 systems.-gxcoff+โ ๐งจ Produces debugging info in XCOFF format (if that's supported), using GNU extensions that only GDB understands. Using these extensions will likely make other debuggers crash or refuse to read the program, and it may cause assemblers other than the GNU assembler (GAS) to fail with an error ๐ญ-gvmsโ ๐ค Produces debugging info in Alpha/VMS debug format (if that's supported). This is the format DEBUG uses on Alpha/VMS systems.-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ ๐๏ธ Requests debugging info and useslevelto specify how much info you get. The default level is 2.
Level 0 produces no debug info at all, so -g0 negates -g ๐
โโ๏ธ
Level 1 produces minimal info, enough to make backtraces in the parts of the program you don't plan to debug. This includes descriptions of functions and external variables, and line number tables, but no info about local variables.
Level 3 includes extra info, like all the macro definitions present in the program. Some debuggers support macro expansion when you use -g3 ๐
If you use multiple -g options, with or without level numbers, the last one is the one that takes effect ๐
-gdwarf doesn't accept a concatenated debug level, to avoid confusion with -gdwarf-level. Instead, use an additional -glevel option to change the debug level for DWARF ๐ง
-fno-eliminate-unused-debug-symbolsโ ๐ซ By default, no debug info is produced for symbols that aren't actually used. Use this option if you want debug info for all symbols ๐-femit-class-debug-alwaysโ ๐ช Instead of emitting debugging info for a C++ class in only one object file, this emits it in all object files that use the class. This option should only be used with debuggers that can't handle the way GCC normally emits debugging info for classes, because it increases the size of the debugging info by as much as a factor of two ๐-fno-merge-debug-stringsโ ๐งต Tells the linker not to merge together strings in the debugging info that are identical across different object files. Merging isn't supported by all assemblers or linkers. It decreases the size of the debug info in the output file, at the cost of longer link processing time. Merging is enabled by default โจ-fdebug-prefix-map=old=newโ okay so when you compile files living inold, GCC writes the debug info like they actually live innewinstead ๐บ๏ธ Bestie, this lets you swap a build-time path for an install-time path in the debug info. You can also turn an absolute path into a relative one by using.fornew. It can give more reproducible builds that don't care where they're located ๐ธ, 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 can handle it. It's on by default when you compile with optimization (-Os,-O,-O2, ...) and debug info (-g) and the debug info format supports it. Lowkey main character energy โจ-fvar-tracking-assignmentsโ this annotates assignments to user variables early in compilation and tries to carry those annotations all the way to the end ๐ The goal is better debug info while optimizing. Using-gdwarf-4alongside it is recommended. It can be turned on even when var-tracking is off, but then the annotations get made and maintained and then tossed at the end. By default it's enabled together with-fvar-tracking, except when selective scheduling is enabled.-gsplit-dwarfโ if DWARF debug info is enabled, this splits as much of it as possible into a separate output file ending in.dwo๐ง This lets the build system skip linking files that have debug info. To actually be useful, you need a debugger that can read.dwofiles.-gdwarf32,-gdwarf64โ if DWARF debug info is enabled,-gdwarf32picks the 32-bit DWARF format and-gdwarf64picks the 64-bit one ๐ The default is target specific, though on most targets it's-gdwarf32. The 32-bit format is smaller, but it can't handle more than 2GiB of debug info in any of the DWARF debug info sections. The 64-bit format allows bigger debug info, but not every consumer supports it yet ๐-gdescribe-diesโ this adds description attributes to some DWARF DIEs that don't have a name attribute ๐ Think artificial variables, external references and call site parameter DIEs.-gpubnamesโ generates the DWARF.debug_pubnamesand.debug_pubtypessections ๐-ggnu-pubnamesโ generates.debug_pubnamesand.debug_pubtypesin a format that can be converted into a GDB index ๐ซถ Heads up, this only helps 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 in.debug_info๐ It's more efficient in a separate comdat section, since the linker can then remove duplicates. But not every DWARF consumer supports.debug_typesyet, and on some objects it makes the debug info bigger instead of 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 โจ They're joined with spaces, separating them from each other and from the compiler version. It's enabled by default. See also-frecord-gcc-switchesfor another way of stashing compiler options in the object file.-gstrict-dwarfโ no extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ซ On most targets, using non-conflicting extensions from later standard versions is allowed anyway.-gno-strict-dwarfโ allows extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ฆ-gas-loc-supportโ tells the compiler that the assembler supports.locdirectives ๐ฅ The compiler can then use them so the assembler generates DWARF2+ line number tables. This is usually what you want, because assembler-generated line number tables are a lot more compact than the ones the compiler makes itself. It's enabled by default if the assembler was found to support these directives at GCC configure time.-gno-as-loc-supportโ forces GCC to generate DWARF2+ line number tables internally, if those tables are supposed to be generated at all ๐ โโ๏ธ-gas-locview-supportโ tells the compiler that the assembler supports"view"assignment and reset assertion checking in.locdirectives ๐ It's enabled by default if the assembler was found to support them at GCC configure time.-gno-as-locview-supportโ forces GCC to assign view numbers internally, but only if-gvariable-location-viewswas explicitly requested ๐ฅบ-gcolumn-info,-gno-column-infoโ emits location column information into DWARF debug info, instead of just file and line ๐ It's enabled by default.-gstatement-frontiers,-gno-statement-frontiersโ this makes GCC drop markers in the internal representation at the start of statements ๐งญ It keeps them roughly in place throughout compilation and uses them to guide the output of"is_stmt"markers in the line number table. It's enabled by default when you compile with optimization (-Os,-O1,-O2, ...) and output DWARF 2 debug info at the normal level.-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-viewsโ this augments variable location lists with progressive view numbers, implied by the line number table ๐ฆ Debug info consumers can then inspect state at certain points in the program, even when no instructions tied to those source locations exist there. If the assembler can't handle view numbers in line number tables, the compiler has to emit the line number table itself, which usually makes them a bit less compact. The augmented tables and lists are fully backward-compatible, so consumers that don't know about these augmentations can still read them, but they won't get any benefit either.
It's enabled by default when outputting DWARF 2 debug info at the normal level, as long as there's assembler support, -fvar-tracking-assignments is enabled, and -gstrict-dwarf is not. Without assembler support it may still be enabled, but that forces GCC to output internal line number tables. If -ginternal-reset-location-views isn't enabled, that will most certainly lead to silently mismatching location views ๐ฌ
โ ๏ธ There's a proposed representation for view numbers that is not backward compatible with the location list format introduced in DWARF 5. You can turn it on with -gvariable-location-views=incompat5. This option may be removed in the future, and it's only provided as a reference implementation of the proposed representation. Debug info consumers aren't expected to support this extended format, and they'd be unable to decode location lists that use it ๐
-ginternal-reset-location-views,-gno-internal-reset-location-viewsโ this attempts to figure out which location views can be left out of location view lists โ๏ธ It needs the compiler to have very accurate insn length estimates, which isn't always the case. It may silently generate incorrect view lists when you're using an assembler that doesn't support location view lists. The GNU assembler will flag any such error as a"view number mismatch". This is only enabled on ports that define a reliable estimation function.-ginline-points,-gno-inline-pointsโ generates extended debug info for inlined functions ๐ Location view tracking markers get inserted at inlined entry points, so address and view numbers can be computed and output in the debug info. This can be enabled independently of location views, in which case the view numbers won't be output. It can only be enabled along with statement frontiers, and it's only enabled by default if location views are enabled.-gz[=type]โ produces compressed debug sections in DWARF format, if that's supported ๐๏ธ If type isn't given, the default depends on what the assembler and linker can do. type may be one of:noneโ don't compress debug sectionszlibโ use zlib compression in ELF gABI formatzlib-gnuโ use zlib compression in traditional GNU format
If the linker can't write compressed debug sections, the option gets rejected. Otherwise, if the assembler doesn't support them, -gz is silently ignored when producing object files.
-femit-struct-debug-baseonlyโ emits debug info for struct-like types only when the base name of the compilation source file matches the base name of the file where the struct is defined ๐ฅน This substantially reduces the size of debug info, but there's a significant potential loss in type information for the debugger. For a less aggressive option, see-femit-struct-debug-reduced. For more detailed control, see-femit-struct-debug-detailed. This option only works with DWARF debug output.-femit-struct-debug-reducedโ emits debug info for struct-like types only when the base name of the compilation source file matches the base name of the file where the type is defined ๐ธ The exception is if the struct is a template or is defined in a system header. This significantly reduces the size of debug info, with some potential loss in type information. For a more aggressive option, see-femit-struct-debug-baseonly. For more detailed control, see-femit-struct-debug-detailed. This only works with DWARF debug output.-femit-struct-debug-detailed[=spec-list]โ this lets you specify which struct-like types the compiler generates debug info for ๐ฏ The whole point is to cut down on duplicate struct debug info between different object files within the same program.
This one is the glow-up of -femit-struct-debug-reduced and -femit-struct-debug-baseonly ๐
โจ and honestly it covers most of what you'll need ๐ Its value looks like this:
[dir:|ind:][ord:|gen:](any|sys|base|none)
The first word is optional and filters by how a struct gets used ๐ฆ dir: means the struct is used directly, like it's the type of a variable or a member. ind: means it's used indirectly, through pointers to structs. Basically, if using an incomplete struct would be valid, that's an indirect use ๐ For example, in struct one direct; struct two * indirect;, the first one is direct and the second one is indirect.
The second word is also optional and picks between ordinary structs (ord:) and generic structs (gen:) ๐ง Generic structs are a little tricky, ngl. In C++, they're non-explicit specializations of template classes, or non-template classes inside those. Other languages have generics too, but -femit-struct-debug-detailed doesn't implement them yet, so don't expect it to handle them ๐ญ
The third word decides which source files get debug info for their structs ๐ธ none and any mean what you'd expect. base means the base name of the file where the type is declared has to match the base name of your main compilation file. So when you compile foo.c, you get debug info for types declared in foo.c and foo.h, but not other headers ๐ sys covers types that match base or that are declared in system or compiler headers.
You might need to play around with settings to find what works best for your project ๐ซถ
The default is -femit-struct-debug-detailed=all.
This option only works with DWARF debug output, so keep that in mind bestie โ ๏ธ
-fno-dwarf2-cfi-asmโ Puts DWARF unwind info into a compiler-generated.eh_framesection, instead of using GAS.cfi_*directives ๐-fno-eliminate-unused-debug-typesโ Normally, when making DWARF output, GCC skips debug info for types that never show up in the source file being compiled ๐ Sometimes you want debug info for every type declared in a compilation unit, even unused ones. For example, you might want to cast a value to a type that's declared but not used in your program while you're debugging ๐ Most of the time though, this just wastes a ton of space ๐
โจ Options That Control Optimization โจ
These options control various kinds of optimization ๐ฅ
Without any optimization option, the compiler's goal is to cut down on compilation cost and make debugging give you the results you expect ๐ Statements are independent. So if you hit a breakpoint between statements, you can assign a new value to any variable, or jump the program counter to any other statement in the function, and get exactly the results you'd expect from the source code ๐ฆ
Turning on optimization flags makes the compiler try to improve performance and/or code size, but it costs compilation time and might make the program harder to debug ๐ธ
The compiler optimizes based on what it knows about your program ๐ง Compiling multiple files at once into a single output file lets the compiler use info from all of those files when it compiles each one ๐
Not every optimization has a flag ๐ Only the ones that do are listed in this section.
Most optimizations are completely disabled at -O0, or whenever no -O level is set on the command line, even if you add individual optimization flags ๐ In the same way, -Og suppresses lots of optimization passes.
Depending on your target and how GCC was configured, the set of optimizations enabled at each -O level might be a little different from what's listed here ๐ To find the exact set for each level, run -Q --help=optimizers ๐ซถ
If you use more than one -O option, with or without level numbers, the last one is the one that counts ๐
Options that look like -fflag are machine-independent flags โจ Most flags have both a positive and a negative form, and the negative form of -ffoo is -fno-foo. Below, only one form is listed, the one you'll usually use ๐ You can figure out the other one by removing no- or adding it.
The following options control specific optimizations ๐ฆ They're either turned on by -O options or related to ones that are. You can use these flags in the rare cases when you want to "fine-tune" which optimizations get performed ๐ง
-O,-O1โ Optimize ๐ธ Optimizing compilation takes somewhat more time, and a lot more memory for a large function. With-O, the compiler tries to shrink code size and cut execution time, without doing any optimization that takes a huge amount of compilation time.-Oturns on the following flags:
-fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments
-fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdelayed-branch
-fdse -fforward-propagate -fguess-branch-probability -fif-conversion
-fif-conversion2 -finline-functions-called-once -fipa-modref
-fipa-profile -fipa-pure-const -fipa-reference
-fipa-reference-addressable -fmerge-constants -fmove-loop-invariants
-fmove-loop-stores -fomit-frame-pointer -freorder-blocks
-fshrink-wrap -fshrink-wrap-separate -fsplit-wide-types
-fssa-backprop -fssa-phiopt -ftree-bit-ccp -ftree-ccp -ftree-ch
-ftree-coalesce-vars -ftree-copy-prop -ftree-dce
-ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre
-ftree-phiprop -ftree-pta -ftree-scev-cprop -ftree-sink -ftree-slsr
-ftree-sra -ftree-ter -funit-at-a-time
-O2โ Optimize even more ๐ฅ GCC does nearly every supported optimization that doesn't involve a space-speed tradeoff. Compared to-O, this increases both compilation time and the performance of the generated code.-O2turns on every flag that-O1does, plus these:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fcaller-saves -fcode-hoisting -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize
-fdevirtualize-speculatively -fexpensive-optimizations
-ffinite-loops -fgcse -fgcse-lm -fhoist-adjacent-loads
-finline-functions -finline-small-functions -findirect-inlining
-fipa-bit-cp -fipa-cp -fipa-icf -fipa-ra -fipa-sra -fipa-vrp
-fisolate-erroneous-paths-dereference -flra-remat
-foptimize-sibling-calls -foptimize-strlen -fpartial-inlining
-fpeephole2 -freorder-blocks-algorithm=stc
-freorder-blocks-and-partition -freorder-functions
-frerun-cse-after-loop -fschedule-insns -fschedule-insns2
-fsched-interblock -fsched-spec -fstore-merging -fstrict-aliasing
-fthread-jumps -ftree-builtin-call-dce -ftree-loop-vectorize
-ftree-pre -ftree-slp-vectorize -ftree-switch-conversion
-ftree-tail-merge -ftree-vrp -fvect-cost-model=very-cheap
Heads up bestie ๐ There's a warning under-fgcseabout using-O2on programs that use computed gotos, so go read that before you turn it on ๐
-O3โ Optimize yet more ๐ช-O3turns on every optimization that-O2does, and also these flags:
-fgcse-after-reload -fipa-cp-clone -floop-interchange
-floop-unroll-and-jam -fpeel-loops -fpredictive-commoning
-fsplit-loops -fsplit-paths -ftree-loop-distribution
-ftree-partial-pre -funswitch-loops -fvect-cost-model=dynamic
-fversion-loops-for-strides
-O0โ Cuts down compilation time and makes debugging give the expected results ๐ง This is the default ๐-Osโ Optimize for size ๐-Osenables all-O2optimizations except the ones that often increase code size. Those are:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, makes the compiler tune for code size instead of execution speed, and runs further optimizations designed to shrink the code ๐ฆ
-Ofastโ Ignores strict standards compliance ๐-Ofastenables all-O3optimizations. It also turns on optimizations that aren't valid for every standard-compliant program. It turns on-ffast-math,-fallow-store-data-racesand the Fortran-specific-fstack-arrays, unless-fmax-stack-var-sizeis specified, and-fno-protect-parens. It turns off-fsemantic-interposition.
This one is spicy, so only use it if you know your code can handle these looser rules โ ๏ธ
-Ogโ Optimize the debugging experience ๐-Ogshould be your go-to level for the normal edit-compile-debug cycle ๐ It gives you a reasonable amount of optimization while keeping compilation fast and debugging smooth. It's a better pick than-O0for producing debuggable code, because some compiler passes that collect debug info are disabled at-O0.
Like -O0, -Og completely disables a bunch of optimization passes, so the individual options that control them do nothing. Otherwise, -Og enables all -O1 optimization flags except the ones that might get in the way of debugging:
-fbranch-count-reg -fdelayed-branch -fdse -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fmove-loop-stores -fssa-phiopt
-ftree-bit-ccp -ftree-dse -ftree-pta -ftree-sra
-Ozโ Optimize aggressively for size instead of speed ๐ธ This may increase the number of instructions executed, if those instructions take fewer bytes to encode.-Ozworks similarly to-Os, including turning on most-O2optimizations.-fno-defer-popโ For machines that have to pop arguments after a function call, this pops the arguments as soon as each function returns ๐งน At-O1and higher,-fdefer-popis the default, which lets the compiler let arguments pile up on the stack across several function calls and pop them all at once ๐ฅ-fforward-propagateโ Runs a forward propagation pass on RTL โจ The pass tries to combine two instructions and checks whether the result can be simplified. If loop unrolling is active, two passes run, and the second one is scheduled after loop unrolling. This option is enabled by default at optimization levels-O1,-O2,-O3,-Os๐-ffp-contract=styleโจ โ this one's all about floating-point expression contraction, and it comes in three flavours:-ffp-contract=off๐ซ turns contraction off entirely.-ffp-contract=fast๐ฅ turns it on, so things like fused multiply-add operations can get formed when the target has native support for them.-ffp-contract=on๐ค turns it on only if the language standard allows it. Bestie, this one is currently not implemented, so it's treated exactly the same as-ffp-contract=off. Not it. ๐
The default is -ffp-contract=fast. ๐
-fomit-frame-pointer๐ฆ โ skip the frame pointer in any function that doesn't actually need one. That means no more instructions to save, set up, and restore it, and on lots of targets you also get an extra register to play with. Iconic. โจ
On some targets this does literally nothing, because the standard calling sequence always uses a frame pointer, so it can't be left out. ๐
Heads up: -fno-omit-frame-pointer doesn't promise the frame pointer gets used in every function. Several targets always omit it in leaf functions anyway. ๐
Enabled by default at -O1 and higher. ๐ธ
-foptimize-sibling-calls๐ โ optimizes sibling and tail recursive calls. Main character energy. ๐
Enabled at levels -O2, -O3, -Os. ๐ฅ
-foptimize-strlen๐ง โ speeds up standard C string functions like"strlen","strchr"or"strcpy", plus their"_FORTIFY_SOURCE"counterparts, by swapping them for faster alternatives. Obsessed. ๐ญ
Enabled at levels -O2, -O3. โจ
-fno-inline๐ โโ๏ธ โ don't expand any functions inline, except the ones marked with thealways_inlineattribute. This is the default when you're not optimizing. ๐
If you want to exempt just a single function from inlining, mark it with the noinline attribute. ๐ซถ
-finline-small-functions๐ โ integrates functions into their callers whenever the body is smaller than the code for calling it would be, so the overall program gets smaller. The compiler makes a heuristic guess about which functions are simple enough. This applies to all functions, even the ones not declared inline. It's giving efficiency. ๐
Enabled at levels -O2, -O3, -Os. โญ
-findirect-inlining๐ฎ โ also inlines indirect calls that the compiler can figure out at compile time, thanks to earlier inlining. This only does anything if inlining is already turned on by-finline-functionsor-finline-small-functions. ๐
Enabled at levels -O2, -O3, -Os. ๐ธ
-finline-functions๐ฆข โ considers every function for inlining, even the ones not declared inline. The compiler heuristically picks which ones are worth integrating. ๐ง
If every call to a given function gets integrated and the function is declared static, it usually won't be output as assembler code in its own right. Lowkey genius. ๐
Enabled at levels -O2, -O3, -Os. Also enabled by -fprofile-use and -fauto-profile. ๐
-finline-functions-called-once๐ โ considers allstaticfunctions called exactly once for inlining into their caller, even if they aren't markedinline. Once a call to one of them gets integrated, that function isn't output as assembler code in its own right. ๐ฅน
Enabled at levels -O1, -O2, -O3 and -Os, but not -Og. ๐ซ
-fearly-inliningโก โ inlines functions markedalways_inline, along with any functions whose body seems smaller than the function call overhead. This happens early, before the-fprofile-generateinstrumentation and the real inlining pass. It makes profiling way cheaper and usually makes inlining faster in programs with big chains of nested wrapper functions. Efficient, bestie. ๐ซง
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. Very cleanup-core. ๐งน
Enabled at levels -O2, -O3 and -Os. ๐
-finline-limit=n๐๏ธ โ GCC normally caps how big a function can be and still get inlined. This flag gives you coarse control over that cap, wherenis the size of inlinable functions measured in pseudo instructions. ๐
Inlining is actually controlled by a bunch of parameters, which you can set one at a time with --param name=value. The -finline-limit=n option sets some of them for you:
max-inline-insns-singleis set ton/2.max-inline-insns-autois set ton/2.
See below for documentation on the individual inlining parameters and what their defaults are. ๐
Note: there may be no value for -finline-limit that gives you the default behaviour. Plot twist. ๐ญ
Note: "pseudo instruction" is just an abstract measurement of a function's size in this context. It is in no way a count of assembly instructions, so what it means could change from one release to another. Don't build your whole personality around it. ๐
-fno-keep-inline-dllexport๐ฏ โ a more fine-grained version of-fkeep-inline-functions. It only applies to functions declared with the"dllexport"attribute or declspec. ๐ช-fkeep-inline-functions๐ฆ โ in C, emitsstaticfunctions declaredinlineinto the object file, even if they've been inlined into all of their callers. This doesn't touch functions using theextern inlineextension in GNU C90. In C++, it emits any and all inline functions into the object file. ๐ง-fkeep-static-functions๐พ โ emitsstaticfunctions into the object file, even if they're never used. Packed, no notes. ๐-fkeep-static-consts๐ โ emits variables declaredstatic constwhen optimization isn't turned on, even if nothing references them. ๐ฅก
GCC turns this on by default. If you want the compiler to check whether a variable is referenced no matter what optimization is doing, use -fno-keep-static-consts. ๐ต๏ธโโ๏ธ
-fmerge-constants๐ค โ tries to merge identical constants (string constants and floating-point constants) across compilation units. ๐งท
This is the default for optimized compilation if the assembler and linker support it. Use -fno-merge-constants to shut this behaviour down. ๐
โโ๏ธ
Enabled at levels -O1, -O2, -O3, -Os. ๐
-fmerge-all-constants๐ซ โ tries to merge identical constants and identical variables. It implies-fmerge-constants, and on top of that it considers things like constant initialized arrays or initialized constant variables with integral or floating-point types. ๐งฎ
Warning, bestie: C and C++ require every variable, including multiple instances of the same variable in recursive calls, to have distinct locations. Using this option therefore results in non-conforming behaviour. Proceed with caution. ๐
-fmodulo-sched๐ข โ performs swing modulo scheduling right before the first scheduling pass. It looks at the innermost loops and reorders their instructions by overlapping different iterations. Honestly, so smart. ๐ง โจ-fmodulo-sched-allow-regmoves๐โโ๏ธ โ performs more aggressive SMS-based modulo scheduling and allows register moves. Setting this flag deletes certain anti-dependence edges, which triggers generation of reg-moves based on the life-range analysis. This only works when-fmodulo-schedis also enabled. ๐-fno-branch-count-reg๐ข โ disables the optimization pass that hunts for chances to use "decrement and branch" instructions on a count register. Instead of decrementing a register, comparing it against zero, and then branching based on the result, you get the count-register version. This only matters on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390. ๐ฅ๏ธ
Note that -fno-branch-count-reg doesn't remove the decrement and branch instructions that other optimization passes already put into the generated instruction stream. ๐ซถ
The default is -fbranch-count-reg at -O1 and higher, except for -Og. ๐ธ
-fno-function-cse๐ โ doesn't put function addresses into registers. Instead, every instruction that calls a constant function contains that function's address explicitly. ๐
This gives you less efficient code, but some strange hacks that alter the assembler output may get confused by the optimizations you get when this option is not used. So, know your hacks. ๐งช
The default is -ffunction-cse. ๐
-fno-zero-initialized-in-bss๐๏ธ โ if the target supports a BSS section, GCC normally puts variables that are initialized to zero into BSS, which can save space in the resulting code. This option turns that behaviour off, because some programs explicitly rely on variables going into the data section. For example, a program might want to find the beginning of that section, or make assumptions based on it. ๐งญ
The default is -fzero-initialized-in-bss. ๐
-fthread-jumps๐งต โ performs optimizations that check whether a jump branches to a location where another comparison, subsumed by the first, is found. If it is, the first branch gets redirected to either the destination of the second branch or to the point right after it, depending on whether the condition is known to be true or false. ๐ชก
Enabled at levels -O1, -O2, -O3, -Os. โจ
-fsplit-wide-types๐ช โ when a type occupies multiple registers (like"long long"on a 32-bit system), this splits the registers apart and allocates them independently. This usually generates better code for those types, but it may make debugging harder. Tradeoffs, bestie. ๐ฅฒ
Enabled at levels -O1, -O2, -O3, -Os. ๐ซง
-fsplit-wide-types-earlyโฐ โ fully splits wide types early, instead of very late. This does nothing unless-fsplit-wide-typesis turned on. It's the default on some targets. ๐ฏ-fcse-follow-jumps๐ โ during common subexpression elimination (CSE), it scans through jump instructions when the jump's target isn't reached by any other path. For example, when CSE meets an"if"statement with an"else"clause, it follows the jump when the tested condition is false. ๐
Enabled at levels -O2, -O3, -Os. ๐
-fcse-skip-blocks๐ฆ โ similar to-fcse-follow-jumps, but it makes CSE follow jumps that conditionally skip over blocks. When CSE hits a simple"if"statement with no"else"clause,-fcse-skip-blockshas CSE follow the jump around the body of the"if". Slick. ๐
Enabled at levels -O2, -O3, -Os. ๐
-frerun-cse-after-loop๐ โ re-runs common subexpression elimination after the loop optimizations have been performed. Second chances are everything. ๐ฅฐ
Enabled at levels -O2, -O3, -Os. โญ
-fgcseโ ๐ Okay so this turns on a global common subexpression elimination pass, and it also does global constant and copy propagation. It's giving "stop redoing the same work" energy โจ. Note: if you're compiling a program that uses computed gotos (a GCC extension), you might get better run-time performance by turning this pass off with-fno-gcseon the command line ๐ . Enabled at levels-O2,-O3,-Os.-fgcse-lmโ ๐ธ When this is on, global common subexpression elimination tries to move loads that only get killed by stores into themselves. So a loop with a load/store sequence can get its load moved outside the loop, with a copy/store inside the loop. Lowkey iconic ๐ฆ. Enabled by default when-fgcseis enabled.-fgcse-smโ ๐งน This runs a store motion pass right after global common subexpression elimination, and it tries to move stores out of loops. If you pair it with-fgcse-lm, a loop with a load/store sequence can become a load before the loop and a store after it ๐ซถ. Not enabled at any optimization level.-fgcse-lasโ ๐ This one eliminates redundant loads that happen after stores to the same memory location, covering both partial and full redundancies. Not enabled at any optimization level.-fgcse-after-reloadโ ๐งฝ This runs a redundant load elimination pass after reload, and its whole job is cleaning up redundant spilling. Enabled by-O3,-fprofile-useand-fauto-profile.-faggressive-loop-optimizationsโ ๐ The loop optimizer uses language constraints to figure out bounds for a loop's number of iterations. This assumes loop code does not invoke undefined behavior, like signed integer overflows or out-of-bound array accesses, so be careful with that ๐ฌ. The bounds guide loop unrolling, loop peeling, and loop exit test optimizations. Enabled by default.-funconstrained-commonsโ ๐ฆ This tells the compiler that variables declared in common blocks (like in Fortran) might later get overridden with longer trailing arrays. It stops certain optimizations that depend on knowing the array bounds ๐.-fcrossjumpingโ ๐ This does the cross-jumping transformation, which unifies equivalent code and saves code size. The result may or may not perform better than without it, so it's not a guaranteed win ๐คทโโ๏ธ. Enabled at levels-O2,-O3,-Os.-fauto-inc-decโ โ This combines increments or decrements of addresses with memory accesses. It's always skipped on architectures that don't have instructions to support it. Enabled by default at-O1and higher on architectures that support this.-fdceโ ๐๏ธ This does dead code elimination (DCE) on RTL. Enabled by default at-O1and higher.-fdseโ ๐งผ This does dead store elimination (DSE) on RTL. Enabled by default at-O1and higher.-fif-conversionโ ๐ This tries to transform conditional jumps into branch-less equivalents. That includes conditional moves, min, max, set flags, abs instructions, and 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-O1,-O2,-O3,-Os, but not with-Og.-fif-conversion2โ โก This uses conditional execution (where the hardware has it) to transform conditional jumps into branch-less equivalents. Enabled at levels-O1,-O2,-O3,-Os, but not with-Og.-fdeclone-ctor-dtorโ ๐ฏ Okay, the C++ ABI needs multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that calls operator delete afterwards. With virtual bases, the base and complete variants end up as clones, which means two copies of the function. With this option, those variants become thunks that call one common implementation ๐ง. Enabled by-Os.-fdelete-null-pointer-checksโ ๐ซ This assumes programs can't safely dereference null pointers, and that no code or data element lives at address zero. It turns on simple constant folding optimizations at all optimization levels. Other GCC passes use this flag to run global dataflow analyses that remove useless null pointer checks. Those analyses assume that touching address zero always traps, so if a pointer gets checked after it's already been dereferenced, it can't be null ๐.
โ ๏ธ Heads up: in some environments this assumption isn't true. If your program depends on that behavior, use -fno-delete-null-pointer-checks to turn this optimization off.
This option is enabled by default on most targets. On Nios II ELF it defaults to off. On AVR, CR16, and MSP430 it's completely disabled. Passes that use the dataflow information get enabled independently at different optimization levels.
-fdevirtualizeโ ๐ฏ This tries to convert calls to virtual functions into direct calls. It happens both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp). Enabled at levels-O2,-O3,-Os.-fdevirtualize-speculativelyโ ๐ฎ This tries to convert virtual function calls into speculative direct calls. Based on the type inheritance graph, GCC figures out the likely targets for a given call. If that set is small (ideally size 1), the call becomes a conditional that picks between a direct call and an indirect call. Those speculative calls unlock more optimizations, like inlining. If they turn out to be useless after further optimization, they get converted back to their original form ๐.-fdevirtualize-at-ltransโ ๐ This streams extra information needed for aggressive devirtualization when the link-time optimizer runs in local transformation mode. It enables more devirtualization, but it significantly increases the size of the streamed data, so it's disabled by default ๐.-fexpensive-optimizationsโ ๐ธ This performs a bunch of minor optimizations that are relatively expensive. Enabled at levels-O2,-O3,-Os.-freeโ ๐งน This attempts to remove redundant extension instructions. It's especially helpful on x86-64, 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 made during its lifetime. When the constructor begins, the object has an indeterminate value, and any changes made during its lifetime are dead once it's destroyed. Normally dead store elimination takes advantage of this. If your code relies on the object's storage value sticking around beyond the object's lifetime, use this flag to turn that optimization off ๐ โโ๏ธ. If you want to keep stores 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 can be picked explicitly with-flifetime-dse=2. And-flifetime-dse=0is the same as-fno-lifetime-dse.-flive-range-shrinkageโ ๐ This tries to reduce register pressure through register live range shrinkage. It's helpful for fast processors with small or moderate-sized register sets ๐๏ธ.-fira-algorithm=algorithmโ ๐จ This uses the specified coloring algorithm for the integrated register allocator.algorithmcan bepriority, which means Chow's priority coloring, orCB, which means Chaitin-Briggs coloring. Chaitin-Briggs coloring isn't implemented for every architecture, but on the targets that do support it, it's the default because it generates better code ๐.-fira-region=regionโ ๐บ๏ธ This uses the specified regions for the integrated register allocator. Theregionargument should be one of the following:allโ uses all loops as register allocation regions. This can give the best results for machines with a small and/or irregular register set.mixedโ uses all loops except loops with small register pressure as the regions. This value usually gives the best results in most cases and for most architectures, and it's enabled by default when you compile 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โ ๐๏ธ This uses IRA to evaluate register pressure in the code hoisting pass when deciding whether to hoist expressions. It usually results in smaller code, but it can slow the compiler down ๐ข. Enabled at level-Osfor all targets.-fira-loop-pressureโ ๐ This uses IRA to evaluate register pressure in loops when deciding whether to move loop invariants. It usually generates faster and smaller code on machines with large register files (>= 32registers), but it can also slow the compiler down. Enabled at level-O3for some targets ๐.-fno-ira-share-save-slotsโ ๐ซ This disables sharing of stack slots used for saving call-used hard registers that live through a call. Each hard register gets its own stack slot, so function stack frames end up larger ๐.-fno-ira-share-spill-slotsโ ๐ซ This disables sharing of stack slots allocated for pseudo-registers. Each pseudo-register that doesn't get a hard register gets its own stack slot, so function stack frames end up larger too ๐ฅฒ.-flra-rematโ โป๏ธ This enables CFG-sensitive rematerialization in LRA. Instead of loading the values of spilled pseudos, LRA tries to rematerialize (recalculate) them when that's profitable. Enabled at levels-O2,-O3,-Os.-fdelayed-branchโ ๐ฆฅ If the target machine supports it, this attempts to reorder instructions so it can use the instruction slots available after delayed branch instructions. Enabled at levels-O1,-O2,-O3,-Os, but not at-Og.-fschedule-insnsโ okay so if the target machine supports it, GCC tries to shuffle instructions around so the CPU isn't just sitting there waiting on data that isn't ready yet ๐ This is clutch 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. Enabled at levels-O2,-O3. ๐ฆ-fschedule-insns2โ basically the same energy as-fschedule-insns, but it gets a second scheduling pass after register allocation is done ๐ฅ It's especially iconic on machines with a relatively small number of registers, where memory loads take more than one cycle. Enabled at levels-O2,-O3,-Os.
-fno-sched-interblockโ the vibe here is "no scheduling across basic blocks" ๐ โโ๏ธ Normally this is on when scheduling happens before register allocation, so either-fschedule-insnsor-O2or higher turns it on.-fno-sched-specโ this one shuts off speculative motion of non-load instructions ๐ซ Also normally on when scheduling happens before register allocation, meaning-fschedule-insnsor-O2or higher.-fsched-pressureโ this turns on register pressure sensitive insn scheduling before register allocation ๐ง โจ It only makes sense when that pre-allocation scheduling is on (so-fschedule-insnsor-O2or higher). It can make the generated code better and smaller by keeping register pressure from climbing past the number of available hard registers, which means fewer spills in register allocation. Main character energy, honestly ๐-fsched-spec-loadโ allows speculative motion of some load instructions ๐ Only makes sense when scheduling before register allocation, so-fschedule-insnsor-O2or higher.-fsched-spec-load-dangerousโ the bolder sister of the one above, letting speculative motion of more load instructions ๐ Same deal: only makes sense when scheduling before register allocation, so-fschedule-insnsor-O2or higher.-fsched-stalled-insns,-fsched-stalled-insns=nโ this decides how many insns (if any) can get moved early from the queue of stalled insns into the ready list during the second scheduling pass ๐-fno-sched-stalled-insnsmeans nothing gets moved early, and-fsched-stalled-insns=0means there's no limit on how many queued insns can jump the line. If you just write-fsched-stalled-insnswith no value, it's the same as-fsched-stalled-insns=1.-fsched-stalled-insns-dep,-fsched-stalled-insns-dep=nโ this controls 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 has an effect during the second scheduling pass, and only if-fsched-stalled-insnsis being used.-fno-sched-stalled-insns-depis equivalent to-fsched-stalled-insns-dep=0, and-fsched-stalled-insns-depwith no value is equivalent to-fsched-stalled-insns-dep=1. ๐ซถ-fsched2-use-superblocksโ when scheduling after register allocation, this uses superblock scheduling ๐ That lets instructions move across basic block boundaries, which can give you faster schedules.
โ ๏ธ Heads up bestie: this one is experimental! Not every machine description GCC uses models the CPU closely enough to avoid unreliable results from the algorithm, so be careful with it ๐ญ
It only makes sense when scheduling after register allocation, so -fschedule-insns2 or -O2 or higher.
-fsched-group-heuristicโ turns on the group heuristic in the scheduler, which favors the instruction that belongs to a schedule group ๐ง It's on by default whenever scheduling is enabled, so-fschedule-insnsor-fschedule-insns2or-O2or higher.-fsched-critical-path-heuristicโ enables the critical-path heuristic, which favors instructions sitting on the critical path ๐ฃ๏ธ Also on by default whenever scheduling is enabled, so-fschedule-insnsor-fschedule-insns2or-O2or higher.-fsched-spec-insn-heuristicโ enables the speculative instruction heuristic, which favors speculative instructions with greater dependency weakness ๐ฆ On by default whenever scheduling is enabled, so-fschedule-insnsor-fschedule-insns2or-O2or higher.-fsched-rank-heuristicโ enables the rank heuristic, which favors the instruction living in a basic block with greater size or frequency ๐ On by default whenever scheduling is enabled, so-fschedule-insnsor-fschedule-insns2or-O2or higher.-fsched-last-insn-heuristicโ enables the last-instruction heuristic, which favors the instruction that's less dependent on the last instruction scheduled ๐ On by default whenever scheduling is enabled, so-fschedule-insnsor-fschedule-insns2or-O2or higher.-fsched-dep-count-heuristicโ enables the dependent-count heuristic, which favors the instruction that has more instructions depending on it ๐ฏ On by default whenever scheduling is enabled, so-fschedule-insnsor-fschedule-insns2or-O2or higher.
-freschedule-modulo-scheduled-loopsโ modulo scheduling happens before the traditional scheduling, and if a loop got modulo scheduled, later scheduling passes might change its schedule ๐ Use this option to control that behavior, bestie.-fselective-schedulingโ schedules instructions using the selective scheduling algorithm ๐ฏ It runs instead of the first scheduler pass.-fselective-scheduling2โ same selective scheduling algorithm, but this one runs instead of the second scheduler pass ๐ฏ-fsel-sched-pipeliningโ enables software pipelining of the innermost loops during selective scheduling ๐ This does nothing unless-fselective-schedulingor-fselective-scheduling2is turned on.-fsel-sched-pipelining-outer-loopsโ when pipelining loops during selective scheduling, this also pipelines the outer loops too ๐ช It has no effect unless-fsel-sched-pipeliningis turned on.
-fsemantic-interpositionโ okay so some object formats, like ELF, let the dynamic linker swap out symbols (that's "interposing") ๐ That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, because the function or variable might get changed out from under it. This is super useful for stuff like swapping in a debugging version of memory allocation functions, but it's expensive in terms of code quality ๐ฉ With-fno-semantic-interposition, the compiler assumes that if interposition does happen for functions, the overwriting function will have precisely the same semantics (and side effects). Same idea for variables: the constructor of the variable will be the same. This flag has no effect on functions explicitly declaredinline(where interposition is never allowed to change semantics), or on symbols explicitly declared weak.-fshrink-wrapโ emits function prologues only before the parts of the function that actually need them, instead of at the very top ๐ Enabled by default at-Oand higher.-fshrink-wrap-separateโ shrink-wraps the parts of the prologue and epilogue separately, so each part only runs when it's needed ๐งผ This is on by default, but it 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 the calls ๐พ This allocation only happens when it seems to give better code. It's always enabled by default on certain machines, usually the ones with no call-preserved registers to use instead. Enabled at levels-O2,-O3,-Os.-fcombine-stack-adjustmentsโ tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐ฅ Enabled by default at-O1and higher.-fipa-raโ lets the compiler use caller save registers for allocation if none of the called functions use those registers โจ That means you don't have 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 get compiled before it. It's enabled at levels-O2,-O3,-Os, however it's turned off if the generated code will be instrumented for profiling (-p, or-pg), or if the callee's register usage can't be known exactly (this happens on targets that don't expose prologues and epilogues in RTL) ๐ โโ๏ธ-fconserve-stackโ tries to minimize stack usage, even if the program ends up slower because of it ๐ข This option implies setting the large-stack-frame parameter to100and the large-stack-frame-growth parameter to400.
-ftree-reassocโ performs reassociation on trees ๐ณ Enabled by default at-O1and higher.-fcode-hoistingโ performs code hoisting, which tries to move the evaluation of expressions that run on all paths to the function exit as early as possible ๐ It's especially useful as a code size optimization, but it often helps code speed too. Enabled by default at-O2and higher.-ftree-preโ performs partial redundancy elimination (PRE) on trees ๐งน Enabled by default at-O2and-O3.-ftree-partial-preโ makes partial redundancy elimination (PRE) more aggressive ๐ค Enabled by default at-O3.-ftree-forwpropโ performs forward propagation on trees โก๏ธ Enabled by default at-O1and higher.-ftree-freโ performs full redundancy elimination (FRE) on trees ๐ The difference between FRE and PRE is that FRE only considers expressions that are computed on all paths leading to the redundant computation. That makes the analysis faster than PRE, though it exposes fewer redundancies. Enabled by default at-O1and higher.-ftree-phipropโ performs hoisting of loads from conditional pointers on trees ๐ช This pass is enabled by default at-O1and higher.-fhoist-adjacent-loadsโ okay so this one speculatively hoists loads from both branches of an if-then-else, but only when the loads grab adjacent spots in the same structure and the target architecture has a conditional move instruction ๐. It's on by default at-O2and higher โจ.-ftree-copy-propโ copy propagation on trees ๐ , which cleans up all the unnecessary copy operations so your code stops carrying dead weight ๐ซถ. Enabled by default at-O1and higher.-fipa-pure-constโ finds out which functions are pure or constant ๐ฎ. Enabled by default at-O1and higher.-fipa-referenceโ figures out which static variables never escape the compilation unit ๐ธ. Enabled by default at-O1and higher.-fipa-reference-addressableโ spots read-only, write-only and non-addressable static variables ๐ฆ. Enabled by default at-O1and higher.-fipa-stack-alignmentโ reduces stack alignment on call sites whenever it can ๐ง. Enabled by default.-fipa-ptaโ does interprocedural pointer analysis and interprocedural modification and reference analysis ๐ง .
๐ Heads up bestie: this one can eat excessive memory and compile-time on large compilation units. It is not enabled by default at any optimization level.
-fipa-profileโ propagates profile info across functions โจ. The 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-O1and higher.-fipa-modrefโ interprocedural mod/ref analysis, which figures out the side effects of functions (the memory locations they modify or reference) so the compiler can optimize across the function call boundary ๐. This flag is enabled by default at-O1and higher.-fipa-cpโ interprocedural constant propagation ๐ฅ. It checks when values passed to functions are constants and optimizes accordingly, and it can seriously boost performance if your app passes constants into functions ๐. This flag is enabled by default at-O2,-Osand-O3. It is also enabled by-fprofile-useand-fauto-profile.-fipa-cp-cloneโ function cloning to make interprocedural constant propagation stronger ๐งฌ. When enabled, it clones functions when an externally visible function can be called with constant arguments. Since this can create multiple copies of functions, it may significantly increase code size (see--param ipa-cp-unit-growth=value) ๐. This flag is enabled by default at-O3. It is also enabled by-fprofile-useand-fauto-profile.-fipa-bit-cpโ when enabled, does interprocedural bitwise constant propagation ๐. This flag is enabled by default at-O2and by-fprofile-useand-fauto-profile. It requires that-fipa-cpis enabled.-fipa-vrpโ when enabled, does interprocedural propagation of value ranges ๐. This flag is enabled by default at-O2. It requires that-fipa-cpis enabled.-fipa-icfโ Identical Code Folding for functions and read-only variables ๐ซง. It reduces code size, but it may disturb unwind stacks by swapping a function out for an equivalent one with a different name ๐. It works more effectively with link-time optimization enabled.
Although the behavior is similar to the Gold Linker's ICF optimization, GCC ICF works on different levels, so the optimizations are not the same. There are equivalences that only GCC finds and equivalences that only Gold finds ๐ค.
This flag is enabled by default at -O2 and -Os.
-flive-patching=levelโ controls GCC's optimizations so the output is suitable for live-patching ๐ฉน.
If the compiler's optimization uses a function's body (or info pulled from its body) to optimize or change another function, that other function is called an impacted function of the first one. So 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 inlining a function into its caller, cloning a function and changing its caller to call this new clone, or extracting a function's pureness/constness information to optimize its direct or indirect callers, etc.
Usually, the more IPA optimizations enabled, the larger the number of impacted functions for each function. To keep that number under control and make the list of impacted functions 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 as well.
-flive-patching=inline-clone disables the following optimization flags: -fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment -fipa-modref
inline-only-staticโ only enables inlining of static functions ๐งโโ๏ธ. As a result, when patching a static function, all its callers are impacted and so need to be patched as well.
In addition to all the flags that -flive-patching=inline-clone disables, -flive-patching=inline-only-static disables the following additional optimization 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-patching is not supported with link-time optimization (-flto) ๐
โโ๏ธ.
-fisolate-erroneous-paths-dereferenceโ detects paths that trigger erroneous or undefined behavior by dereferencing a null pointer ๐จ. It isolates those paths from the main control flow and turns the statement with the erroneous or undefined behavior into a trap. This flag is enabled by default at-O2and higher, and it depends on-fdelete-null-pointer-checksalso being enabled.-fisolate-erroneous-paths-attributeโ detects paths that trigger erroneous or undefined behavior because a null value is used in a way 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 may be enabled by-O2in the future.-ftree-sinkโ performs forward store motion on trees ๐ผ. This flag is enabled by default at-O1and higher.-ftree-bit-ccpโ performs sparse conditional bit constant propagation on trees and propagates pointer alignment information ๐. This pass only operates on local scalar variables and is enabled by default at-O1and higher, except for-Og. It requires that-ftree-ccpis enabled.-ftree-ccpโ performs sparse conditional constant propagation (CCP) on trees ๐งน. This pass only operates on local scalar variables and is enabled by default at-O1and higher.-fssa-backpropโ propagates info about how a value gets used back up the definition chain so the definitions can be simplified ๐. For example, this pass strips sign operations if the sign of a value never matters. This flag is enabled by default at-O1and higher.-fssa-phioptโ does 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 a switch into initializations from a scalar array ๐ญ. This flag is enabled by default at-O2and higher.-ftree-tail-mergeโ looks for identical code sequences, and when it finds them, replaces one with a jump to the other ๐ช. This optimization is known as tail merging or cross jumping. This flag is enabled by default at-O2and higher. The compilation time in this pass can be limited using themax-tail-merge-comparisonsparameter and themax-tail-merge-iterationsparameter.-ftree-dceโ dead code elimination (DCE) on trees ๐. This flag is enabled by default at-O1and higher.-ftree-builtin-call-dceโ conditional dead code elimination (DCE) for calls to built-in functions that may set "errno" but are otherwise free of side effects ๐ท. This flag is enabled 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 not loop forever ๐. This lets the compiler remove loops that otherwise have no side effects, without treating eventual endless looping as a side effect.
This option is enabled by default at -O2 for C++ with -std=c++11 or higher.
-ftree-dominator-optsโ runs a bunch of simple scalar cleanups (constant/copy propagation, redundancy elimination, range propagation and expression simplification) based on a dominator tree traversal ๐ซง. It also does jump threading (to reduce jumps to jumps). This flag is enabled by default at-O1and higher.-ftree-dseโ dead store elimination (DSE) on trees ๐ป. A dead store is a store into a memory location that gets overwritten by another store later without any intervening loads, so the earlier store can be deleted. This flag is enabled by default at-O1and higher.-ftree-chโ loop header copying on trees ๐ถ. This is beneficial because it increases the effectiveness of code motion optimizations, and it also saves one jump. This flag is enabled by default at-O1and higher. It is not enabled for-Os, since it usually increases code size.-ftree-loop-optimizeโ loop optimizations on trees ๐โจ. This flag is enabled by default at-O1and higher.-ftree-loop-linear,-floop-strip-mine,-floop-blockโ okay bestie, these three share one description ๐ฆ They all do loop nest optimizations, and it's literally the same as-floop-nest-optimizeโจ To use this code transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure is switched on ๐-fgraphite-identityโ this one is giving science experiment ๐งช It enables the identity transformation for graphite. For every SCoP, GCC generates the polyhedral representation and then transforms it back to gimple. Using-fgraphite-identitylets you check the costs or benefits of theGIMPLE -> GRAPHITE -> GIMPLEtransformation ๐ 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, and it is so iconic ๐ It's a generic loop nest optimizer based on the Pluto optimization algorithms, and it calculates a loop structure optimized for data-locality and parallelism ๐
โ ๏ธ Heads up: this option is experimental, so it's still a little spicy ๐ถ๏ธ
-floop-parallelize-allโ uses the Graphite data dependence analysis to identify loops that can be parallelized ๐งต It parallelizes all the loops that can be analyzed to not contain loop carried dependences, but it does this without checking that it is profitable to parallelize the loops ๐-ftree-coalesce-varsโ while GCC transforms the program out of the SSA representation, this one tries to reduce copying by coalescing versions of different user-defined variables, not just compiler temporaries ๐ซถ It may severely limit your ability to debug an optimized program compiled with-fno-var-tracking-assignments, so keep that in mind ๐ In the negated form, this flag prevents SSA coalescing of user variables. It's enabled by default if optimization is enabled, and it does very little otherwise ๐ธ-ftree-loop-if-convertโ attempts 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 โจ This is enabled by default if vectorization is enabled ๐ฆ-ftree-loop-distributionโ performs loop distribution, which can improve cache performance on big loop bodies and lets further loop optimizations, like parallelization or vectorization, take place ๐ For example, this loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
is transformed to:
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile ๐
-ftree-loop-distribute-patternsโ performs loop distribution of patterns that can be code generated with calls to a library ๐ This flag is 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 transformed into a call to memset zero. This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile ๐
-floop-interchangeโ performs loop interchange outside of graphite ๐ This flag can improve cache performance on loop nests and let further loop optimizations, like vectorization, take place ๐ง For example, this loop:
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
is transformed to:
for (int i = 0; i < N; i++)
for (int k = 0; k < N; k++)
for (int j = 0; j < N; j++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile ๐
-floop-unroll-and-jamโ applies unroll and jam transformations on feasible loops. In a loop nest, this unrolls the outer loop by some factor and fuses the resulting multiple inner loops ๐ซถ This flag is enabled by default at-O3. It is also enabled by-fprofile-useand-fauto-profile๐ฅ-ftree-loop-imโ performs loop invariant motion on trees ๐โโ๏ธ This pass only moves invariants that are hard to handle at RTL level, like function calls or operations that expand to nontrivial sequences of insns. With-funswitch-loops, it also moves operands of conditions that are invariant out of the loop, so loop unswitching can use just trivial invariantness analysis ๐ง The pass also includes store motion ๐-ftree-loop-ivcanonโ creates a canonical counter for the number of iterations in loops where figuring out that number needs complicated analysis ๐งฎ Later optimizations can then determine the number easily. It's especially useful in connection with unrolling ๐ธ-ftree-scev-cpropโ performs final value replacement. If a variable is modified in a loop in such a way that its value when exiting the loop can be determined using only its initial value and the number of loop iterations, GCC replaces uses of the final value with that computation, as long as it's sufficiently cheap โจ This reduces data dependencies and may allow further simplifications. It's enabled by default at-O1and higher ๐ฆ-fivoptsโ performs induction variable optimizations on trees, which means strength reduction, induction variable merging, and induction variable elimination ๐งโโ๏ธ-ftree-parallelize-loops=nโ parallelizes loops, aka splits their iteration space to run innthreads ๐งต This is only possible for loops whose iterations are independent and can be arbitrarily reordered. The optimization is only profitable on multiprocessor machines, for loops that are CPU-intensive, rather than loops constrained by things like memory bandwidth ๐ฅ๏ธ This option implies-pthread, so it's only supported on targets that have support for-pthread๐ซ-ftree-ptaโ performs function-local points-to analysis on trees. This flag is enabled by default at-O1and higher, except for-Og๐ซง-ftree-sraโ performs scalar replacement of aggregates ๐ This pass replaces structure references with scalars so structures don't get committed to memory too early. This flag is enabled by default at-O1and higher, except for-Og๐ท-fstore-mergingโ performs merging of narrow stores to consecutive memory addresses ๐ฆ It merges contiguous stores of immediate values that are narrower than a word into fewer, wider stores, which cuts down on the number of instructions. This is enabled by default at-O2and higher as well as-Os๐-ftree-terโ performs temporary expression replacement during theSSA->normalphase. Single use/single def temporaries get swapped out at their use location for their defining expression ๐ This results innon-GIMPLEcode, but it gives the expanders much more complex trees to work on, which leads to betterRTLgeneration ๐ง This is enabled by default at-O1and higher ๐-ftree-slsrโ performs straight-line strength reduction on trees ๐ It recognizes related expressions involving multiplications and replaces them with less expensive calculations when possible. This is enabled by default at-O1and higher ๐-ftree-vectorizeโ performs vectorization on trees ๐ This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified ๐ซถ-ftree-loop-vectorizeโ performs loop vectorization on trees ๐ This flag is enabled by default at-O2, and by-ftree-vectorize,-fprofile-use, and-fauto-profile๐-ftree-slp-vectorizeโ performs basic block vectorization on trees โญ This flag is enabled by default at-O2, and by-ftree-vectorize,-fprofile-use, and-fauto-profile๐ฅ-ftrivial-auto-var-init=choiceโ initializes automatic variables with either a pattern or zeroes, to boost the security and predictability of a program by preventing uninitialized memory disclosure and use ๐ GCC still considers an automatic variable that doesn't have an explicit initializer to be uninitialized, and-Wuninitializedand-Wanalyzer-use-of-uninitialized-valuewill still report warnings on those variables ๐ With this option, GCC also initializes any padding of automatic variables that have structure or union types to zeroes ๐งธ
The three values of choice are:
uninitializedโ doesn't initialize any automatic variables. This is C and C++'s default ๐patternโ initializes automatic variables with values that will likely turn logic bugs into crashes down the line, are easily recognized in a crash dump, and aren't values programmers can rely on for useful program semantics ๐ฆ The current value is a byte-repeatable pattern with the byte0xFE. The values used for pattern initialization might be changed in the future โ ๏ธzeroโ initializes automatic variables with zeroes ๐ซง
The default is uninitialized ๐
You can control this behavior for a specific variable by using the variable attribute "uninitialized" ๐ธ
-fvect-cost-model=modelโ okay bestie, this one lets you tweak the cost model GCC uses for vectorization ๐modelhas to be one ofunlimited,dynamic,cheap, orvery-cheapโจunlimitedโ the vectorized code path is assumed to be profitable, no cap ๐dynamicโ a runtime check guards the vectorized path, so it only switches on for iteration counts that will likely run faster than the original scalar loop ๐ฆcheapโ skips vectorizing loops where it would be cost prohibitive, like when it needs runtime checks for data dependence or alignment. Otherwise it's exactly the same asdynamic๐ธvery-cheapโ only vectorizes if the vector code would entirely replace the scalar code being vectorized. For example, if each vectorized iteration can only handle exactly four iterations of the scalar loop, this model only allows it if the scalar iteration count is known to be a multiple of four ๐
The default cost model depends on other optimization flags and is either dynamic or cheap ๐ง
-fsimd-cost-model=modelโ same energy, but for loops marked with the OpenMPsimddirective ๐modelshould beunlimited,dynamic, orcheap. Every value means exactly what it does in-fvect-cost-model, and by default, whatever cost model you set with-fvect-cost-modelis the one that gets used ๐ซถ-ftree-vrpโ turns on Value Range Propagation on trees โจ It's kinda like constant propagation, except instead of tracking single values, it tracks ranges of values. That lets the optimizers delete unnecessary range checks, like array bound checks and null pointer checks ๐ฅ Enabled by default at-O2and higher.
Null pointer check elimination only happens if -fdelete-null-pointer-checks is enabled ๐
-fsplit-pathsโ splits paths leading to loop backedges ๐ฆ This can improve dead code elimination and common subexpression elimination. Enabled by default at-O3and above ๐-fsplit-ivs-in-unrollerโ lets the compiler express the values of induction variables in later iterations of an unrolled loop using the value from the first iteration. This breaks up long dependency chains, which improves the efficiency of the scheduling passes ๐ธ
A combination of -fweb and CSE is often enough to get the same effect, ngl. But it's not reliable when the loop body is more complicated than a single basic block, and it 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 is enabled by default for PowerPC targets, but disabled by default everywhere else ๐-fpartial-inliningโ inlines parts of functions ๐ง This only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functionsโจ Enabled at levels-O2,-O3,-Os.-fpredictive-commoningโ performs predictive commoning, which means reusing computations (especially memory loads and stores) from previous iterations of loops ๐ฅ Enabled at level-O3. It's also turned on by-fprofile-useand-fauto-profile๐-fprefetch-loop-arraysโ if the target machine supports it, generates instructions to prefetch memory, so loops that access large arrays can run faster ๐ฆ Heads up, this may make the code better or worse, since the results are highly dependent on how the loops are structured in your source ๐ Disabled at level-Os.-fno-printf-return-valueโ stops GCC from swapping in constants for the known return values of formatted output functions likesprintf,snprintf,vsprintf, andvsnprintf(but notprintforfprintf) ๐ง That swap is a whole glow-up: when the arguments are constant, or known to be in a range that pins down the exact return value, GCC can optimize or even eliminate branches based on it ๐ For example, when-fprintf-return-valueis in effect, both the branch and the body of theifstatement (but not the call tosnprint) can be optimized away wheniis a 32-bit or smaller integer, because the return value is guaranteed to be at most 8 ๐คฏ
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations and yields the best results with -O2 and above. It works in tandem with the -Wformat-overflow and -Wformat-truncation options. The -fprintf-return-value option is enabled by default ๐
-fno-peephole,-fno-peephole2โ disables any machine-specific peephole optimizations ๐ธ The difference between the two is how they're implemented in the compiler. Some targets use one, some use the other, and a few use both ๐ซถ
-fpeephole is enabled by default. -fpeephole2 is enabled at levels -O2, -O3, -Os โจ
-fno-guess-branch-probabilityโ tells GCC not to guess branch probabilities using heuristics ๐
GCC uses heuristics to guess branch probabilities when profiling feedback (-fprofile-arcs) doesn't provide them. These heuristics are based on the control flow graph. If some branch probabilities are specified by __builtin_expect, the heuristics guess 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 complicated, so sometimes it helps to turn the heuristics off, so the effects of __builtin_expect are easier to understand ๐ง
You can also specify the expected probability of an expression with the __builtin_expect_with_probability built-in function โจ
The default is -fguess-branch-probability at levels -O, -O2, -O3, -Os ๐
-freorder-blocksโ reorders basic blocks in the compiled function to cut down on taken branches and improve code locality ๐ Enabled at levels-O1,-O2,-O3,-Osโจ-freorder-blocks-algorithm=algorithmโ picks the algorithm used for basic block reordering.algorithmcan besimple, which doesn't increase code size (except sometimes through 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 -O1, -Os, and stc at levels -O2, -O3 ๐
-freorder-blocks-and-partitionโ on top of reordering basic blocks to cut down on taken branches, this splits hot and cold basic blocks into separate sections of the assembly and.ofiles, for better paging and cache locality ๐
This 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 can 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 uses special subsections:.text.hotfor the most frequently executed functions, and.text.unlikelyfor unlikely executed ones. The linker does the reordering, so the object file format has to support named sections and the linker has to place them in a reasonable way ๐ง
This option isn't effective unless you either provide profile feedback (see -fprofile-arcs for details) or manually annotate functions with hot or cold attributes ๐ซถ
Enabled at levels -O2, -O3, -Os ๐ธ
-fstrict-aliasingโ lets the compiler assume the strictest aliasing rules that apply to the language being compiled ๐ฅ For C (and C++), this turns on optimizations based on the type of expressions. An object of one type is assumed to never reside at the same address as an object of a different type, unless the types are almost the same. For example,unsigned intcan aliasint, but notvoid*ordouble. 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 (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, access by taking the address, casting the resulting pointer and dereferencing the result has undefined behavior, even if the cast uses a union type, e.g.:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os ๐
-fipa-strict-aliasingโ controls whether the-fstrict-aliasingrules are applied across function boundaries ๐ Heads up: if multiple functions get inlined into a single function, the memory accesses are no longer considered to be crossing a function boundary ๐
This option is enabled by default and is only effective in combination with -fstrict-aliasing โจ
-falign-functions,-falign-functions=n,-falign-functions=n:m,-falign-functions=n:m:n2,-falign-functions=n:m:n2:m2โ bestie, this one lines up the start of every function ๐ It snaps the start to the next power-of-two that's>= n, and it's allowed to skip up tom-1bytes to get there. The payoff is that at least the firstmbytes of the function can be fetched by the CPU without crossing ann-byte alignment boundary. So cute โจ- If m isn't specified, it defaults to n.
- Examples:
-falign-functions=32aligns functions to the next 32-byte boundary,-falign-functions=24aligns to the next 32-byte boundary only if that can be done by skipping 23 bytes or less, and-falign-functions=32:7aligns to the next 32-byte boundary only if that can be done by skipping 6 bytes or less. - The second pair, n2:m2, gives you a secondary alignment ๐ For example,
-falign-functions=64:7:32:3aligns to the next 64-byte boundary if that can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if that can be done by skipping 2 bytes or less. If m2 isn't specified, it defaults to n2. - Some assemblers only support this flag when n is a power of two. In that case, n gets rounded up.
-fno-align-functionsand-falign-functions=1are equivalent and mean functions are not aligned.- If n isn't specified or is zero, the compiler uses a machine-dependent default. The maximum allowed n value is
65536. - Enabled at levels
-O2,-O3๐ฅ
-flimit-function-alignmentโ okay this one is giving restraint ๐ง If it's on, the compiler tries to avoid overaligning functions for no reason. It asks the assembler to align by the amount set with-falign-functions, but it won't skip more bytes than the size of the function.-falign-labels,-falign-labels=n,-falign-labels=n:m,-falign-labels=n:m:n2,-falign-labels=n:m:n2:m2โ this one aligns all branch targets to a power-of-two boundary ๐ธ Its parameters work the same way as-falign-functions.-fno-align-labelsand-falign-labels=1are equivalent and mean labels are not aligned.- If
-falign-loopsor-falign-jumpsapply and are greater than this value, their values get used instead. - If n isn't specified or is zero, you get a machine-dependent default that is very likely to be
1, which means no alignment. The maximum allowed n value is65536. - Enabled at levels
-O2,-O3๐
-falign-loops,-falign-loops=n,-falign-loops=n:m,-falign-loops=n:m:n2,-falign-loops=n:m:n2:m2โ aligns loops to a power-of-two boundary ๐ฆ If the loops run many times, the speed-up makes up for any execution of the dummy padding instructions. Literally worth it.- If
-falign-labelsis greater than this value, its value is used instead. - Parameters work the same as
-falign-functions.-fno-align-loopsand-falign-loops=1are equivalent and mean loops are not aligned. The maximum allowed n value is65536. - If n isn't specified or is zero, the compiler uses a machine-dependent default.
- Enabled at levels
-O2,-O3โจ
- If
-falign-jumps,-falign-jumps=n,-falign-jumps=n:m,-falign-jumps=n:m:n2,-falign-jumps=n:m:n2:m2โ aligns branch targets to a power-of-two boundary, but only for branch targets that can only be reached by jumping ๐ง In this case, no dummy operations need to run, so it's extra lowkey efficient.- If
-falign-labelsis greater than this value, its value is used instead. - Parameters are analogous to
-falign-functions.-fno-align-jumpsand-falign-jumps=1are equivalent and mean that loops are not aligned ๐ (yes, the page literally says loops there, even though this is the jumps flag, so keep that in mind). - If n isn't specified or is zero, the compiler uses a machine-dependent default. The maximum allowed n value is
65536. - Enabled at levels
-O2,-O3๐
- If
-fno-allocation-dceโ do not remove unused C++ allocations during dead code elimination. Keep those allocations, babe ๐-fallow-store-data-racesโ this one is a risky flex ๐ It lets the compiler do optimizations that might introduce new data races on stores, without proving that the variable can't be accessed by other threads at the same time. It doesn't touch optimization of local data.- It's safe to use if you already know global data won't be accessed by multiple threads.
- Examples of optimizations it enables include hoisting or if-conversions that might cause a value already in memory to be rewritten with that same value. That rewriting is safe in a single-threaded context but may be unsafe in a multi-threaded one.
- On some processors, if-conversions may be required to enable vectorization.
- Enabled at level
-Ofast๐ฅ
-funit-at-a-timeโ this one is kept around for compatibility reasons, so it has no effect ๐ Meanwhile-fno-unit-at-a-timeimplies-fno-toplevel-reorderand-fno-section-anchors.- Enabled by default.
-fno-toplevel-reorderโ don't reorder top-level functions, variables, and"asm"statements. They come out in the same order they appear in the input file ๐ With this on, unreferenced static variables are not removed. It's mainly there to support existing code that relies on a particular ordering. For new code, it's better to use attributes when possible.-ftoplevel-reorderis the default at-O1and higher, and also at-O0if-fsection-anchorsis explicitly requested.-fno-toplevel-reorderimplies-fno-section-anchors.
-fwebโ this one builds webs (the way they're commonly used for register allocation) and gives each web its own individual pseudo register ๐ฆ That lets the register allocation pass work on pseudos directly, and it also strengthens CSE, the loop optimizer, and the trivial dead code remover. The catch: it can make debugging impossible, since variables no longer stay in a "home register" ๐ญ- Enabled by default with
-funroll-loops.
- Enabled by default with
-fwhole-programโ assume the current compilation unit is the whole program being compiled ๐ All public functions and variables become static functions, exceptmainand anything merged by the attribute"externally_visible". Because of that, the interprocedural optimizers can go harder on them.
This option should not be used together with -flto. A linker plugin should give you safer and more precise info instead.
-flto[=n]โ this is the big one, bestie ๐ It runs the standard link-time optimizer. When you invoke it with source code, GCC 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 from those ELF sections and instantiated as if they were part of the same translation unit. Main character energy โจ
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 all the files in the same link with the same options, and specify those options at link time too. For example:
gcc -c -O2 -flto foo.c
gcc -c -O2 -flto bar.c
gcc -o myprog -flto -O2 foo.o bar.o
The first two invocations save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o. The final invocation reads the GIMPLE bytecode from foo.o and bar.o, merges the two files into a single internal image, and compiles the result as usual. Since both are merged into one image, all the interprocedural analyses and optimizations work across the two files as if they were a single one. So, for example, the inliner can inline functions in bar.o into functions in foo.o and vice-versa ๐ซถ
Another (simpler) way to enable link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
That generates bytecode for foo.c and bar.c, merges them into a single GIMPLE representation, and optimizes them as usual to produce myprog.
The important thing to keep in mind is that you need to use the GCC driver to perform the link step. GCC automatically performs link-time optimization if any of the objects involved were compiled with the -flto command-line option. You can always override that automatic decision by passing -fno-lto to the link command ๐
To make whole program optimization effective, you need to make certain whole program assumptions. The compiler needs to know which functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes information to the compiler about used and externally visible symbols. When the linker plugin isn't available, use -fwhole-program so the compiler can make those assumptions, which leads to more aggressive optimization decisions ๐
When a file is compiled with -flto and without -fuse-linker-plugin, the generated object file is larger than a regular one, because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). That 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 the 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 attempts to infer link-time options from the settings used to compile the input files.
If you don't pass an optimization level -O at link time, GCC uses the highest optimization level that was used when compiling the object files ๐
ngl, that's usually what you want. BUT ๐ it's generally ineffective to specify -O only at link time and not at compile time, and there are two reasons. First, compiling without optimization suppresses the compiler passes that gather the info needed for good link-time optimization ๐. Second, some early optimization passes can only run at compile time, not at link time. So do the optimizing at compile time, bestie ๐ซถ
There are some code generation flags that GCC keeps around when it generates bytecode, because they need to be used during the final link ๐ง Right now, the following options and their settings get taken from the first object file that explicitly specifies them: -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm and all the -m target flags ๐ธ
The options -fPIC, -fpic, -fpie and -fPIE get combined using this scheme ๐ฆ
-fPIC + -fpic = -fpic
-fPIC + -fno-pic = -fno-pic
-fpic/-fPIC + (no option) = (no option)
-fPIC + -fPIE = -fPIE
-fpic + -fPIE = -fpie
-fPIC/-fpic + -fpie = -fpie
Certain ABI-changing flags have to match in every compilation unit ๐ซ If you try to override them at link time with a conflicting value, it 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 ๐
Diagnostic options such as -Wstringop-overflow get passed through to the link stage, and their setting matches that of the compile step at function granularity ๐ This only matters for diagnostics emitted during optimization. Also, code transforms such as inlining can lead to warnings being enabled or disabled for regions of code that aren't consistent with the setting at compile time ๐
When you need to pass options to the assembler via -Wa or -Xassembler, make sure you either compile those translation units with -fno-lto, or consistently use the same assembler options on all translation units ๐งต You can alternatively specify assembler options at LTO link time too ๐ก
To enable debug info generation, you need to supply -g at compile time ๐ If any of the input files at link time were built with debug info generation enabled, the link will enable debug info generation as well ๐ Any elaborate debug info settings, like the DWARF level -gdwarf-5, need to be explicitly repeated on the linker command line, and mixing different settings across translation units is discouraged ๐ฉ
๐ If LTO encounters objects with C linkage declared with incompatible types in separate translation units that get linked together (undefined behavior according to ISO C99 6.2.7), a non-fatal diagnostic may be issued. The behavior is still undefined at run time. Similar diagnostics may be raised for other languages too.
Another feature of LTO is that you can apply interprocedural optimizations to files written in different languages ๐
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice that the final link is done with g++ to get the C++ runtime libraries, and -lgfortran is added to get the Fortran runtime libraries ๐ง In general, when mixing languages in LTO mode, you should use the same link command options 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 if you're using a linker with plugin support ๐ฆ To create static libraries suitable for LTO, use gcc-ar and gcc-ranlib instead of ar and ranlib. To show the symbols of object files with GIMPLE bytecode, use gcc-nm ๐ Those commands require that ar, ranlib and nm have been compiled with plugin support. At link time, use the flag -fuse-linker-plugin to make sure the library participates in the LTO optimization process ๐ฆ
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin enabled, the linker extracts the needed GIMPLE files from libfoo.a and passes them on to the running GCC so they become part of the aggregated GIMPLE image to be optimized โจ
If you're not using a linker with plugin support and/or don't enable the linker plugin, the objects inside libfoo.a get extracted and linked as usual, but they 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 require the presence of the whole program to operate ๐ If the program doesn't require any symbols to be exported, you can combine -flto and -fwhole-program to let the interprocedural optimizers use more aggressive assumptions, which may lead to better optimization opportunities ๐ Use of -fwhole-program is not needed when the linker plugin is active (see -fuse-linker-plugin).
The current implementation of LTO makes no attempt to generate bytecode that's portable between different types of hosts ๐ฅ๏ธ The bytecode files are versioned with a strict version check, so bytecode generated by one version of GCC does not work with an older or newer version of GCC ๐
๐ Link-time optimization does not work well with generation of debugging information on systems other than those using a combination of ELF and DWARF.
If you specify the optional n, the optimization and code generation done at link time is executed 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 specify -flto=jobserver to use GNU make's job server mode to determine the number of parallel jobs ๐ค This is 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's job server ๐
Use -flto=auto to use GNU make's job server, if available, or otherwise fall back to autodetection of the number of CPU threads present in your system ๐งต
-flto-partition=algโ Specify the partitioning algorithm used by the link-time optimizer ๐งฉ The value is either1to1to specify a partitioning mirroring the original source files, orbalancedto specify partitioning into equally sized chunks (whenever possible), ormaxto create a new partition for every symbol where possible. Specifyingnoneas an algorithm disables partitioning and streaming completely. The default value isbalanced. While1to1can be used as a workaround for various code ordering issues, themaxpartitioning is intended for internal testing only. The valueonespecifies that exactly one partition should be used, while the valuenonebypasses partitioning and executes the link-time optimization step directly from the WPA phase.-flto-compression-level=nโ This option sets the level of compression used for the intermediate language written to LTO object files, and it's only meaningful together with LTO mode (-flto) ๐๏ธ GCC currently supports two LTO compression algorithms. Forzstd, valid values are0(no compression) to19(maximum compression), whilezlibsupports values from0to9. Values outside this range are 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 option relies on plugin support in the linker, which is available ingoldor in GNU ld 2.21 or newer. This option enables the extraction of object files with GIMPLE bytecode out of library archives, which improves the quality of optimization by exposing more code to the link-time optimizer. This information specifies what symbols can be accessed externally (by a non-LTO object or during dynamic linking). Resulting code quality improvements on binaries (and shared libraries that use hidden visibility) are similar to-fwhole-program. See-fltofor a description of the effect of this flag and how to use it. This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker supporting 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 ๐ This makes them usable for both LTO linking and normal linking. This option is effective only when compiling with-fltoand is 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 linker plugin support for basic functionality. Additionally,nm,arandranlibneed to support linker plugins to allow a full-featured build environment (capable of building static libraries etc). GCC provides thegcc-ar,gcc-nmandgcc-ranlibwrappers to pass the right options to these tools. With non-fat LTO, makefiles need to be modified to use them. Note that modern binutils provide a plugin auto-load mechanism. 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
okay so this one is a post-register-allocation glow-up ๐ After register allocation and post-register allocation instruction splitting, GCC hunts for arithmetic instructions that set processor flags in a way that works like a comparison. If it can, it deletes the explicit comparison operation โจ
This pass only applies to certain targets that can't explicitly represent the comparison operation before register allocation is complete. So not every target gets this treatment ๐
Enabled at levels -O1, -O2, -O3, -Os.
-fcprop-registers
bestie, this one is giving copy-propagation energy ๐ฆ After register allocation and post-register allocation instruction splitting, GCC runs a copy-propagation pass. The goal is to reduce scheduling dependencies and, every once in a while, to eliminate the copy entirely ๐ธ
Enabled at levels -O1, -O2, -O3, -Os.
-fprofile-correction
Okay, so profiles collected from an instrumented binary for multi-threaded programs can come out inconsistent because some counter updates got missed ๐ญ With this option on, GCC uses heuristics to correct or smooth out those inconsistencies. By default, GCC throws an error message when it spots an inconsistent profile.
This option is enabled by -fauto-profile.
-fprofile-partial-training
Here's the vibe: with -fprofile-use, every part of the program that didn't run during the train run gets optimized aggressively for size instead of speed ๐ Sometimes it's not practical to train every possible hot path. For example, a program might contain functions made for specific hardware, and the training might not cover every hardware configuration the program runs on.
With -fprofile-partial-training, profile feedback gets ignored for every function that wasn't executed during the train run. Those functions get optimized as if they were compiled without profile feedback at all. This gives better performance when the train run isn't representative, but it also leads to significantly bigger code ๐
-fprofile-use, -fprofile-use=path
main character energy alert ๐ These turn on profile feedback-directed optimizations, plus the following optimizations. Most of them are only really worth it when profile feedback is available:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Before you can use this option, you must first generate profiling information. No skipping this step, bestie ๐ซถ
By default, GCC emits an error message if the feedback profiles don't match the source code. You can turn that error into a warning with -Wno-error=coverage-mismatch. Just know that this may result in poorly optimized code ๐ Also, by default, GCC emits a warning message if the feedback profiles don't exist at all (see -Wmissing-profile).
If you pass a path, GCC looks there for the profile feedback data files. See -fprofile-dir.
-fauto-profile, -fauto-profile=path
this one is sampling-based feedback-directed optimization, and it's obsessed with speed ๐ It turns on those sampling-based optimizations along with the following ones, which are mostly only worth it when profile feedback is around:
-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 information. If you leave it out, it defaults to fbdata.afdo in the current directory ๐ง
Making an AutoFDO profile data file means running your program with the perf utility on a supported GNU/Linux target system. For more info, check out https://perf.wiki.kernel.org/ โจ
Here's an example:
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Next, use the create_gcov tool to convert the raw profile data into a format GCC can actually use. You also have to hand this tool the unstripped binary for your program. See https://github.com/google/autofdo ๐
Here's that example:
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
Next up, the floating-point crew ๐งฎ These options are all about trading speed against correctness, so it's a vibe check on how precise you need your math to be. None of them turn on by themselves. You have to specifically enable each one you want ๐
-ffloat-store
This one tells GCC not to keep floating-point variables in registers, and it also blocks other options that might change whether a floating-point value comes from a register or from memory ๐
It prevents undesirable excess precision on machines like the 68000, where the floating registers (of the 68881) keep more precision than a "double" is supposed to have. The x86 architecture has a similar issue. For most programs, that extra precision is only a good thing, but a few programs depend on the precise definition of IEEE floating point. For those, use -ffloat-store after you've modified the code to store all the important intermediate computations into variables ๐ซถ
-fexcess-precision=style
this lets you have more say over excess precision on machines where floating-point operations happen in a format with more precision or range than the IEEE standard and interchange floating-point types ๐ฆ
By default, -fexcess-precision=fast is in effect. That means operations may be carried out in a wider precision than the types in your source if that would make the code faster. It's also unpredictable when rounding to the types in your source actually happens.
When compiling C, if you specify -fexcess-precision=standard, excess precision follows the rules in ISO C99. In particular, both casts and assignments make values round to their semantic types. (-ffloat-store only affects assignments, so this one is stricter ๐) This option is enabled by default for C if a strict conformance option such as -std=c99 is used. -ffast-math enables -fexcess-precision=fast by default no matter whether a strict conformance option is used.
-fexcess-precision=standard is not implemented for languages other than C. On x86, it has no effect if -mfpmath=sse or -mfpmath=sse+387 is specified. In the former case, IEEE semantics apply without excess precision. In the latter, rounding is unpredictable.
-ffast-math
this is the speed-at-all-costs option ๐๏ธ It sets -fno-math-errno, -funsafe-math-optimizations, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans, -fcx-limited-range and -fexcess-precision=fast.
It also causes the preprocessor macro __FAST_MATH__ to be defined โจ
โ ๏ธ This option is not turned on by any-Ooption besides-Ofast. It can produce incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, give you faster code for programs that don't need the guarantees of those specifications.
-fno-math-errno
Do not set errno after calling math functions that run as a single instruction, like sqrt. A program that relies on IEEE exceptions for math error handling might want this flag for speed while still keeping IEEE arithmetic compatibility ๐ธ
โ ๏ธ This option is not turned on by any -O option. It can produce incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, give you faster code for programs that don't need the guarantees of those specifications.
The default is -fmath-errno.
On Darwin systems, the math library never sets errno. So there's no reason for the compiler to think it might, and -fno-math-errno is the default there ๐
-funsafe-math-optimizations
this one lets the compiler do floating-point optimizations that (a) assume your arguments and results are valid and (b) might violate IEEE or ANSI standards ๐ When it's used at link time, it may pull in libraries or startup files that change the default FPU control word or do other similar optimizations.
โ ๏ธ This option is not turned on by any -O option. It can produce incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, give you faster code for programs that don't need the guarantees of those specifications.
It enables -fno-signed-zeros, -fno-trapping-math, -fassociative-math and -freciprocal-math.
The default is -fno-unsafe-math-optimizations.
-fassociative-math
This allows re-association of operands in series of floating-point operations. It breaks the ISO C and C++ language standards because it can change 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 don't use it when ordered comparisons are required.
This option requires that both -fno-signed-zeros and -fno-trapping-math be in effect. It also doesn't make much sense with -frounding-math. For Fortran, the option is automatically enabled when both -fno-signed-zeros and -fno-trapping-math are in effect.
The default is -fno-associative-math.
-freciprocal-math
This lets the compiler use the reciprocal of a value instead of dividing by that value, if doing so enables optimizations. For example, x / y can be replaced with x * (1/y), which is useful if (1/y) is subject to common subexpression elimination. Heads up though: this loses precision and increases the number of flops operating on the value ๐งฎ
The default is -fno-reciprocal-math.
-ffinite-math-only
This allows optimizations for floating-point arithmetic that assume your arguments and results are never NaNs or +-Infs ๐
โ ๏ธ This option is not turned on by any -O option. It can produce incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, give you faster code for programs that don't need the guarantees of those specifications.
The default is -fno-finite-math-only.
-fno-signed-zeros๐ โ okay so this one tells GCC it can do floating-point optimizations that don't care whether a zero is positive or negative. IEEE arithmetic treats+0.0and-0.0as distinct values, which normally stops GCC from simplifying things likex+0.0or0.0*x(even with-ffinite-math-only). With this flag, the sign of a zero result basically stops mattering ๐ซถ- The default is
-fsigned-zeros.
- The default is
-fno-trapping-math๐ฅ โ this one says "pretend floating-point operations can't cause user-visible traps." Those traps are division by zero, overflow, underflow, inexact result, and invalid operation. It only works if-fno-signaling-nansis in effect too. Turning it on can give you faster code if your program relies on "non-stop" IEEE arithmetic, for example โจ- The default is
-ftrapping-math.
- The default is
โ ๏ธ bestie, never turn this on through any -O option! It can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. Only use it on purpose ๐
-frounding-math๐ โ this one turns off 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. Use it for programs that change the FP rounding mode dynamically, or that might run with a non-default rounding mode. It also disables constant folding of floating-point expressions at compile time (since rounding mode can change those results) and arithmetic transformations that are unsafe with sign-dependent rounding modes ๐- The default is
-fno-rounding-math.
- The default is
๐งช this one is experimental, so it doesn't currently guarantee that every GCC optimization affected by rounding mode gets disabled. Future versions of GCC might give finer control over this using C99'sFENV_ACCESSpragma. This command-line option will be used to set the default state forFENV_ACCESS.
-fsignaling-nans๐ฆ โ compiles your code assuming IEEE signaling NaNs can cause user-visible traps during floating-point operations. Turning it on disables optimizations that might change the number of exceptions you can see with signaling NaNs. It also implies-ftrapping-math๐- This option causes the preprocessor macro
__SUPPORT_SNAN__to be defined. - The default is
-fno-signaling-nans.
- This option causes the preprocessor macro
๐งช also experimental! It doesn't currently guarantee that every GCC optimization affecting signaling NaN behavior gets disabled.
-fno-fp-int-builtin-inexact๐ง โ this stops the built-in functionsceil,floor,round, andtrunc(plus theirfloatandlong doublevariants) from generating code that raises theinexactfloating-point exception for noninteger arguments. ISO C99 and C11 let these functions raiseinexact, but ISO/IEC TS 18661-1:2014 (the C bindings to IEEE 754-2008, as integrated into ISO C2X) doesn't allow it, so this flag is the bestie for that vibe ๐- 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 if you use
-fno-fp-int-builtin-inexact, if the functions end up calling a library function, theinexactexception may still be raised if that library implementation doesn't follow TS 18661.
- The default is
-fsingle-precision-constant๐ โ treats floating-point constants as single precision, instead of quietly converting them to double-precision constants.-fcx-limited-range๐ธ โ when enabled, this says a range reduction step isn't needed when doing complex division. It also means there's no checking whether the result of a complex multiplication or division isNaN + I*NaN, and no attempt to rescue that situation. The default is-fno-cx-limited-range, but-ffast-mathturns it on โญ- This option controls the default setting of the ISO C99
CX_LIMITED_RANGEpragma. Nevertheless, the option applies to all languages.
- This option controls the default setting of the ISO C99
-fcx-fortran-rules๐ โ complex multiplication and division follow Fortran rules. Range reduction happens as part of complex division, but there's still no checking whether the result of a complex multiplication or division isNaN + I*NaN, and no attempt to rescue it.- 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, so be careful, bestie ๐
-fbranch-probabilities๐ โ after you run a program compiled with-fprofile-arcs, you can compile it a second time using-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 very dependent on the structure of the generated code, so you must use the same source code and the same optimization options for both compilations. See details about the file naming in-fprofile-arcs.- With
-fbranch-probabilities, GCC puts aREG_BR_PROBnote on eachJUMP_INSNandCALL_INSN, and those can be used to improve optimization. Right now they're only used in one place: inreorg.cc. Instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to figure out exactly which path is taken more often ๐ง - Enabled by
-fprofile-useand-fauto-profile.
- With
-fprofile-values๐ โ if combined with-fprofile-arcs, it adds code so that some data about values of expressions in the program gets gathered.- With
-fbranch-probabilities, it reads back the data gathered from profiling values of expressions, to use in optimizations. - Enabled by
-fprofile-generate,-fprofile-use, and-fauto-profile.
- With
-fprofile-reorder-functions๐ฆ โ function reordering based on profile instrumentation collects the first time each function executes, then orders those functions in ascending order.- Enabled with
-fprofile-use.
- Enabled with
-fvptโจ โ if combined with-fprofile-arcs, this option tells the compiler to add code that gathers information about values of expressions. With-fbranch-probabilities, it reads back that data and actually performs the 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.
- Enabled with
-frename-registers๐ โ tries to avoid false dependencies in scheduled code by using registers left over after register allocation. This optimization helps the most on processors with lots of registers. Depending on the debug information format the target uses, though, it can make debugging impossible, since variables no longer stay in a "home register" ๐- Enabled by default with
-funroll-loops.
- Enabled by default with
-fschedule-fusion๐ฅ โ performs a target-dependent pass over the instruction stream to schedule instructions of the same type together. The target machine can run them more efficiently when they're adjacent 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 transformation simplifies the control flow of the function, which lets other optimizations do a better job ๐- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-funroll-loops๐ โ unrolls loops whose number of iterations can be determined at compile time or upon entry to the loop.-funroll-loopsimplies-frerun-cse-after-loop,-fweb, and-frename-registers. It also turns on complete loop peeling (i.e. complete removal of loops with a small constant number of iterations). This option makes code larger, and it may or may not make it run faster ๐คท- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-funroll-all-loops๐ โ unrolls all loops, even if their number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly.-funroll-all-loopsimplies the same options as-funroll-loops.-fpeel-loops๐ โ peels loops that have enough information to show they don't roll much (from profile feedback or static analysis). It also turns on complete loop peeling (i.e. complete removal of loops with small constant number of iterations).- 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
-fmove-loop-stores๐ โ enables the loop store motion pass in the GIMPLE loop optimizer. This moves invariant stores to after the end of the loop, in exchange for carrying the stored value in a register across the iteration. Heads up: for this option to have an effect,-ftree-loop-imhas to be enabled as well.- 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, with duplicates of the loop on both branches (modified according to the result of the condition).- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-fversion-loops-for-strides๐ โ if a loop iterates over an array with a variable stride, it creates another version of the loop that assumes the stride is always one. For example:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
This is particularly useful for assumed-shape arrays in Fortran, where (for example) it allows better vectorization assuming contiguous accesses. This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile ๐ฆ
โจ OPTIONS โจ (continued, bestie) ๐
-ffunction-sections,-fdata-sectionsโ okay so these two put each function or data item into its own section in the output file ๐ฆ, but only if the target supports arbitrary sections. The name of the function (or the data item) decides what the section is called in the output file ๐ .
Use these on systems where the linker can do optimizations for locality of reference in the instruction space โจ. Most ELF object format systems have linkers like that ๐. On AIX, the linker rearranges sections (CSECTs) based on the call graph ๐ง. The performance impact varies, so it's not guaranteed to be a glow-up ๐.
Together with linker garbage collection (linker --gc-sections option), these options may lead to smaller statically-linked executables (after stripping) ๐.
On ELF/DWARF systems, these options do not degrade the quality of the debug information ๐. There could be issues with other object files/debug info formats ๐ฌ.
Only use these options when there are significant benefits from doing so, bestie ๐. When you specify them, the assembler and linker create larger object and executable files and are also slower ๐ข. These options affect code generation ๐ง . They prevent optimizations by the compiler and assembler from using relative locations inside a translation unit, since those locations are unknown until link time ๐. An example of such an optimization is relaxing calls to short call instructions.
-fstdarg-optโ this one optimizes the prologue of variadic argument functions based on how those arguments are actually used ๐.-fsection-anchorsโ this is giving "fewer address calculations" energy โจ. It tries to reduce the number of symbolic address calculations by using shared "anchor" symbols to reach nearby objects ๐ธ. On some targets, this can cut down on GOT entries and GOT accesses ๐ .
Here's the vibe. Say you compile this foo function:
static int a, b, c;
int foo (void) { return a + b + c; }
Normally it calculates the addresses of all three variables ๐ญ. But if you compile it with -fsection-anchors, it 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];
}
Not all targets support this option, so check before you get too attached ๐ฅบ.
-fzero-call-used-regs=choiceโ main character security energy ๐ก๏ธ. This zeroes the call-used registers at function return, which helps either mitigate Return-Oriented Programming (ROP) attacks or stop information leaking out through registers ๐.
The possible values of choice are the same as for the zero_call_used_regs attribute ๐. The default is skip ๐. You can control this for one specific function by using the function attribute zero_call_used_regs โจ.
--param name=valueโ okay this one is for the nerds who want to tweak the dials ๐๏ธ. GCC uses various constants to control how much optimization happens. For example, GCC won't inline functions that have more than a certain number of instructions ๐. You can change some of these constants on the command line with--param๐.
Heads up: the names of specific parameters, and what the values mean, are tied to the compiler's internals and can change without notice in future releases ๐จ.
To find the minimal, maximal, and default value of a parameter, use --help=param -Q options together ๐. The value is always an integer ๐ข. These are the name choices recognized for all targets:
predictable-branch-outcomeโ when a branch is predicted to be taken with a probability lower than this threshold (in percent), it counts as well predictable ๐ฎ.max-rtl-if-conversion-insnsโ RTL if-conversion tries to get rid of conditional branches around a block and swap them for conditionally executed instructions ๐. This sets the maximum number of instructions in a block that should be considered for if-conversion. The compiler also uses other heuristics to decide whether if-conversion is actually worth it ๐ง.max-rtl-if-conversion-predictable-costโ same if-conversion idea, but this sets the maximum permissible cost for the sequence that would be generated ๐ธ. The limit depends on whether the branch is statically determined to be predictable or not ๐. The units match the GCC internalseq_costmetric ๐. The compiler tries to pick a reasonable default for this using theBRANCH_COSTtarget macro ๐ฏ.max-crossjump-edgesโ the maximum number of incoming edges to consider for cross-jumping โ๏ธ. The algorithm used by-fcrossjumpingis O(N^2) in the number of edges coming into each block, so higher values mean more aggressive optimization ๐ฅ. The catch is that compile time goes up for probably a small gain in executable size ๐.min-crossjump-insnsโ the minimum number of instructions that must match at the end of two blocks before cross-jumping happens on them ๐ค. This value gets ignored when every instruction in the block being cross-jumped from is matched ๐ .max-grow-copy-bb-insnsโ the maximum code size expansion factor when copying basic blocks instead of jumping ๐ฆ. The expansion is measured relative to a jump instruction ๐ฆ.max-goto-duplication-insnsโ the maximum number of instructions to duplicate into a block that jumps to a computed goto ๐ช. To avoid O(N^2) behavior in a bunch of passes, GCC factors computed gotos early and unfactors them as late as possible ๐งฉ. Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsget unfactored ๐ซ.max-delay-slot-insn-searchโ the maximum number of instructions to look at when hunting for something to fill a delay slot ๐. Past this arbitrary number, the time saved by filling the slot is basically nothing, so GCC stops searching ๐. Higher values mean more aggressive optimization and longer compile times, for probably a small execution-time win โฑ๏ธ.max-delay-slot-live-searchโ when filling delay slots, this is the maximum number of instructions to consider while searching for a block with valid live register information ๐ต๏ธโโ๏ธ. Raising this arbitrary value means more aggressive optimization but longer compile times ๐ข. This parameter should be removed once the delay slot code is rewritten to maintain the control-flow graph ๐ง.max-gcse-memoryโ the approximate maximum amount of memory, in"kB", that can be allocated to do global common subexpression elimination ๐ง . If the optimization needs more memory than this, it just doesn't happen ๐ โโ๏ธ.max-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is bigger than this value for any expression, RTL PRE inserts or removes the expression ๐. That means it leaves partially redundant computations sitting in the instruction stream ๐ซ .max-pending-list-lengthโ the maximum number of pending dependencies the scheduler allows before it flushes the current state and starts over ๐งน. Big functions with few branches or calls can make these lists excessively large, which needlessly eats memory and resources ๐พ.max-modulo-backtrack-attemptsโ the maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop ๐. Larger values can exponentially increase compilation time, so be careful ๐.max-inline-functions-called-once-loop-depthโ the maximal loop depth of a call that the inline heuristics will consider when they try to inline all functions called once ๐.max-inline-functions-called-once-insnsโ the maximal estimated size of functions produced while inlining functions called once ๐.max-inline-insns-singleโ several parameters control the tree inliner in GCC, and this one sets the maximum number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will consider for inlining ๐ช. This only affects functions declaredinlineand methods implemented in a class declaration (C++) ๐.max-inline-insns-autoโ when you use-finline-functions(included in-O3), a whole bunch of functions that the compiler would otherwise skip get looked at for inlining ๐. Those functions get a different, more restrictive limit than functions declared inline, and that limit is set with--param max-inline-insns-auto๐.max-inline-insns-smallโ this is the bound applied to calls considered relevant with-finline-small-functions๐ค.max-inline-insns-sizeโ this is the bound applied to calls that are optimized for size ๐. A little growth may 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 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 ๐. That hint means it'll enable later optimizations too ๐.uninlined-thunk-insns,uninlined-thunk-timeโ same as--param uninlined-function-insnsand--param uninlined-function-time, but applied to function thunks ๐งต.inline-min-speedupโ when the estimated performance improvement of the caller plus callee runtime goes over this threshold (in percent), the function can be inlined no matter what the--param max-inline-insns-singleand--param max-inline-insns-autolimits say ๐. That's an absolute serve, no cap ๐.large-function-insns: okay so this is the limit for really big functions ๐. Once a function is bigger than this after inlining, inlining gets reined in by--param large-function-growth. It's mainly here to stop extreme compile times caused by the non-linear algorithms the back end uses ๐.large-function-growth: caps how much a large function can grow from inlining, in percent ๐. For example,100limits large function growth to 2.0 times the original size ๐ซถ.large-unit-insns: the threshold for a large translation unit ๐งฉ. Growth from inlining in units bigger than this is limited by--param inline-unit-growth, but for small units that cap can be way too tight ๐. Picture a unit with an inline function A and a function B that just calls A three times ๐ฆ. If B is tiny next to A, the unit growth is 300% and that inlining is still totally sane โจ. For huge units full of tiny inlineable functions, though, the overall growth limit keeps code size from exploding exponentially ๐ฅ. So for smaller units, the size gets bumped up to--param large-unit-insnsbefore--param inline-unit-growthgets applied ๐ธ.lazy-modules: the max number of C++ module files that can be open at once when lazy loading ๐.inline-unit-growth: caps the overall growth of the compilation unit from inlining ๐ฑ. For example,20limits 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 from interprocedural constant propagation ๐ข. For example,10limits 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 for 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,1000limits large stack frame growth to 11 times the original size ๐ญ.max-inline-insns-recursive,max-inline-insns-recursive-auto: the max number of instructions an out-of-line copy of a self-recursive inline function can grow into by doing recursive inlining ๐.--param max-inline-insns-recursiveapplies to functions declared inline. For functions that aren't declared inline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and--param max-inline-insns-recursive-autoapplies instead ๐ .max-inline-recursive-depth,max-inline-recursive-depth-auto: the max recursion depth used for recursive inlining ๐ช.--param max-inline-recursive-depthapplies to functions declared inline. For functions that aren't declared inline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and--param max-inline-recursive-depth-autoapplies instead ๐.min-inline-recursive-probability: recursive inlining is only worth it for functions that recurse deeply on average ๐. For functions with shallow recursion it can hurt, because it bloats the prologue or makes the function body more complicated for other optimizers ๐ค. When profile feedback is available (see-fprofile-generate), the real recursion depth can be guessed from the probability that a function recurses through a given call expression ๐ฎ. This parameter only allows inlining for call expressions whose probability is above the threshold (in percent) ๐.early-inlining-insns: the growth the early inliner is allowed to make ๐ฃ. Basically, it ups the amount of inlining for code with a large abstraction penalty ๐๏ธ.max-early-inliner-iterations: the limit on iterations of the early inliner ๐. This basically bounds how many nested indirect calls the early inliner can resolve. Deeper chains still get handled by late inlining ๐ฐ๏ธ.comdat-sharing-probability: the probability (in percent) that C++ inline functions with comdat visibility are shared across multiple compilation units ๐ค.modref-max-bases,modref-max-refs,modref-max-accesses: the max number of base pointers, references, and accesses stored for a single function by mod/ref analysis ๐๏ธ.modref-max-tests: the max number of tests the alias oracle can run to disambiguate memory locations using mod/ref information ๐ต๏ธ. This parameter ought to 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 to0disables the analysis completely ๐ซ.modref-max-escape-points: the max number of escape points modref tracks per SSA-name ๐.modref-max-adjustments: the max amount the access range can be enlarged during modref dataflow analysis ๐.profile-func-internal-id: controls whether the function internal id gets used in the profile database lookup ๐ชช. If the value is0, the compiler uses an id based on the function assembler name and filename ๐งพ. That makes old profile data more tolerant of source changes, like function reordering ๐ซง.min-vect-loop-bound: the min number of iterations below which loops aren't vectorized when-ftree-vectorizeis used ๐ซ. The number of iterations after vectorization has to be greater than this value for vectorization to happen ๐.
gcse-cost-distance-ratio: a scaling factor for the max distance an expression can be moved by GCSE optimizations โ๏ธ. Right now this is only supported in the code hoisting pass ๐. The bigger the ratio, the more aggressive the hoisting of simple expressions (the ones costing less thangcse-unrestricted-cost) ๐. Specifying0disables hoisting of simple expressions ๐ .gcse-unrestricted-cost: the cost, roughly measured as a single typical machine instruction, at which GCSE stops constraining how far an expression can travel ๐ฃ๏ธ. This is also only supported in the code hoisting pass ๐ช. The lower the cost, the more aggressive the hoisting gets ๐. Specifying0lets all expressions travel unrestricted distances ๐ฆ .max-hoist-depth: the depth of the dominator tree search for expressions to hoist ๐ณ. This exists to avoid quadratic behavior in the hoisting algorithm ๐ซ . A value of0doesn't limit the search, but it may slow compilation of huge functions ๐ข.max-tail-merge-comparisons: the max number of similar bbs a bb gets compared with ๐งโ๐คโ๐ง. It's used to avoid quadratic behavior in tree tail merging ๐งต.max-tail-merge-iterations: the max number of iterations of the pass over the function โฑ๏ธ. It's used to limit compilation time in tree tail merging ๐.store-merging-allow-unaligned: lets the store merging pass introduce unaligned stores if it's legal to do so ๐งฒ.max-stores-to-merge: the max number of stores the store merging pass will attempt to merge into wider stores ๐งฑ.max-store-chains-to-track: the max number of store chains tracked at the same time while trying to merge them into wider stores ๐.max-stores-to-track: the max number of stores tracked at the same time while trying to merge them into wider stores ๐.max-unrolled-insns: the max number of instructions a loop can have and still be unrolled ๐. If a loop gets unrolled, this parameter also decides how many times the loop code is unrolled ๐ฏ.max-average-unrolled-insns: the max number of instructions, biased by how probable their execution is, that a loop can have and still be unrolled ๐ฒ. If a loop gets unrolled, this parameter also decides how many times the loop code is unrolled ๐.max-unroll-times: the max number of unrollings of a single loop ๐.max-peeled-insns: the max number of instructions a loop can have and still be peeled ๐. If a loop gets peeled, this parameter also decides how many times the loop code is peeled ๐ง .max-peel-times: the max number of peelings of 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 min cost for an expression to count as expensive in loop invariant motion ๐ธ.min-loop-cond-split-prob: when FDO profile information is available, this sets the min threshold for the probability of a semi-invariant condition statement triggering a loop split โ๏ธ. It's the probability that makes the split worth it, so the loop gets split only when the condition is likely enough ๐.iv-consider-all-candidates-bound: the bound on the number of candidates for induction variables ๐งฎ. Below this bound, every candidate gets considered for each use in induction variable optimizations ๐ซถ. If there are more candidates than this, only the most relevant ones get considered, so the time complexity doesn't go quadratic ๐คโจ.iv-max-considered-uses๐ธ โ okay so the induction variable optimizations just give up ๐ญ when a loop has too many induction variable uses. Not worth the stress, bestie.iv-always-prune-cand-set-boundโจ โ if the candidate set is smaller than this value, GCC always tries to clean out unnecessary ivs from the set whenever it adds a new one. Very tidy behavior ๐ .avg-loop-niter๐ โ the average number of iterations of a loop.dse-max-object-size๐ง โ the max size (in bytes) of objects that dead store elimination tracks bytewise. Bigger numbers can mean longer compile times, so don't go wild ๐.dse-max-alias-queries-per-store๐ โ the max number of queries sent to the alias oracle per store. Higher values mean longer compile times, but they can also remove more dead stores ๐ฆ.scev-max-expr-size๐ โ a limit on how big expressions can get in the scalar evolutions analyzer. Huge expressions slow the analyzer down, lowkey a vibe killer ๐.scev-max-expr-complexity๐งฉ โ a limit on how complex expressions can be in the scalar evolutions analyzer. Complicated expressions slow it 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 the vectorizer can perform when doing loop versioning for alignment.vect-max-version-for-alias-checks๐ซถ โ the max number of run-time checks the vectorizer can perform when doing loop versioning for alias.vect-max-peeling-for-alignment๐ โ the max number of loop peels the vectorizer uses to improve access alignment. A value of-1means no limit at all, which is very main character energy ๐.max-iterations-to-track๐ต๏ธ โ the max number of loop iterations that the brute-force algorithm for analyzing a loop's iteration count will try to evaluate.hot-bb-count-fraction๐ฅ โ this is the denominator n of the fraction 1/n of the maximal execution count of a basic block in the entire program. A basic block has to hit at least that much to count as hot. The default is10000, so a basic block is hot if its execution count is greater than 1/10000 of the maximal execution count. A value of0means it is never considered hot. This one is used in non-LTO mode ๐ง .hot-bb-count-ws-permille๐ โ the number of most-executed permilles, from0to1000, of the profiled execution of the entire program. A basic block's execution count has to be part of that group to be considered hot. The default is990, meaning a basic block is hot if its execution count contributes to the upper 990 permilles, or 99.0%, of the profiled execution of the entire program. A value of0means it is never considered hot. This one is used in LTO mode ๐.hot-bb-frequency-fractionโญ โ this is the denominator n of the fraction 1/n of the execution frequency of a function's entry block. A basic block in that function needs at least that much to be considered hot. The default is1000, so a basic block counts as hot in a function if it runs more often than 1/1000 of the entry block's frequency. A value of0means it is never considered hot ๐ท.unlikely-bb-count-fraction๐ โ this is the denominator n of the fraction 1/n of the number of profiled runs of the entire program. A basic block's execution count has to be below that to be considered unlikely executed. The default is20, so a basic block is unlikely executed if it runs in fewer than 1/20, or 5%, of the program's runs. A value of0means it is always considered unlikely executed.max-predicted-iterations๐ฎ โ the max number of loop iterations GCC predicts statically. This is handy when a function has one loop with a known bound and another with an unknown bound. The known count gets predicted correctly, while the unknown count averages out to roughly 10. That makes the loop without bounds look artificially cold compared to the other one ๐ฅถ.builtin-expect-probability๐ฏ โ controls the probability of the expression having the specified value. This takes a percentage, so0through100๐ฏ.builtin-string-cmp-inline-length๐งต โ the max length of a constant string for a builtin string cmp call that's eligible for inlining.align-threshold๐ โ picks a fraction of the maximal execution frequency of a basic block in a function, used to decide whether that basic 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๐ฆ โ this value limits superblock formation once the given percentage of executed instructions is covered. It keeps code size from blowing up for no reason.
The tracer-dynamic-coverage-feedback parameter is only used when profile feedback is available. Real profiles, as opposed to statically estimated ones, are way less balanced, so the threshold can be set to a larger value.
tracer-max-code-growth๐ฑ โ stops tail duplication once code growth has reached the given percentage. Honestly this is a pretty artificial limit, since most duplicates get cleaned up later in cross jumping. So it can be set much higher than the desired code growth.tracer-min-branch-ratio๐ โ stops reverse growth when the reverse probability of the best edge is less than this threshold, given in percent.tracer-min-branch-probability,tracer-min-branch-probability-feedback๐ฆ โ stops forward growth if the best edge has a probability lower than this threshold.
Same deal as tracer-dynamic-coverage, there are two of these. tracer-min-branch-probability-feedback is used for compilation with profile feedback, and tracer-min-branch-probability is used for compilation without it. The feedback value needs to be more conservative (higher) so the tracer actually works ๐.
stack-clash-protection-guard-size๐ก๏ธ โ specifies the size of the operating system provided stack guard, as 2 raised to num bytes. Higher values may reduce the number of explicit probes. But a value larger than the operating system provided guard will leave code vulnerable to stack clash style attacks, which is a big no-no ๐ซ.stack-clash-protection-probe-interval๐งญ โ stack clash protection involves probing stack space as it gets allocated. This param controls the max distance between probes into the stack, as 2 raised to num bytes. Higher values may reduce the number of explicit probes. But a value larger than the operating system provided guard will leave code vulnerable to stack clash style attacks ๐ฌ.max-cse-path-length๐ค๏ธ โ the max number of basic blocks on a path that CSE considers.max-cse-insns๐งพ โ the max number of instructions CSE processes before it flushes.ggc-min-expand๐งน โ GCC uses a garbage collector to manage its own memory allocation. This param sets the minimum percentage by which the garbage collector's heap is allowed to expand between collections. Tuning it may improve compilation speed, but it has no effect on code generation.
The default is 30% + 70% * (RAM/1GB), with an upper bound of 100% when RAM is at least 1GB. If getrlimit is available, "RAM" means the smallest of actual RAM and RLIMIT_DATA or RLIMIT_AS. If GCC can't calculate RAM on a particular platform, the lower bound of 30% is used. Setting this parameter and ggc-min-heapsize to zero causes a full collection to occur at every opportunity. This is extremely slow, but it can be useful for debugging ๐ข.
ggc-min-heapsize๐ชฃ โ the minimum size of the garbage collector's heap before it bothers collecting garbage. The first collection happens after the heap expands byggc-min-expand% beyondggc-min-heapsize. Again, tuning this may improve compilation speed, and it has no effect on code generation.
The default is the smallest of RAM/8, RLIMIT_RSS, or a limit that tries to make sure RLIMIT_DATA or RLIMIT_AS aren't 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 particular platform, the lower bound is used. Setting this parameter very large effectively disables garbage collection. Setting this parameter and ggc-min-expand to zero causes a full collection to occur at every opportunity ๐๏ธ.
max-reload-search-insns๐ โ the max number of instructions reload should look backward through to find an equivalent register. Higher values mean more aggressive optimization, which makes compilation take longer for probably slightly better performance.max-cselib-memory-locations๐ง โ the max number of memory locations cselib should take into account. Higher values mean more aggressive optimization, which makes compilation take longer for probably slightly better performance.max-sched-ready-insns๐ โ the max number of instructions ready to be issued that the scheduler should consider at any given time during the first scheduling pass. Higher values mean more thorough searches, which makes compilation take longer for probably little benefit.max-sched-region-blocks๐งฑ โ the max number of blocks in a region that can be considered for interblock scheduling.max-pipeline-region-blocks๐ข โ the max number of blocks in a region that can be considered for pipelining in the selective scheduler.max-sched-region-insns๐บ โ the max number of insns in a region that can be considered for interblock scheduling.
okay so this is where the scheduler and optimizer settings get EXTRA ๐ bestie, you do NOT need to memorize all of these, but the vibes are immaculate โจ
max-pipeline-region-insnsโ the cap on how many insns a region can have before the selective scheduler even considers pipelining it ๐ธmin-spec-probโ the minimum chance (in percents) of reaching a source block that interblock speculative scheduling needs before it gets involved ๐ฆmax-sched-extend-regions-itersโ how many times the compiler can loop through the CFG trying to extend regions ๐ Set it to0and region extensions are disabled, no cap, no debate ๐ซmax-sched-insn-conflict-delayโ the biggest conflict delay an insn can have and still be eligible for speculative motion ๐sched-spec-prob-cutoffโ the least probability of speculation success (in percents) that has to be there before speculative insns actually get scheduled ๐sched-state-edge-prob-cutoffโ the minimum probability an edge needs before the scheduler bothers saving its state across it ๐sched-mem-true-dep-costโ the minimal distance (in CPU cycles) between a store and a load that are aiming at the same memory locations ๐งselsched-max-lookaheadโ the size of the lookahead window for selective scheduling. It's basically how deep the search goes when hunting for available instructions ๐selsched-max-sched-timesโ how many times one instruction can get scheduled during selective scheduling. This is the limit on how many iterations an instruction is allowed to be pipelined through ๐ฅselsched-insns-to-renameโ the number of best instructions on the ready list that get considered for renaming in the selective scheduler ๐sms-min-scโ the smallest stage count that the swing modulo scheduler will generate ๐max-last-value-rtlโ the biggest size, counted in RTLs, that the combiner can record in an expression as the last known value of a pseudo register ๐ซถmax-combine-insnsโ the maximum number of instructions the RTL combiner tries to combine at once ๐integer-share-limitโ small integer constants can share one data structure, which saves memory and makes the compiler faster โก This sets the biggest value a shared integer constant can have ๐ssp-buffer-sizeโ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectoris on ๐ก๏ธmin-size-for-stack-sharingโ the minimum size of variables that take part in stack slot sharing when you're not optimizing ๐ฆmax-jump-thread-duplication-stmtsโ the most statements a block can have and still be duplicated when threading jumps ๐งตmax-fields-for-field-sensitiveโ the maximum number of fields in a structure that gets treated in a field sensitive way during pointer analysis ๐ฌ
prefetch-latencyโ an estimate of how many instructions, on average, run before a prefetch finishes โณ The prefetch distance scales with this number. Crank it up and you might end up with fewer streams getting prefetched (seesimultaneous-prefetches) ๐ธsimultaneous-prefetchesโ the maximum number of prefetches that can run at the same time ๐โโ๏ธl1-cache-line-sizeโ the size of an L1 data cache line, in bytes ๐l1-cache-sizeโ the size of the L1 data cache, in kilobytes ๐l2-cache-sizeโ the size of the L2 data cache, in kilobytes ๐prefetch-dynamic-stridesโ whether the loop array prefetch pass should issue software prefetch hints for strides that aren't constant. Sometimes that's a win, but a non-constant stride can make it really hard to tell when the hints actually help ๐ค- Set it to
1if you want prefetch hints for non-constant strides โ - Set it to
0if you only want hints for strides that are known to be constant and belowprefetch-minimum-stride๐ซ
- Set it to
prefetch-minimum-strideโ the minimum constant stride, in bytes, before prefetch hints kick in. If the stride is below this threshold, no prefetch hints get issued ๐- This one is super useful for processors with hardware prefetchers ๐ฅ๏ธ Those two can clash with the software prefetchers, so if the hardware has a max stride it can handle, put that number here to make 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 ๐
destructive-interference-sizeandconstructive-interference-sizeโ these are the values behind the C++17 variables"std::hardware_destructive_interference_size"and"std::hardware_constructive_interference_size"๐- The destructive interference size is the minimum recommended offset between two independent objects that are accessed concurrently at the same time ๐ฅ
- The constructive interference size is the maximum recommended size of contiguous memory that gets accessed together ๐ค
- Usually both match the size of an L1 cache line for the target, in bytes ๐ For a generic target that covers a range of L1 cache line sizes, the constructive size is typically the small end of that range and the destructive size is the large end ๐
- > โ ๏ธ The destructive interference size is meant for layout, so it has ABI impact. Its default isn't expected to stay stable, and on some targets it changes with
-mtune. Using it somewhere ABI stability matters, like a library's public interface, is strongly discouraged ๐ญ If you really have to use it there, users can pin the value with this option. - The constructive interference size is way less sensitive, since it's usually only used in a
static_assertto check that a type fits in a cache line โ
See also -Winterference-size ๐
loop-interchange-max-num-stmtsโ the maximum number of stmts in a loop that can be interchanged ๐loop-interchange-stride-ratioโ the minimum ratio between the strides of two loops for interchange to be profitable ๐ฐmin-insn-to-prefetch-ratioโ the minimum ratio between the number of instructions and the number of prefetches needed to enable prefetching in a loop ๐งฎprefetch-min-insn-to-mem-ratioโ the minimum ratio between the number of instructions and the number of memory references needed to enable prefetching in a loop ๐งuse-canonical-typesโ whether the compiler should use the "canonical" type system. It should always be1, since that uses a more efficient internal mechanism for comparing types in C++ and Objective-C++ ๐ But if bugs in the canonical type system are causing compilation failures, set it to0to turn canonical types off ๐switch-conversion-max-branch-ratioโ switch initialization conversion won't create arrays bigger thanswitch-conversion-max-branch-ratiotimes the number of branches in the switch ๐ฆmax-partial-antic-lengthโ the maximum length of the partial antic set computed during the tree partial redundancy elimination optimization (-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 parameter caps the length of those sets to stop the runaway behavior. Setting it to0allows an unlimited set length ๐rpo-vn-max-loop-depthโ the maximum 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 get value-numbered optimistically, and the remaining ones don't ๐ซงsccvn-max-alias-queries-per-accessโ the maximum number of alias-oracle queries performed when looking for redundancies in loads and stores ๐ If this limit is hit, the search is aborted and the load or store is not considered redundant. The number of queries is algorithmically limited to the number of stores on all paths from the load to the function entry ๐งญ
ira-max-loops-numโ IRA uses regional register allocation by default ๐บ๏ธ If a function has more loops than this parameter's number, only that many of the most frequently executed loops form regions for regional register allocation ๐ฅira-max-conflict-table-sizeโ IRA uses a sophisticated algorithm to compress the conflict table, but huge functions can still need an excessive amount of memory for it ๐ 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 when deciding whether to move loop invariants (see-O3) ๐ง This is the number of available registers reserved for other purposes. The default is the best value found from numerous experiments ๐งชira-consider-dup-in-all-altsโ makes IRA consider matching constraints (duplicated operand numbers) heavily across all available alternatives for the preferred register class ๐ฏ- Set to
0and IRA only respects the matching constraint when it's the only available alternative with an appropriate register class ๐ โโ๏ธ - Otherwise, IRA checks every available alternative for the preferred register class, even after it has found a choice with an appropriate class, and respects the qualified matching constraint it found ๐ง โจ
- Set to
lra-inheritance-ebb-probability-cutoffโ okay so LRA tries to reuse values it reloaded into registers in later insns ๐ง โจ. That's called inheritance ๐ , and the EBB is the region used for it. This parameter sets the minimal fall-through edge probability, in percentage, that decides whether a BB gets added to an inheritance EBB in LRA ๐ฆ. The default was picked from tons of SPEC2000 runs on x86-64 ๐ธ.loop-invariant-max-bbs-in-loopโ loop invariant motion can be super expensive ๐ญ, both in compilation time and in the compile-time memory it needs, especially with massive loops ๐. Any loop with more basic blocks than this value just won't get loop invariant motion ๐.loop-max-datarefs-for-datadepsโ building data dependencies gets pricey for huge loops ๐ธ. This caps how many data references in a loop get considered for data dependence analysis ๐ซถ. The really big loops over the cap aren't handled by the optimizations that use loop data dependencies ๐ซ.max-vartrack-sizeโ sets a max number of hash table slots for variable tracking dataflow analysis on any function ๐ฅ. If you go over it with variable tracking at assignments enabled, the analysis for that function gets retried without it, after all the debug insns are removed from the function ๐. If it's still over the limit without debug insns, var tracking analysis is completely disabled for that function ๐ญ. Setting it to zero makes it unlimited โพ๏ธ.max-vartrack-expr-depthโ max recursion levels when mapping variable names or debug temporaries to value expressions ๐. It's a trade-off: compile time for more complete debug information ๐. Set it too low and value expressions that could be represented in debug info might end up unused ๐. Set it higher and the compiler may 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 (e.g. begin stmt markers) ๐ท๏ธ, so complexity doesn't explode at inlining or expanding to RTL ๐ฅ. If a function has more of those gimple stmts than the limit, they get dropped from the inlined copy of the function and from its RTL expansion โ๏ธ.min-nondebug-insn-uidโ nondebug insns start their uids at this value ๐ข. The range below it is reserved exclusively for debug insns created by-fvar-tracking-assignments๐ง. Debug insns can still get (non-overlapping) uids above it if that reserved range runs 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 pieces of an aggregate IPA-SRA tracks ๐งฉ. That also makes it 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) want to swap scalar parts of aggregates for uses of independent scalar variables โจ. These two cap the max size, in storage units, of an aggregate that's even considered for that ๐ฆ. The first applies when compiling for speed (sra-max-scalarization-size-Ospeed) ๐๏ธ, and the second applies when compiling for size (sra-max-scalarization-size-Osize) ๐ค.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 ๐. It only applies when using-fgnu-tm๐.graphite-max-nb-scop-paramsโ to avoid exponential effects in the Graphite loop transforms ๐๐ฅ, the number of parameters in a Static Control Part (SCoP) is bounded ๐ง. A value of zero lifts the bound ๐. A variable whose value is unknown at compile time and is defined outside a SCoP counts as a parameter of that SCoP ๐ซง.loop-block-tile-sizeโ loop blocking or strip mining, enabled with-floop-blockor-floop-strip-mine, strip mines each loop in the nest by a given number of iterations ๐ฐ. You can change the strip length usingloop-block-tile-size๐.ipa-jump-function-lookupsโ the number of statements visited during jump function offset discovery ๐.ipa-cp-value-list-sizeโ IPA-CP tries to track all possible values and types passed to a function's parameter so it can propagate them and perform devirtualization ๐ง .ipa-cp-value-list-sizeis the max number of values and types it stores per formal parameter of a function ๐.ipa-cp-eval-thresholdโ IPA-CP calculates its own score from its cloning profitability heuristics ๐งฎ and goes ahead with the cloning opportunities whose scores exceedipa-cp-eval-threshold๐.ipa-cp-max-recursive-depthโ the max depth of recursive cloning for a self-recursive function ๐.ipa-cp-min-recursive-probabilityโ recursive cloning only happens when the probability of the call being executed exceeds this parameter ๐ฒ.ipa-cp-profile-count-baseโ with-fprofile-use, IPA-CP looks at the measured execution count of a call graph edge at this percentage position in its histogram ๐. That's the basis it uses for its heuristics calculation ๐งช.ipa-cp-recursive-freq-factorโ the number of times interprocedural copy propagation expects recursive functions to call themselves ๐.ipa-cp-recursion-penaltyโ the percentage penalty recursive functions receive when they're evaluated for cloning ๐ฌ.ipa-cp-single-call-penaltyโ the percentage penalty functions get when they contain a single call to another function and are evaluated for cloning ๐.ipa-max-agg-itemsโ IPA-CP can also propagate a number of scalar values passed in an aggregate ๐ฆ. This controls the max number of those values per parameter ๐ข.ipa-cp-loop-hint-bonusโ when IPA-CP figures out that a cloning candidate would make the number of loop iterations known ๐, it adds a bonus ofipa-cp-loop-hint-bonusto that candidate's profitability score ๐.ipa-max-loop-predicatesโ the max number of different predicates IPA uses to describe when loops in a function have known properties ๐ท๏ธ.ipa-max-aa-stepsโ while analyzing function bodies, IPA-CP uses alias analysis to track values pointed to by function parameters ๐ต๏ธ. So it doesn't spend forever on huge functions, it gives up and considers all memory clobbered after examiningipa-max-aa-stepsstatements that modify memory ๐ซ .ipa-max-switch-predicate-boundsโ the max number of boundary endpoints of case ranges in a switch statement ๐. For a switch over this limit, IPA-CP won't construct the cloning cost predicate for the default case, which is used to estimate cloning benefit ๐ซ.ipa-max-param-expr-opsโ IPA-CP analyzes conditional statements that reference a function parameter to estimate cloning benefit for a certain constant value ๐ง. If the number of operations in a parameter expression goes overipa-max-param-expr-ops, the expression is treated as complicated and isn't handled by IPA analysis ๐ .lto-partitionsโ the desired number of partitions produced during WHOPR compilation ๐งฉ. The number should exceed the number of CPUs used for compilation ๐ป.lto-min-partitionโ the size of the minimal partition for WHOPR (in estimated instructions) ๐. This stops tiny programs from being split into too many partitions ๐.lto-max-partitionโ the size of the max partition for WHOPR (in estimated instructions) ๐. It gives an upper bound for the individual size of a partition ๐. 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 to consult for suggestions when C++ name lookup fails for an identifier ๐.sink-frequency-thresholdโ the max relative execution frequency (in percent) of the target block, compared to a statement's original block, that still allows statement sinking ๐ฌ. Bigger numbers mean more aggressive statement sinking ๐ช. A small positive adjustment is applied to statements with memory operands, since those are even more profitable to sink ๐ฐ.max-stores-to-sinkโ the max number of conditional store pairs that can be sunk ๐ณ๏ธ. Set it to0if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is disabled โ ๏ธ.case-values-thresholdโ the smallest number of different values for which a jump-table is better than a tree of conditional branches ๐ณ. If the value is0, the default for the machine is used ๐ค.jump-table-max-growth-ratio-for-sizeโ the max code size growth ratio when expanding into a jump table (in percent) ๐. This one is used when optimizing for size ๐ฆ.jump-table-max-growth-ratio-for-speedโ the max code size growth ratio when expanding into a jump table (in percent) ๐. This one is used when optimizing for speed ๐๏ธ.tree-reassoc-widthโ okay so this one sets the max number of instructions that get run in parallel in a reassociated tree ๐ณ. If it's set to a non-zero value, it overrides the target-dependent heuristics that would otherwise be used by default. ๐sched-pressure-algorithmโ this lets you pick between the two available versions of-fsched-pressure๐ฅ. Algorithm 1 is the original one, and it's the more likely to stop instructions from getting reordered ๐. Algorithm 2 was designed as a compromise between algorithm 1's pretty conservative vibe and the rather aggressive approach of the default scheduler โจ. It leans harder on having a regular register file and accurate register pressure classes. If you want the deets, check outhaifa-sched.ccin the GCC sources ๐.
The default choice depends on the target ๐ฏ.
max-slsr-cand-scanโ sets the max number of existing candidates that get considered when the compiler is looking 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 if you're using-fsanitize=address. If you want to turn global objects protection off, use--param asan-globals=0๐ โโ๏ธ.asan-stackโ enables buffer overflow detection for stack objects ๐ง. This is on by default when using-fsanitize=address. To disable stack protection, use--param asan-stack=0option ๐.asan-instrument-readsโ enables buffer overflow detection for memory reads ๐. It's on by default when using-fsanitize=address. To turn off memory reads protection, use--param asan-instrument-reads=0๐ซถ.asan-instrument-writesโ enables buffer overflow detection for memory writes โ๏ธ. Again, this is on by default when using-fsanitize=address. To disable memory writes protection, use--param asan-instrument-writes=0option ๐.asan-memintrinโ enables detection for built-in functions ๐ ๏ธ. This is on by default with-fsanitize=address. To turn off built-in functions protection, use--param asan-memintrin=0๐.asan-use-after-returnโ enables detection of use-after-return, which is kind of a big deal ๐ญ. It's on by default when you use the-fsanitize=addressoption. To disable it, use--param asan-use-after-return=0๐.
Note: By default the check is disabled at run time ๐. If you want to turn it on, add"detect_stack_use_after_return=1"to the environment variableASAN_OPTIONSโจ.
asan-instrumentation-with-call-thresholdโ if the number of memory accesses in the function being instrumented is greater than or equal to this number, the compiler 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 with-fsanitize=hwaddress, but it's off by default with-fsanitize=kernel-hwaddress. To turn stack instrumentation off, use--param hwasan-instrument-stack=0, and to turn it back on, use--param hwasan-instrument-stack=1๐.hwasan-random-frame-tagโ when you're using stack instrumentation, tags for stack variables get decided using a deterministic sequence that begins at a random tag for each frame ๐ฒ. If this parameter isn't set, the tags use the same sequence but start from 1 ๐ข. It's enabled by default for-fsanitize=hwaddressand unavailable for-fsanitize=kernel-hwaddress๐ซ. To disable it, use--param hwasan-random-frame-tag=0๐ .hwasan-instrument-allocasโ enables hwasan instrumentation of dynamically sized stack-allocated variables ๐ท. This is on by default with-fsanitize=hwaddressand off by default with-fsanitize=kernel-hwaddress. To turn off instrumentation of these variables, use--param hwasan-instrument-allocas=0, and to turn it on, use--param hwasan-instrument-allocas=1๐ฆ.hwasan-instrument-readsโ enables hwasan checks on memory reads ๐๏ธ. Read instrumentation is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To stop checking memory reads, use--param hwasan-instrument-reads=0๐ โโ๏ธ.hwasan-instrument-writesโ enables hwasan checks on memory writes ๐. Write instrumentation is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To stop checking memory writes, use--param hwasan-instrument-writes=0๐ธ.hwasan-instrument-mem-intrinsicsโ enables hwasan instrumentation of builtin functions ๐งฐ. This is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress. To turn off instrumentation of builtin functions, use--param hwasan-instrument-mem-intrinsics=0๐ซ .use-after-scope-direct-emission-thresholdโ if the size of a local variable in bytes is smaller than or equal to this number, the compiler directly poisons (or unpoisons) shadow memory instead of using run-time callbacks ๐งช.tsan-distinguish-volatileโ emits special instrumentation for accesses to volatiles ๐.tsan-instrument-func-entry-exitโ emits instrumentation calls to__tsan_func_entry()and__tsan_func_exit()๐ช.max-fsm-thread-path-insnsโ the max number of instructions to copy when duplicating blocks on a finite state automaton jump thread path ๐งต.max-fsm-thread-lengthโ the max number of basic blocks on a jump thread path ๐งถ.threader-debugโthreader-debug=[none|all]turns on verbose dumping of the threader solver ๐ฃ๏ธ.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. The options arestatic,dynamic,guided,auto, andruntime๐๏ธ.parloops-min-per-threadโ the minimum number of iterations per thread of an innermost parallelized loop where the parallelized 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 max depth of recursion when querying properties of SSA names in things like fold routines ๐. One level of recursion corresponds to following a use-def chain ๐.max-speculative-devirt-maydefsโ the max number of may-defs analyzed when looking for a must-def that specifies the dynamic type of an object invoking a virtual call that might be devirtualized speculatively ๐ต๏ธโโ๏ธ.max-vrp-switch-assertionsโ the max number of assertions to add along the default edge of a switch statement during VRP ๐.evrp-sparse-thresholdโ the max number of basic blocks before EVRP switches to a sparse cache ๐๏ธ.evrp-modeโ specifies the mode Early VRP should operate in ๐๏ธ.vrp1-modeโ specifies the mode VRP pass 1 should operate in 1๏ธโฃ.vrp2-modeโ specifies the mode VRP pass 2 should operate in 2๏ธโฃ.ranger-debugโ specifies the type of debug output to be issued for ranges ๐.evrp-switch-limitโ specifies the max number of switch cases before EVRP ignores a switch ๐.unroll-jam-min-percentโ the minimum percentage of memory references that must be optimized away for the unroll-and-jam transformation to be considered profitable ๐ฐ.unroll-jam-max-unrollโ the max number of times the outer loop should be unrolled by the unroll-and-jam transformation ๐.max-rtl-if-conversion-unpredictable-costโ the max permissible cost for the sequence that the RTL if-conversion pass would generate for a branch that's considered unpredictable ๐.max-variable-expansions-in-unrollerโ if-fvariable-expansion-in-unrolleris used, this is the max number of times an individual variable gets expanded during loop unrolling ๐.partial-inlining-entry-probabilityโ the max probability of the entry BB of a split region (as a percent relative to the entry BB of the function) that still lets partial inlining happen ๐ฒ.max-tracked-strlensโ the max number of strings the strlen optimization pass will track string lengths for ๐งต.gcse-after-reload-partial-fractionโ the threshold ratio for performing partial redundancy elimination after reload โ๏ธ.gcse-after-reload-critical-fractionโ the threshold ratio of critical edges' execution count that permits performing redundancy elimination after reload ๐งฎ.max-loop-header-insnsโ the max number of insns in a loop header duplicated by the copy loop headers pass ๐.vect-epilogues-nomaskโ enables loop epilogue vectorization using a smaller vector size ๐ง.vect-partial-vector-usageโ controls when the loop vectorizer considers using partial vector loads and stores as an alternative to falling back to scalar code ๐ช. The values are:0โ the vectorizer never uses partial vector loads and stores ๐ซ.1โ partial vector loads and stores are allowed if vectorization removes the need for the code to iterate ๐.2โ partial vector loads and stores are allowed in all loops ๐ซ.
This parameter only has an effect on targets that support partial vector loads and stores ๐ฏ.
vect-inner-loop-cost-factorโ the max factor the loop vectorizer applies to the cost of statements in an inner loop, relative to the loop being vectorized ๐ช. The factor applied is the max of the estimated number of iterations of the inner loop and this parameter. The default value of this parameter is50๐ฏ.avoid-fma-max-bitsโ the max number of bits for which we avoid creating FMAs ๐ โโ๏ธ.sms-loop-average-count-thresholdโ a threshold on the average loop count considered by the swing modulo scheduler ๐ข.sms-dfa-historyโ okay so this one sets how many cycles the swing modulo scheduler looks at when it checks for conflicts using the DFA ๐graphite-allow-codegen-errorsโ decides whether codegen errors should be ICEs when-fcheckingis on ๐sms-max-ii-factorโ a tuning factor for the upper bound the swing modulo scheduler uses when it schedules a loop ๐lra-max-considered-reload-pseudosโ the max number of reload pseudos that get considered while spilling a non-reload pseudo ๐ฆmax-pow-sqrt-depthโ the max depth of sqrt chains you're allowed to use when synthesizing exponentiation by a real constant ๐ธmax-dse-active-local-storesโ caps how many active local stores RTL dead store elimination can have at once ๐งนasan-instrument-allocasโ turns on ASan protection for allocas and VLAs ๐ก๏ธmax-iterations-computation-costโ the bound on how expensive an expression can be when GCC computes the number of iterations ๐max-isl-operationsโ the max number of isl operations, where0means unlimited โพ๏ธgraphite-max-arrays-per-scopโ the max number of arrays allowed per scop ๐ฆmax-vartrack-reverse-op-sizeโ the max size of a loc list for which reverse ops should get added ๐งfsm-scale-path-stmtsโ a scale factor applied to the number of statements in a threading path, compared against the number of (scaled) blocks ๐งตuninit-control-dep-attemptsโ the max number of nested calls used to search for control dependencies during uninitialized variable analysis ๐fsm-scale-path-blocksโ a scale factor applied to the number of blocks in a threading path, compared against the number of (scaled) statements ๐sched-autopref-queue-depthโ a control flag for the hardware autoprefetcher scheduler model. It sets how many lookahead cycles the model peeks into, and at' 'it only turns on the instruction sorting heuristic ๐ซถloop-versioning-max-inner-insnsโ the max number of instructions an inner loop can have before the loop versioning pass decides it's too big to copy ๐loop-versioning-max-outer-insnsโ the max number of instructions an outer loop can have before the loop versioning pass decides it's too big to copy, not counting any instructions in inner loops that directly benefit from versioning ๐ssa-name-def-chain-limitโ the max number of SSA_NAME assignments GCC follows when figuring out a property of a variable, like its value. This limits how many iterations or recursive calls GCC makes when optimizing certain statements or checking their validity before it issues diagnostics ๐store-merging-max-sizeโ the max size of a single store merging region, in bytes ๐hash-table-verification-limitโ the number of elements that get hash table verification done for each searched element ๐งmax-find-base-term-valuesโ the max number of VALUEs handled during a singlefind_base_termcall ๐ซanalyzer-max-enodes-per-program-pointโ the max number of exploded nodes per program point inside the analyzer. Once it's hit, analysis of that point stops ๐analyzer-max-constraintsโ the max number of constraints per state ๐analyzer-min-snodes-for-call-summaryโ the min number of supernodes inside a function before the analyzer bothers summarizing its effects at call sites ๐analyzer-max-enodes-for-full-dumpโ the max depth of exploded nodes that can show up in a dot dump before it switches to a less verbose format ๐๏ธanalyzer-max-recursion-depthโ the max number of times a callsite can show up in a call stack inside the analyzer. Once that's reached, analysis of a call that would recurse deeper gets terminated ๐analyzer-max-svalue-depthโ the max depth of a symbolic value before the analyzer approximates it as unknown โanalyzer-max-infeasible-edgesโ the max number of infeasible edges to reject before a diagnostic gets declared infeasible ๐ซgimple-fe-computed-hot-bb-thresholdโ the number of executions a basic block needs before it counts as hot. This parameter is only used in the GIMPLE FE ๐ฅanalyzer-bb-explosion-factorโ the max number of'after supernode'exploded nodes per supernode inside the analyzer, before analysis gets terminated ๐ฅranger-logical-depthโ the max depth of logical expression evaluation that ranger will look through when it evaluates outgoing edge ranges ๐งrelation-block-limitโ the max number of relations the oracle will register in a basic block ๐คopenacc-kernelsโ picks the mode for handling OpenACCkernelsconstructs ๐- With
--param=openacc-kernels=decompose, OpenACCkernelsconstructs get decomposed into parts, a sequence of compute constructs, and each one is handled individually. This is work in progress. - With
--param=openacc-kernels=parloops, OpenACCkernelsconstructs are handled en bloc by the parloops pass. This is the current default.
- With
openacc-privatizationโ picks the mode for OpenACC privatization diagnostics, which show up under-fopt-info-omp-noteand applicable-fdump-tree-*-details๐- With
--param=openacc-privatization=quiet, nothing gets diagnosed. This is the current default. - With
--param=openacc-privatization=noisy, diagnostics get shown.
- With
The following choices of name are available on AArch64 targets: ๐
aarch64-sve-compare-costsโ when vectorizing for SVE, GCC considers using "unpacked" vectors for smaller elements, and it uses the cost model to pick the cheapest approach. It also uses the cost model to choose between SVE and Advanced SIMD vectorization.
Using unpacked vectors means storing smaller elements in larger containers and accessing elements with extending loads and truncating stores. โจ
aarch64-float-recp-precisionโ the number of Newton iterations used to calculate the reciprocal for thefloattype. The precision of division is proportional to this param when division approximation is enabled. The default value is1. ๐ฆaarch64-double-recp-precisionโ the number of Newton iterations used to calculate the reciprocal for thedoubletype. The precision of division is proportional to this param when division approximation is enabled. The default value is2. ๐ธaarch64-autovec-preferenceโ forces an ISA selection strategy for auto-vectorization. It accepts values from0to4, inclusive. ๐0โ use the default heuristics1โ use only Advanced SIMD for auto-vectorization2โ use only SVE for auto-vectorization3โ use both Advanced SIMD and SVE, and prefer Advanced SIMD when the costs are deemed equal4โ use both Advanced SIMD and SVE, and prefer SVE when the costs are deemed equal- The default value is
0.
aarch64-loop-vect-issue-rate-nitersโ some AArch64 CPU tuning tries to weigh both latencies and issue rates when deciding whether a loop should be vectorized with SVE, vectorized with Advanced SIMD, or not vectorized at all. If this parameter is set ton, GCC won't use this heuristic for loops known to execute in fewer thannAdvanced SIMD iterations. ๐๏ธ
๐ง Program Instrumentation Options ๐ง
GCC supports a bunch of command-line options that tack run-time instrumentation onto the code it normally generates ๐ . One reason you'd instrument is to collect profiling stats so you can find program hot spots, do code coverage analysis, or run profile-guided optimizations ๐ฅ. Another kind of instrumentation adds run-time checks that catch programming errors like invalid pointer dereferences or out-of-bounds array accesses, plus deliberately hostile attacks like stack smashing or C++ vtable hijacking ๐ก๏ธ. There's also a general hook that can be used to build other forms of tracing or function-level instrumentation for debugging or program analysis ๐ซถ.
-p,-pgโ generates extra code that writes profile information for the analysis programprof(with-p) orgprof(with-pg) ๐. You have to use this option when compiling the source files you want data about, and you have to use it when linking too โ ๏ธ.
You can use the function attribute "no_instrument_function" to skip profiling of individual functions when compiling with these options ๐.
-fprofile-arcsโ adds code so that program flow arcs get instrumented ๐. While the program runs, it records how many times each branch and call gets executed, and how many times each one is taken or returns. On targets that support constructors with priority, profiling handles constructors, destructors, and C++ constructors and destructors of classes used as the type of a global variable properly ๐.
When the compiled program exits, it saves this data to a file called auxname.gcda for each source file ๐พ. The data can be used for profile-directed optimizations (-fbranch-probabilities) or for test coverage analysis (-ftest-coverage). Each object file's auxname comes from the name of the output file, if one is explicitly specified and it isn't the final executable. Otherwise it's the basename of the source file. In both cases, any suffix gets removed. For example, foo.gcda for input file dir/foo.c, or dir/foo.gcda for output file specified as -o dir/foo.o ๐ง.
Heads up: if a command line links source files directly, the matching .gcda files get prefixed with the unsuffixed name of the output file. So "gcc a.c b.c -o binary" would generate binary-a.gcda and binary-b.gcda files ๐ฏ.
--coverageโ this is what you use to compile and link code instrumented for coverage analysis ๐งช. It's a synonym for-fprofile-arcs -ftest-coveragewhen compiling, and for-lgcovwhen linking. Check the docs for those options for more details ๐.- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, add the extra-ftest-coverageoption. You don't need to profile every source file in a program ๐.
- Compile the source files with
- Step 1: Compile your source files with
-fprofile-abs-pathtoo, so the.gcnofiles get absolute path names. That waygcovcan find the right sources even when your builds run from different working directories. ๐ - Step 2: Link your object files with
-lgcovor-fprofile-arcs. The second one already brings in the first, so you're covered either way. ๐ - Step 3: Run your program on a representative workload to collect the arc profile info. You can repeat this as many times as you want ๐. You can even run several instances at once. As long as the file system supports locking, the data files get updated correctly ๐. Unless you're using a strict ISO C dialect option,
forkcalls are detected and handled properly, so nothing gets double counted ๐.
Also, you can recompile an object file multiple times and its .gcda file will merge, as long as the source file and compiler options haven't changed ๐งฉ.
- Step 4: For profile-directed optimizations, compile your source files again with the same optimization and code generation options, plus
-fbranch-probabilities๐ฏ. - Step 5: For test coverage analysis, use
gcovto turn the.gcnoand.gcdafiles into human-readable info. Check the gcov documentation for the full scoop ๐.
With -fprofile-arcs, GCC builds a program flow graph for each function in your program, then finds a spanning tree for that graph ๐ณ. Only the arcs not on the spanning tree need instrumenting, and GCC adds code to count how many times those arcs run ๐ข. If an arc is the only exit or the only entrance to a block, the counting code can go right into that block. Otherwise, GCC has to make a new basic block just to hold it ๐งฑ.
-ftest-coverageโ Okay, this one is giving coverage โจ. It makes a notes file that thegcovcode-coverage utility can use to show how much of your program is covered. Each source file's notes file is namedauxname.gcno. Scroll up to-fprofile-arcsfor whatauxnamemeans and how to actually generate the test coverage data ๐. Heads up: your coverage data matches your source files way more closely if you don't optimize ๐.-fprofile-abs-pathโ This one turns relative source file names into absolute path names in the.gcnofiles ๐บ๏ธ. It's the same perk as before:gcovcan find the correct sources in projects where compilations happen from different working directories ๐.-fprofile-dir=pathโ This sets the directory where GCC looks for profile data files, and that path can be absolute or relative ๐. It only affects profile data generated by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-use,-fbranch-probabilities, and their related options ๐. By default the directory is the current one, so the profile data file sits right next to the object file ๐ . If the object file name isn't an absolute path, GCC mangles the absolute path of thesourcename.gcdafile and uses that as the.gcdafile name, so names don't clash ๐. Check out-fprofile-arcsfor the full file naming deets, and also see the similar option-fprofile-note๐.
If you're running an executable in a massively parallel environment, it's smart to save profiles into different folders. You can do that by using these variables in path, which get exported at run-time:
%pโ the process ID ๐%q{VAR}โ the value of the environment variableVAR๐
-fprofile-generate,-fprofile-generate=pathโ This turns on the options you usually need for instrumenting an app, so it can produce a profile for later recompiles with profile feedback based optimization ๐ ๏ธ. You have to use-fprofile-generatewhen compiling and when linking, no skipping ๐จ. It enables-fprofile-arcs,-fprofile-values,-finline-functions, and-fipa-bit-cp๐ . If you give it apath, GCC looks there for the profile feedback data files. See-fprofile-dirfor the details ๐. When you're ready to optimize based on what got collected, use-fprofile-use๐.-fprofile-info-section,-fprofile-info-section=nameโ This one is a little niche ๐ง. It registers the profile info in a specific section instead of using a constructor/destructor. The section is callednameif you give one, and otherwise it defaults to.gcov_info๐ท๏ธ. For each translation unit, a pointer to the profile info from-fprofile-arcsgets placed in that section. This option turns off the constructor registration and the destructor processing ๐ง.
โ ๏ธ This option is not intended for hosted environments like GNU/Linux! It's built for free-standing environments, like embedded systems, that have limited resources and don't support constructors/destructors or C library file I/O ๐ค.
The linker can gather those input sections into one continuous memory block and define start and end symbols for it. Here's an example GNU linker script that defines a linker output section:
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
Then your program can dump the profiling info registered in this linker set. It goes something like this ๐ป:
#include <gcov.h>
#include <stdio.h>
#include <stdlib.h>
extern const struct gcov_info *__gcov_info_start[];
extern const struct gcov_info *__gcov_info_end[];
static void
filename (const char *f, void *arg)
{
puts (f);
}
static void
dump (const void *d, unsigned n, void *arg)
{
const unsigned char *c = d;
for (unsigned i = 0; i < n; ++i)
printf ("%02x", c[i]);
}
static void *
allocate (unsigned length, void *arg)
{
return malloc (length);
}
static void
dump_gcov_info (void)
{
const struct gcov_info **info = __gcov_info_start;
const struct gcov_info **end = __gcov_info_end;
/* Obfuscate variable to prevent compiler optimizations. */
__asm__ ("" : "+r" (info));
while (info != end)
{
void *arg = NULL;
__gcov_info_to_gcda (*info, filename, dump, allocate, arg);
putchar ('\n');
++info;
}
}
int
main()
{
dump_gcov_info();
return 0;
}
-fprofile-note=pathโ If you give it apath, GCC saves the.gcnofile into that location ๐ฅ. Heads up: if you combine this with multiple source files, the.gcnofile gets overwritten ๐ฌ.-fprofile-prefix-path=pathโ This pairs withprofile-generate=profile_dirandprofile-use=profile_dirto tell GCC where the base directory of your built source tree is ๐ฒ. By default,profile_dirholds files with mangled absolute paths for every object file in the project, which is a mess ๐. It becomes a real problem when the directory you built the instrumented binary in is different from the one you used for the feedback-optimized build, because then the profile data won't be found during the optimized build ๐. In those setups, pass-fprofile-prefix-path=pathwithpathpointing to the build's base directory. That strips the irrelevant part and keeps every file name relative to the main build directory ๐งน.-fprofile-prefix-map=old=newโ When you compile files living in directoryold, the profiling info (recorded with--coverage) describes them as if they lived in directorynewinstead ๐ญ. Also check out-ffile-prefix-map๐ฏ.-fprofile-update=methodโ This changes the update method for an app that's instrumented for profile feedback based optimization ๐. Themethodshould besingle,atomic, orprefer-atomic.singleis great for single-threaded apps, whileatomicstops profile corruption by emitting thread-safe code ๐งต.
๐จ Warning: If your app doesn't properly join all its threads (or it creates a detached thread), the profile file can still get corrupted. Bestie, be careful!
Using prefer-atomic gets transformed into atomic when the target supports it, or into single if it doesn't ๐. The GCC driver automatically picks prefer-atomic whenever -pthread is on the command line ๐ง.
-fprofile-filter-files=regexโ This instruments only the functions from files whose names match any of the regular expressions, which are separated by semicolons ๐. For example,-fprofile-filter-files=main\.c;module.*\.cwill instrument onlymain.cand all C files starting with 'module' ๐ธ.-fprofile-exclude-files=regexโ This is the opposite vibe: it instruments only the functions from files whose names don't match any of the regular expressions, again separated by semicolons ๐ โโ๏ธ. For example,-fprofile-exclude-files=/usr/.*stops instrumentation for every file in the/usr/folder ๐ซ.-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ This controls how reproducible the profile gathered by-fprofile-generateis ๐. It's super useful when you want to rebuild a program with the same outcome, like for distribution packages ๐ฆ.
With -fprofile-reproducible=serial, the profile from -fprofile-generate is reproducible, as long as the trained program behaves the same on every invocation of the train run, isn't multi-threaded, and always streams profile data in the same order ๐ง. Profile streaming happens at the end of the program run, but also before the fork function is invoked ๐ด.
Real talk, though: lots of program execution counts depend on things like the length of temporary file names or memory space randomization, which can change hash-table collision rates ๐ฒ. That non-reproducible stuff can be annotated with the no_instrument_function function attribute ๐ท๏ธ. You can use gcov-dump with -l to dump the gathered data and check that it really is reproducible ๐๐.
Okay so, with -fprofile-reproducible=parallel-runs ๐ your collected profile stays reproducible no matter what order the data gets streamed into the gcda files โจ. It lets you run multiple instances of your instrumented program at the same time (like with make -j) ๐โโ๏ธ, but it's giving a tradeoff: the quality of the gathered data takes a hit, especially for indirect call profiling ๐ญ.
-fsanitize=addressโ ๐ฅ Turns on AddressSanitizer, a fast memory error detector. Your memory access instructions get instrumented so it can catch out-of-bounds and use-after-free bugs ๐. This also enables-fsanitize-address-use-after-scope. More details live athttps://github.com/google/sanitizers/wiki/AddressSanitizer๐. The run-time behavior is controlled by theASAN_OPTIONSenvironment variable ๐ธ. Set it to"help=1"and the available options pop up when your instrumented program starts ๐ง. For the full list of supported options, checkhttps://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags๐. โ ๏ธ This one cannot be combined with-fsanitize=threador-fsanitize=hwaddress๐ โโ๏ธ. Also, the only target-fsanitize=hwaddressis currently supported on is AArch64, just FYI ๐ .-fsanitize=kernel-addressโ ๐ง Enables AddressSanitizer for the Linux kernel. Deets are athttps://github.com/google/kasan๐ซถ.-fsanitize=hwaddressโ ๐ฆ Hardware-assisted AddressSanitizer, which is honestly iconic. It uses a hardware ability to ignore the top byte of a pointer, so it can detect memory errors with a low memory overhead ๐. Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs. This also enables-fsanitize-address-use-after-scope. Seehttps://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.htmlfor more details ๐. Run-time behavior is influenced by theHWASAN_OPTIONSenvironment variable, and setting it to"help=1"shows the available options at startup ๐. โ ๏ธ It cannot be combined with-fsanitize=threador-fsanitize=address, and it is currently only available on AArch64 ๐ซ.-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, but with instrumentation differences needed for the kernel. Those differences exist to skiphwasanlibrary initialization calls and to account for the stack pointer having a different value in its top byte ๐.- > ๐
Note: This option has different defaults than
-fsanitize=hwaddress. Instrumenting the stack andallocacalls is not on by default, but you can still turn it on with the command-line options--param hwasan-instrument-stack=1and--param hwasan-instrument-allocas=1respectively ๐. Using a random frame tag is not implemented for kernel instrumentation ๐ฅฒ.
- > ๐
Note: This option has different defaults than
-fsanitize=pointer-compareโ ๐ Instruments comparison operations (<,<=,>,>=) with pointer operands. It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it cannot be combined with-fsanitize=thread๐ซ.- ๐ค Note: By default the check is disabled at run time. To turn it on, add
"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. Using"detect_invalid_pointer_pairs=1"only detects invalid operations when both pointers are non-null ๐ซ .
- ๐ค Note: By default the check is disabled at run time. To turn it on, add
-fsanitize=pointer-subtractโ โ Instruments subtraction with pointer operands. It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it cannot be combined with-fsanitize=thread๐ซ.- ๐ค Note: By default the check is disabled at run time. To enable it, add
"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. Using"detect_invalid_pointer_pairs=1"only detects invalid operations when both pointers are non-null ๐ซ .
- ๐ค Note: By default the check is disabled at run time. To enable it, add
-fsanitize=shadow-call-stackโ ๐ก๏ธ Enables ShadowCallStack, a security enhancement that protects programs against return address overwrites (like stack buffer overflows) ๐ฐ. It works by saving a function's return address to a separately allocated shadow call stack in the function prologue, then restoring the return address from that shadow call stack in the function epilogue ๐ช. Instrumentation only happens in functions that need to save the return address to the stack โจ.- ๐ Right now it only supports the aarch64 platform. It's specifically designed for Linux kernels that enable the
CONFIG_SHADOW_CALL_STACKoption. For user space programs, runtime support is not currently provided inlibcandlibgcc, so users who want this in user space need to provide their own runtime support. โ ๏ธ It should be noted that this may cause the ABI rules to be broken ๐ฌ. - ๐งต On aarch64, the instrumentation makes use of the platform register
"x18". This generally means any code that may run on the same thread as code compiled with ShadowCallStack must be compiled with the flag-ffixed-x18. Otherwise, functions compiled without-ffixed-x18might clobber"x18"and corrupt the shadow stack pointer ๐. - ๐ซ Also, because there is no userspace runtime support, code compiled with ShadowCallStack cannot use exception handling. Use
-fno-exceptionsto turn off exceptions. - ๐ See
https://clang.llvm.org/docs/ShadowCallStack.htmlfor more details.
- ๐ Right now it only supports the aarch64 platform. It's specifically designed for Linux kernels that enable the
-fsanitize=threadโ ๐งต Enables ThreadSanitizer, a fast data race detector. Memory access instructions get instrumented to detect data race bugs ๐โโ๏ธ. Seehttps://github.com/google/sanitizers/wiki#threadsanitizerfor more details. The run-time behavior is influenced using theTSAN_OPTIONSenvironment variable; checkhttps://github.com/google/sanitizers/wiki/ThreadSanitizerFlagsfor a list of supported options ๐. โ ๏ธ It cannot be combined with-fsanitize=addressor-fsanitize=leak.- ๐ต Note: Sanitized atomic builtins cannot throw exceptions when operating on invalid memory addresses with non-call exceptions (
-fnon-call-exceptions).
- ๐ต Note: Sanitized atomic builtins cannot throw exceptions when operating on invalid memory addresses with non-call exceptions (
-fsanitize=leakโ ๐ง Enables LeakSanitizer, a memory leak detector. This option only matters for linking executables, and only when the executable is linked against a library that overrides"malloc"and other allocator functions ๐ซง. Seehttps://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizerfor more details. Run-time behavior is influenced by theLSAN_OPTIONSenvironment variable ๐ท. โ ๏ธ It cannot be combined with-fsanitize=thread.-fsanitize=undefinedโ ๐ Enables UndefinedBehaviorSanitizer, a fast undefined behavior detector. Various computations get instrumented to catch undefined behavior at runtime ๐. Seehttps://clang.llvm.org/docs/UndefinedBehaviorSanitizer.htmlfor more details. Run-time behavior is influenced by theUBSAN_OPTIONSenvironment variable. Here are the current suboptions ๐:-fsanitize=shiftโ ๐ซจ Checks that the result of a shift operation is not 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 is not negative and is smaller than the precision of the promoted first argument.-fsanitize=shift-baseโ ๐งฎ If the second argument of a shift operation is within range, checks that the result of the shift is not undefined. What counts as undefined differs slightly between C and C++, and between ISO C90 and C99, etc.-fsanitize=integer-divide-by-zeroโ ๐ซ Detects integer division by zero.-fsanitize=unreachableโ ๐บ๏ธ With this option, the compiler turns the"__builtin_unreachable"call into a diagnostics message call instead. When the"__builtin_unreachable"call is reached, the behavior is undefined ๐ฑ.-fsanitize=vla-boundโ ๐ Tells the compiler to check that the size of a variable length array is positive.-fsanitize=nullโ ๐ซฅ Enables pointer checking. An application built with this on will throw an error message when it tries to dereference a NULL pointer, when a reference (possibly an rvalue reference) is bound to a NULL pointer, or when a method is invoked on an object pointed to by a NULL pointer ๐ โโ๏ธ.-fsanitize=returnโ ๐ Enables return statement checking. Programs built with this on will throw an error message when the end of a non-void function is reached without actually returning a value. This option works in C++ only ๐โโ๏ธ.-fsanitize=signed-integer-overflowโ โ Enables signed integer overflow checking. It checks that the result of"+","*", and both unary and binary"-"does not overflow in signed arithmetic. This also detectsINT_MIN / -1signed division ๐ง. Heads up, integer promotion rules have to be taken into account, so the following is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ ๐งฑ Enables instrumentation of array bounds, so various out-of-bounds accesses get detected. Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented ๐.-fsanitize=bounds-strictโ ๐งฑ Enables strict instrumentation of array bounds. Most out-of-bounds accesses get detected, including flexible array members and flexible array member-like arrays. Initializers of variables with static storage are still not instrumented ๐ค.-fsanitize=alignmentโ ๐ Checks alignment of pointers when they are dereferenced, when a reference is bound to an insufficiently aligned target, or when a method or constructor is invoked on an insufficiently aligned object ๐ฏ.-fsanitize=object-sizeโ ๐ฆ Instruments memory references using the"__builtin_object_size"function. Various out-of-bounds pointer accesses get detected ๐ซถ.
-fsanitize=float-divide-by-zeroโ okay so this one catches floating-point division by zero ๐งฎ. Unlike a lot of the other sanitizers, it is not switched on by-fsanitize=undefined, because dividing a float by zero can be a totally legit way to get infinities and NaNs โจ. Not every spicy move is a bug, bestie ๐ .-fsanitize=float-cast-overflowโ this one checks floating-point to integer conversions ๐ข and makes sure the result doesn't overflow. Also not part of-fsanitize=undefined, and it doesn't vibe well withFE_INVALIDexceptions turned on ๐.-fsanitize=nonnull-attributeโ instruments calls to make sure no null values get passed into arguments that thenonnullfunction attribute says must never be null ๐ซ. Null in a non-null spot? Not it ๐.-fsanitize=returns-nonnull-attributeโ instrumentsreturnstatements in functions marked with thereturns_nonnullfunction attribute ๐, so it can catch those functions handing back a null value.-fsanitize=boolโ instruments loads frombool๐งธ. If something other than0or1gets loaded, you get a run-time error. Booleans only do 0 and 1, babe ๐ค.-fsanitize=enumโ instruments loads from an enum type ๐. If the value being loaded is outside the range the enum allows, a run-time error gets issued.-fsanitize=vptrโ C++ girlies, this one's for you ๐. It instruments C++ member function calls, member accesses, and some conversions between pointers to base and derived classes, so it can verify the referenced object has the correct dynamic type ๐ฆ.-fsanitize=pointer-overflowโ instruments pointer arithmetic ๐ง. If that pointer math overflows, you get a run-time error.-fsanitize=builtinโ instruments the arguments passed to selected builtin functions โจ. If an invalid value sneaks in, a run-time error gets issued. For example, passing0as the argument to__builtin_ctzor__builtin_clzis undefined behavior, and this option diagnoses it ๐ซถ.
While -ftrapv causes traps for signed overflows to be emitted, -fsanitize=undefined gives a diagnostic message instead ๐ฃ. Heads up: this currently only works for the C family of languages ๐.
-fno-sanitize=allโ disables all the sanitizers you turned on before ๐งน. Fair warning:-fsanitize=allis NOT allowed, because some sanitizers can't be used together ๐.-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks ๐งช. It's super handy for experimenting with different shadow memory layouts in Kernel AddressSanitizer ๐ธ.-fsanitize-sections=s1,s2,...โ sanitizes global variables in the user-defined sections you pick ๐๏ธ. Thesientries may contain wildcards.-fsanitize-recover[=opts]โ this one controls error recovery mode for the sanitizers listed in the comma-separatedoptslist ๐. When recovery is on for a sanitizer, the program tries to keep running like nothing happened. That means several runtime errors can get reported in one run, and the exit code might say success even though errors were reported ๐ญ. The-fno-sanitize-recover=option flips that: only the first error gets reported, and then the program exits with a non-zero exit code ๐.
Right now this only works for -fsanitize=undefined (and its suboptions, except -fsanitize=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, recovery is turned on by default, except for -fsanitize=address, where it's still experimental ๐งช. You can also use -fsanitize-recover=all (turns on recovery for every sanitizer that supports it) or -fno-sanitize-recover=all (turns it off for every sanitizer that supports it) ๐.
Even if recovery is turned on at the compiler side, it also has to be enabled on the runtime library side, or the failures are still fatal ๐. The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while AddressSanitizer defaults to halt_on_error=1. You can override that by setting the halt_on_error flag in the corresponding environment variable ๐ง.
Using this option without an explicit opts parameter is deprecated ๐
. It's the same as specifying this opts list:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ enables sanitization of local variables so it can catch use-after-scope bugs ๐ต๏ธ. This option sets-fstack-reusetononeโจ.-fsanitize-undefined-trap-on-errorโ tells the compiler to report undefined behavior using__builtin_trapinstead of alibubsanlibrary routine ๐ชค. The perk is thatlibubsanisn't needed and doesn't get linked in, so this works even in freestanding environments ๐๏ธ.-fsanitize-coverage=trace-pcโ enables coverage-guided fuzzing 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 a call to__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__sanitizer_cov_trace_cmp8for integral comparisons where both operands are variables. For integral comparisons with one constant operand, it uses__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4or__sanitizer_cov_trace_const_cmp8. For float or double comparisons it uses__sanitizer_cov_trace_cmpfor__sanitizer_cov_trace_cmpd, and for switch statements it uses__sanitizer_cov_trace_switch๐ฏ.-fcf-protection=[full|branch|return|none|check]โ turns on code instrumentation for control-flow transfers ๐ก๏ธ. It checks that target addresses of control-flow transfer instructions (like indirect function calls, function returns, and indirect jumps) are valid, so the flow of control can't get diverted somewhere unexpected ๐ง. This is meant to protect against threats like Return-oriented Programming (ROP), and similar call/jmp-oriented programming (COP/JOP) ๐ค.branchchecks validity at indirect branch instructions, aka call/jmp instructions ๐.returnchecks validity when returning from a function โฉ๏ธ.fullis an alias for bothbranchandreturn๐.noneturns instrumentation off ๐ .checkis used for the final link with link-time optimization (LTO). It issues an error if LTO object files were compiled with different-fcf-protectionvalues.checkis ignored at compile time ๐ซก.
The macro __CET__ is defined when -fcf-protection is used. Its first bit is set to 1 for branch, and its second bit 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 has an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processors or newer ๐ป.
-fharden-comparesโ for every logical test that survives gimple optimizations and isn't the condition in a conditional branch (like conditions tested for conditional moves, or stored in boolean variables), it emits extra code to compute and verify the reversed condition ๐ช. If the results don't match, it calls__builtin_trap. Use this with-fharden-conditional-branchesto cover all conditionals ๐.-fharden-conditional-branchesโ for every non-vectorized conditional branch that survives gimple optimizations, it emits extra code to compute and verify the reversed condition ๐. If the result is unexpected, it calls__builtin_trap. Use this with-fharden-comparesto cover all conditionals ๐ซถ.-fstack-protectorโ emits extra code to check for buffer overflows, like stack smashing attacks ๐งฑ. It adds a guard variable to functions with vulnerable objects. That includes functions that callalloca, and functions with buffers larger than or equal to 8 bytes. The guards get initialized when a function is entered and then checked when it exits. If a guard check fails, an error message is printed and the program exits ๐จ. Only variables that are actually allocated on the stack count; optimized-away variables or variables allocated in registers don't ๐.-fstack-protector-allโ same as-fstack-protector, except that all functions get protected ๐ก๏ธโจ.-fstack-protector-strongโ like-fstack-protector, but it also protects extra functions: ones with local array definitions, or ones that reference local frame addresses ๐ . Same rule applies: only variables actually allocated on the stack count, and optimized-away or register-allocated variables don't.-fstack-protector-explicitโ like-fstack-protector, but it only protects functions that have thestack_protectattribute ๐ฏ.-fstack-checkโ generates code to verify that you don't go beyond the boundary of the stack ๐ฅ. You should specify this if you're running in an environment with multiple threads. In a single-threaded environment you rarely need it, since stack overflow is automatically detected on nearly all systems when there's only one stack ๐งต.
Note that this switch doesn't actually cause checking to be done ๐ โโ๏ธ. The operating system or the language runtime has to do that. The switch just causes code generation that makes sure they see the stack being extended ๐.
okay bestie, the string parameter is where you get to pick your vibe ๐
You can additionally specify a string parameter: no means no checking at all ๐
โโ๏ธ, generic means force the use of old-style checking, and specific means use the best checking method, which is equivalent to bare -fstack-check โจ
Old-style checking is a generic mechanism that requires no specific target support in the compiler, but it comes with some major drawbacks ๐ญ
- Modified allocation strategy for large objects: they are always allocated dynamically if their size exceeds a fixed threshold. ngl this may change the semantics of some code, so keep an eye out ๐
- Fixed limit on the size of the static frame of functions: when it's topped by a particular function, stack checking is not reliable and the compiler issues a warning โ ๏ธ
- Inefficiency: because of both the modified allocation strategy and the generic implementation, code performance takes a hit ๐ซ
Note that old-style stack checking is also the fallback method for specific if no target support has been added in the compiler ๐ง
-fstack-check= is designed for Ada's needs to detect infinite recursion and stack overflows ๐ specific is an excellent choice when compiling Ada code. It is not generally sufficient to protect against stack-clash attacks, though. To protect against those, you want -fstack-clash-protection ๐ก๏ธ
-fstack-clash-protectionโ generates code to prevent stack clash style attacks ๐ฆ When this option is enabled, the compiler only allocates one page of stack space at a time, and each page is accessed immediately after allocation. So it stops allocations from jumping over any stack guard page provided by the operating system ๐
Most targets do not fully support stack clash protection, lowkey tragic ๐ญ However, on those targets, -fstack-clash-protection will protect dynamic stack allocations. It may also provide limited protection for static stack allocations if the target supports -fstack-check=specific โจ
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ generates code to make sure the stack doesn't grow beyond a certain value, either the value of a register or the address of a symbol ๐ธ If a larger stack is required, a signal is raised at run time. For most targets the signal goes off before the stack overruns the boundary, so you can catch it without taking any special precautions ๐ซถ
For instance, if the stack starts at absolute address 0x80000000 and grows downwards, you can use the flags -fstack-limit-symbol=__stack_limit and -Wl,--defsym,__stack_limit=0x7ffe0000 to enforce a stack limit of 128KB ๐
Note that this may only work with the GNU linker. Not every setup is going to vibe with it ๐
You can locally override stack limit checking by using the "no_stack_limit" function attribute ๐
-fsplit-stackโ generates code to automatically split the stack before it overflows ๐ง The resulting program has a discontiguous stack, which can only overflow if the program is unable to allocate any more memory. This is most useful when running threaded programs, because it's no longer necessary to calculate a good stack size to use for each thread ๐คฏ This is currently only implemented for the x86 targets running GNU/Linux ๐ง
When code compiled with -fsplit-stack calls code compiled without -fsplit-stack, there may not be much stack space available for the latter code to run in ๐ฌ If compiling all code, including library code, with -fsplit-stack is not an option, then the linker can fix up these calls so the code compiled without -fsplit-stack always has a large stack. Support for this is implemented in the gold linker in GNU binutils release 2.21 and later ๐
-fvtable-verify=[std|preinit|none]โ this option is only available when compiling C++ code ๐ It turns on (or off, if you use-fvtable-verify=none) the security feature that checks at run time, for every virtual call, that the vtable pointer the call goes through is valid for the type of the object, and hasn't been corrupted or overwritten ๐ If an invalid vtable pointer is detected at run time, an error is reported and execution of the program is immediately halted ๐
This option causes run-time data structures to be built at program startup, and those are used for verifying the vtable pointers ๐งฉ The options std and preinit control the timing of when these data structures are built. In both cases, they're built before execution reaches "main". Using -fvtable-verify=std builds them after shared libraries have been loaded and initialized. -fvtable-verify=preinit builds them before shared libraries have been loaded and initialized ๐ฆ
If this option appears multiple times on the command line with different values specified, none takes highest priority over both std and preinit, and preinit takes priority over std ๐
-fvtv-debugโ when used alongside-fvtable-verify=stdor-fvtable-verify=preinit, it causes debug versions of the runtime functions for the vtable verification feature to be called ๐ This flag also makes the compiler log information about which vtable pointers it finds for each class. That info gets written to a file namedvtv_set_ptr_data.login the directory named by the environment variableVTV_LOGS_DIRif that's defined, or the current working directory otherwise ๐
Note: This feature appends data to the log file. If you want a fresh log file, be sure to delete any existing one ๐๏ธ
-fvtv-countsโ this is a debugging flag ๐ When used alongside-fvtable-verify=stdor-fvtable-verify=preinit, the compiler keeps track of the total number of virtual calls it encounters and the number of verifications it inserts. It also counts the number of calls to certain run-time library functions that it inserts, and logs this for each compilation unit ๐ The compiler writes this info to a file namedvtv_count_data.login the directory named byVTV_LOGS_DIRif that's defined, or the current working directory otherwise. It also counts the size of the vtable pointer sets for each class, and writes that tovtv_class_set_sizes.login the same directory ๐
Note: This feature appends data to the log files. To get fresh log files, be sure to delete any existing ones ๐งน
-finstrument-functionsโ generates instrumentation calls for entry and exit to functions ๐ฅ Just after function entry and just before function exit, the following profiling functions are called with the address of the current function and its call site ๐ (On some platforms,__builtin_return_addressdoes not work beyond the current function, so the call site information may not be available to the profiling functions otherwise ๐)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
The first argument is the address of the start of the current function, which can be looked up exactly in the symbol table ๐
This instrumentation is also done for functions expanded inline in other functions. The profiling calls indicate where, conceptually, the inline function is entered and exited. This means that addressable versions of such functions must be available. If all your uses of a function are expanded inline, this may mean an additional expansion of code size ๐ฆ If you use extern inline in your C code, an addressable version of such functions must be provided. (This is normally the case anyway, but if you get lucky and the optimizer always expands the functions inline, you might have gotten away without providing static copies ๐)
A function may be given the attribute "no_instrument_function", in which case this instrumentation is not done. This can be used for, example, the profiling functions listed above, high-priority interrupt routines, and any functions from which the profiling functions cannot safely be called (perhaps signal handlers, if the profiling routines generate output or allocate memory) ๐ซ
-finstrument-functions-exclude-file-list=file,file,...โ sets the list of functions that are excluded from instrumentation (see the description of-finstrument-functions) ๐ โโ๏ธ If the file that contains a function definition matches with one of thefileentries, then that function is not instrumented. The match is done on substrings: if thefileparameter is a substring of the file name, it's considered to be a match ๐ง
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
That excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys ๐
If, for some reason, you want to include a comma in one of the sym values, write ,,. For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quotes surrounding the option) ๐
-finstrument-functions-exclude-function-list=sym,sym,...โ this is similar to-finstrument-functions-exclude-file-list, but this one sets the list of function names to be excluded from instrumentation ๐ง The function name to be matched is its user-visible name, such as"vector<int> blah(const vector<int> &)", not the internal mangled name (e.g.,"_Z4blahRSt6vectorIiSaIiEE") ๐ค The match is done on substrings: if thesymparameter is a substring of the function name, it's considered to be a match. For C99 and C++ extended identifiers, the function name must be given in UTF-8, not using universal character names ๐-fpatchable-function-entry=N[,M]โ generatesNNOPs right at the beginning of each function, with the function entry point before theMth NOP โจ IfMis omitted, it defaults to0, so the function entry points to the address just at the first NOP ๐ฆ The NOP instructions reserve extra space that can be used to patch in any desired instrumentation at run time, provided that the code segment is writable ๐ ๏ธ The amount of space is controllable indirectly via the number of NOPs. The NOP instruction used corresponds to the instruction emitted by the internal GCC back-end interfacegen_nop. This behavior is target-specific and may also depend on the architecture variant and/or other compilation options ๐ธ
Okay so the patchable function entry stuff is giving main character energy โจ For run-time identification ๐, the starting addresses of these areas (each one is its function entry minus M ๐ง) also get collected into the __patchable_function_entries section of the resulting binary.
Also, bestie, the value of __attribute__ ((patchable_function_entry (N,M))) beats the command-line option -fpatchable-function-entry=N,M ๐. Lowkey iconic, because you can use it to make the area bigger or delete it completely on one single function ๐
. And if N=0, no pad location gets recorded ๐.
The NOP instructions go in at the function entry address, and maybe before it depending on M (even before the prologue) ๐ธ. Honestly, the maximum for N and M is 65535 ๐.
โจ Options Controlling the Preprocessor โจ
These options control the C preprocessor ๐, which runs on every C source file before the actual compilation happens.
If you use the -E option, nothing happens except preprocessing ๐. Some of these options only make sense together with -E, because they make the preprocessor output unsuitable for actual compilation ๐ญ.
Other include-file search path options are documented in Directory Options ๐ฆ, and options that control preprocessor diagnostics are listed in Warning Options ๐ซถ.
-D nameโ Predefinenameas a macro, with definition1๐.-D name=definitionโ The contents ofdefinitionget tokenized and processed as if they showed up during translation phase three in a#definedirective ๐ง. The definition gets cut off at embedded newline characters โ๏ธ.- If you call the preprocessor from a shell (or something shell-like), you might need the shell's quoting syntax to protect characters like spaces, since they mean something in shell syntax ๐.
- If you want a function-like macro on the command line, write its argument list in parentheses before the equals sign (if there is one) ๐. Parentheses mean something to most shells, so quote the option. With
shandcsh,-D'name(args...)=definition'works โจ. -Dand-Uoptions are processed in the order they appear on the command line. All-imacros fileand-include fileoptions get processed after every-Dand-Uoption ๐ฅ.
-U nameโ Cancel any previous definition ofname, whether it was built in or came from a-Doption ๐ โโ๏ธ.-include fileโ Processfileas if#include "file"appeared as the first line of the primary source file ๐. The first directory searched forfileis the preprocessor's working directory, not the directory with the main source file ๐๏ธ. If it's not found there, it gets searched for in the rest of the#include "..."search chain, as normal ๐ฆ.- If you give multiple
-includeoptions, the files get included in the order they appear on the command line ๐.
- If you give multiple
-imacros fileโ Exactly like-include, except any output from scanningfileis thrown away ๐๏ธ. The macros it defines stay defined ๐ . This lets you grab all the macros from a header without also processing its declarations ๐ง.- All files given by
-imacrosget processed before all files given by-include๐.
- All files given by
-undefโ Don't predefine any system-specific or GCC-specific macros ๐. The standard predefined macros stay defined ๐.-pthreadโ Defines additional macros needed for using the POSIX threads library ๐งต. Use this option consistently for both compilation and linking ๐. It's supported on GNU/Linux targets and most other Unix derivatives, plus x86 Cygwin and MinGW targets ๐ธ.-Mโ Instead of printing the preprocessed result, output a rule formakedescribing the dependencies of the main source file ๐. You get one make rule with the object file name for that source file, a colon, and the names of all the included files (including the ones from-includeor-imacroscommand-line options) ๐.- Unless you set it explicitly with
-MTor-MQ, the object file name is the source file name with its suffix swapped for the object file suffix, and with any leading directory parts removed ๐. - If there are lots of included files, the rule gets split across several lines using
\-newline๐. The rule has no commands ๐ซถ. - This option does not suppress the preprocessor's debug output, like
-dM. To keep that debug output from mixing with the dependency rules, explicitly specify the dependency output file with-MF, or use an environment variable likeDEPENDENCIES_OUTPUT๐ง . Debug output still goes to the regular output stream as normal โจ. - Passing
-Mto the driver implies-E, and suppresses warnings with an implicit-w๐.
- Unless you set it explicitly with
-MMโ Like-M, but don't mention header files found in system header directories, or header files included (directly or indirectly) from those system headers ๐ซ.- This means the choice of angle brackets or double quotes in an
#includedirective doesn't by itself decide whether that header shows up in-MMdependency output ๐ฆ.
- This means the choice of angle brackets or double quotes in an
-MF fileโ When used with-Mor-MM, specifies a file to write the dependencies to ๐. If there's no-MF, 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
fileis-, the dependencies get written to stdout ๐ฅ๏ธ.
- When used with the driver options
-MGโ Used along with an option like-Mthat requests dependency generation,-MGassumes missing header files are generated files ๐ ๏ธ. It adds them to the dependency list without raising an error ๐ฅฐ. The dependency filename comes straight from the#includedirective, without any path prepended ๐.-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โ This option tells CPP to add a phony target for each dependency other than the main file, so each one depends on nothing ๐ญ. These dummy rules work around errors thatmakegives when you remove header files without updating the Makefile to match ๐ญ.- This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ Changes the target of the rule emitted by dependency generation ๐ฏ. By default, CPP takes the name of the main input file, deletes any directory components and any file suffix like.c, and appends the platform's usual object suffix ๐ง. That result is the target.- An
-MToption sets the target to be exactly the string you specify ๐ . If you want multiple targets, you can specify them as a single argument to-MT, or use multiple-MToptions ๐. - For example,
-MT '$(objpfx)foo.o'might give:
- An
$(objpfx)foo.o: foo.c
-MQ targetโ Same as-MT, but it quotes any characters that are special to Make ๐.-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
- The default target is automatically quoted, as if it were given with
-MQโจ.
-MDโ-MDis equivalent to-M -MF file, except that-Eis not implied ๐ง. The driver figures outfilebased on whether an-ooption is given ๐. If it is, the driver uses that argument but with a suffix of.d๐งพ. Otherwise, it takes the name of the input file, removes any directory components and suffix, and applies a.dsuffix ๐.- If
-MDis used together with-E, any-oswitch is understood to specify the dependency output file ๐. But if-MDis used without-E, each-ois understood to specify a target object file ๐ฏ. - Since
-Eis not implied,-MDcan generate a dependency output file as a side effect of the compilation process ๐.
- If
-MMDโ Like-MD, but only mention user header files, not system header files ๐ โโ๏ธ.-fpreprocessedโ Tells the preprocessor that the input file has already been preprocessed ๐. This suppresses things like macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives ๐. The preprocessor still recognizes and removes comments, so you can pass a file preprocessed with-Cto the compiler without problems ๐. In this mode, the integrated preprocessor is basically just a tokenizer for the front ends ๐งธ.-fpreprocessedis implicit if the input file has one of the extensions.i,.iior.mi๐ช. Those are the extensions GCC uses for preprocessed files created by-save-temps๐๏ธ.
-fdirectives-onlyโ When preprocessing, handle directives but don't expand macros ๐.- How this behaves depends on the
-Eand-fpreprocessedoptions ๐ค. - With
-E, preprocessing is limited to handling directives such as#define,#ifdef, and#error๐ ๏ธ. Other preprocessor operations, like macro expansion and trigraph conversion, are not performed ๐ซ. In addition, the-dDoption is implicitly enabled ๐. - With
-fpreprocessed, predefinition of command line and most builtin macros is disabled ๐ โโ๏ธ. Macros such as__LINE__, which depend on context, are handled normally ๐. This enables compilation of files previously preprocessed with-E -fdirectives-only๐. - With both
-Eand-fpreprocessed, the rules for-fpreprocessedtake precedence ๐. This enables full preprocessing of files previously preprocessed with-E -fdirectives-only๐ธ.
- How this behaves depends on the
-fdollars-in-identifiersโ Accept$in identifiers ๐ฒ.-fextended-identifiersโ Accept universal character names and extended characters in identifiers ๐. This option is enabled by default for C99 (and later C standard versions) and C++ ๐ซถ.-fno-canonical-system-headersโ When preprocessing, don't shorten system header paths with canonicalization ๐ฃ๏ธ.-fmax-include-depth=depthโ Sets the maximum depth of nested#includedirectives ๐ช. The default is200๐ฏ.-ftabstop=widthโ Sets the distance between tab stops ๐. This helps the preprocessor report correct column numbers in warnings or errors, even if tabs appear on the line ๐ฏ. If the value is less than1or greater than100, the option is ignored ๐. The default is8๐.
-ftrack-macro-expansion[=level] โ okay bestie, this one tracks where tokens live across macro expansions ๐ so that when an error pops up inside a macro, the compiler can print the current macro expansion stack for you ๐ . Heads up though: it makes the preprocessor and the compiler eat more memory ๐ซ . The level lets you dial down how precise the tracking is if memory gets tight โจ:
0turns the whole thing off ๐ โโ๏ธ1tracks locations in a degraded mode for minimal memory overhead ๐ฆ. In this mode, every token that comes out of expanding an argument of a function-like macro shares the same location2tracks locations completely ๐ and is the most memory hungry option ๐- If you give the option with no argument, the default level is
2
Note that -ftrack-macro-expansion=2 is activated by default ๐
-fmacro-prefix-map=old=newโ when you preprocess files hanging out in the directoryold, the__FILE__and__BASE_FILE__macros will act like those files live innewinstead ๐บ๏ธ. Use.fornewto turn an absolute path into a relative one, which can lead to more reproducible builds that are location independent ๐ธ. 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 ๐. The default isUTF-8, andcharsetcan be any encoding your system'siconvlibrary routine supports ๐.-fwide-exec-charset=charsetโ sets the wide execution character set, used for wide string and character constants ๐ง. The default isUTF-32orUTF-16, whichever matches the width ofwchar_t. Same deal as-fexec-charset:charsetcan be any encodingiconvsupports, but you'll have problems with encodings that don't fit exactly inwchar_t๐ญ-finput-charset=charsetโ sets the input character set, used to translate the input file's characters 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 option can override it, but right now the command-line option wins if there's a conflict ๐.charsetcan be any encoding your system'siconvlibrary routine supports.-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โ lets you use a precompiled header together with-E๐ซถ. It inserts a special#pragma, which looks like#pragma GCC pch_preprocess "filename", into the output to mark where the precompiled header was found and what its filename is. When-fpreprocessedis in use, GCC recognizes this#pragmaand loads the PCH โจ.
This option is off by default, because the preprocessed output is only really suitable as input to GCC ๐
. It gets switched on by -save-temps.
You shouldn't write this #pragma in your own code ๐
โโ๏ธ, but it's totally safe to edit the filename if the PCH file is available in a different location ๐งณ. The filename can be absolute, or relative to GCC's current directory.
-fworking-directoryโ turns on linemarkers in the preprocessor output so the compiler knows the current working directory at the time of preprocessing ๐๏ธ. With this enabled, the preprocessor emits a second linemarker after the initial one, containing the current working directory followed by two slashes. When that directory shows up in preprocessed input, GCC uses it as the directory reported as the current working directory in some debugging information formats ๐. This option is implicitly enabled if debugging information is enabled, but you can inhibit it with the negated form-fno-working-directory. If the-Pflag is in the command line, this option has no effect, since no#linedirectives are emitted whatsoever ๐ซ.-A predicate=answerโ makes an assertion with the predicatepredicateand the answeranswer๐ฆ. This form is preferred over the older-A predicate(answer)form, which is still supported, because it doesn't use shell special characters ๐.-A -predicate=answerโ cancels an assertion with the predicatepredicateand the answeranswer๐ โโ๏ธ.-Cโ don't discard comments! All comments get passed through to the output file, except comments in processed directives, which get deleted along with the directive ๐ฌ.
Be prepared for side effects when using -C ๐. It causes the preprocessor to treat comments as tokens in their own right. For example, comments at the start of what would be a directive line turn that line into an ordinary source line, since the first token on the line is no longer a #.
-CCโ don't discard comments, including during macro expansion ๐. This is like-C, except comments contained within macros also get passed through to the output file where the macro is expanded.
On top of the side effects of -C, -CC converts all C++-style comments inside a macro into C-style comments ๐. This stops a later use of that macro from accidentally commenting out the rest of the source line ๐.
-CC is generally used to support lint comments ๐งน.
-Pโ inhibits generation of linemarkers in the preprocessor output ๐ซ. This might be useful when you're running the preprocessor on something that isn't C code and will be sent to a program that might get confused by linemarkers ๐คทโโ๏ธ.-traditional,-traditional-cppโ tries to imitate pre-standard C preprocessors, as opposed to ISO C preprocessors ๐ฐ๏ธ. See the GNU CPP manual for details.
GCC doesn't otherwise try to emulate a pre-standard C compiler, and these options are only supported with the -E switch, or when invoking CPP explicitly ๐.
-trigraphsโ supports ISO C trigraphs ๐บ. These are three-character sequences, all starting with??, that ISO C defines to stand for single characters ๐ค. For example,??/stands for\, so'??/n'is a character constant for a newline ๐.
The nine trigraphs and their replacements are:
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] { } # \ ^ | ~
By default GCC ignores trigraphs ๐, but in standard-conforming modes it converts them ๐
. See the -std and -ansi options.
-remapโ enables special code to work around file systems that only permit very short file names, like MS-DOS ๐.-Hโ prints the name of each header file used, in addition to the other normal activities ๐. Each name is indented to show how deep it is in the#includestack ๐ช. Precompiled header files get printed too, even if they turn out to be invalid. An invalid precompiled header file is printed with...x, and a valid one with...!.-dlettersโ makes debugging dumps during compilation as specified by letters ๐งช. The flags documented here are the ones relevant to the preprocessor. Other letters are interpreted by the compiler proper, or reserved for future versions of GCC, so they're silently ignored ๐คซ. If you specify letters whose behavior conflicts, the result is undefined ๐.-dMโ instead of the normal output, generates a list of#definedirectives for all the macros defined during the execution of the preprocessor, including predefined macros ๐. This is a great way to find out what's predefined in your version of the preprocessor ๐. Assuming you have no filefoo.h, the command:
touch foo.h; cpp -dM foo.h
shows all the predefined macros.
If you use -dM without the -E option, -dM is interpreted as a synonym for -fdump-rtl-mach ๐.
-dDโ like-dM, except in two respects: it does not include the predefined macros, and it outputs both the#definedirectives and the result of preprocessing ๐. Both kinds of output go to the standard output file.-dNโ like-dD, but emits only the macro names, not their expansions ๐ซฅ.-dIโ outputs#includedirectives in addition to the result of preprocessing ๐ฅ.-dUโ like-dD, except only macros that are expanded, or whose definedness is tested in preprocessor directives, are output ๐ฏ. The output is delayed until the use or test of the macro โณ, and#undefdirectives are also output for macros that were tested but undefined at the time ๐.
-fdebug-cppโ only useful for debugging GCC itself ๐. When used from CPP or with-E, it dumps debugging information about location maps. Every token in the output is preceded by the dump of the map its location belongs to ๐บ๏ธ.
When used from GCC without -E, this option has no effect ๐ด.
-Wp,optionโ lets you bypass the compiler driver and passoptiondirectly through to the preprocessor ๐. Ifoptioncontains commas, it gets split into multiple options at the commas. However, many options are modified, translated or interpreted by the compiler driver before being passed to the preprocessor, and-Wpforcibly bypasses that phase ๐.
The preprocessor's direct interface is undocumented and subject to change, so whenever possible you should avoid using -Wp and let the driver handle the options instead ๐ซถ.
-Xpreprocessor optionโ passesoptionas an option to the preprocessor ๐. You can use this to supply system-specific preprocessor options that GCC doesn't recognize.
If you want to pass an option that takes an argument, you must use -Xpreprocessor twice: once for the option, and once for the argument ๐ฏโโ๏ธ.
-no-integrated-cppโ okay so normally GCC does preprocessing as part of reading and parsing your code all in one go ๐ This flag makes it do the preprocessing as its own separate pass before compiling โจ The front end gets invoked twice: once just for preprocessing and once to actually compile the preprocessed input. The language front ends arecc1for C,cc1plusfor C++, andcc1objfor Objective-C. This can be super useful together with-Bor-wrapperif you want to swap in an alternate preprocessor or do extra processing on your source between preprocessing and compiling ๐ฅ-flarge-source-filesโ bestie, this one is for when your files are HUGE ๐ It tells GCC to expect large source files, but the tradeoff is slower compilation and higher memory usage ๐ญ
Here's the tea: GCC normally tracks both column numbers and line numbers in your source files, and it 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 won't include column numbers ๐ That also means options like -Wmisleading-indentation stop working at that point, although the compiler prints a note if this happens. Passing -flarge-source-files makes GCC keep tracking columns for significantly more source lines before it gives up on them ๐ฆ
๐ง Passing Options to the Assembler ๐ง
You can pass options to the assembler, bestie ๐
-Wa,optionโ passesoptionalong to the assembler ๐ Ifoptionhas commas in it, it gets split into multiple options at each comma.-Xassembler optionโ also passesoptionto the assembler ๐ซถ This is the move when you need system-specific assembler options that GCC doesn't recognize.
If you want to pass an option that takes an argument, you must use -Xassembler twice, once for the option and once for the argument ๐
๐ Options for Linking ๐
These options come into play when the compiler links object files into an executable output file. They are meaningless if the compiler is not doing a link step ๐
object-file-nameโ any file name that doesn't end in a special recognized suffix is considered to name an object file or library ๐ธ The linker tells object files apart from libraries by checking the file contents. If linking happens, these object files are used as input to the linker.-c,-S,-Eโ if any of these is used, the linker doesn't run, so object file names should not be used as arguments ๐ซ-flinker-output=typeโ this controls code generation of the link-time optimizer ๐ง By default the linker output is automatically determined by the linker plugin. For debugging the compiler, or if you want incremental linking with a non-LTO object file, it can be handy to control the type manually.
If type is exec, code generation produces a static binary. In this case -fpic and -fpie are both disabled.
If type is dyn, code generation produces a shared library. In this case -fpic or -fPIC is preserved, but not enabled automatically. This allows building shared libraries without position-independent code on architectures where that's possible, i.e. on x86 โจ
If type is pie, code generation produces an -fpie executable. This gives similar optimizations to exec, except that -fpie is not disabled if it was specified at compilation time ๐ฆ
If type is rel, the compiler assumes that incremental linking is happening. The sections containing intermediate code for link-time optimization are merged, pre-optimized, and output to the resulting object file. On top of that, if -ffat-lto-objects is specified, binary code is produced for future non-LTO linking. The object file from incremental linking is smaller than a static library made from the same object files. At link time, the result of incremental linking also loads faster than a static library, assuming most of the objects in the library get used ๐ฅ
Finally, nolto-rel configures the compiler for incremental linking where code generation is forced, a final binary is produced, and the intermediate code for later link-time optimization 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. Heads up: with current interfaces to GNU Binutils, it is however not possible to incrementally link LTO objects and non-LTO objects into a single mixed object file. If any object file in an incremental link can't be used for link-time optimization, the linker plugin issues a warning and uses nolto-rel. To keep whole program optimization, it's recommended to link such objects into a static library instead. Alternatively, it is possible to use H.J. Lu's binutils, which has 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โ search the library namedlibrarywhen linking ๐ The second form, with the library as a separate argument, is only there for POSIX compliance and is not recommended ๐
The -l option gets 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. Those directories include several standard system directories plus any you specify with -L ๐
Static libraries are archives of object files and have file names like liblibrary.a. Some targets also support shared libraries, which typically have names like liblibrary.so. If both static and shared libraries are found, the linker prefers linking with the shared library unless the -static option is used.
It makes a difference where in the command you write this option! The linker searches and processes libraries and object files in the order they are specified. So foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded ๐
-lobjcโ you need this special case of the-loption to link an Objective-C or Objective-C++ program ๐-nostartfilesโ don't use the standard system startup files when linking ๐ The standard system libraries are still used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used.-nodefaultlibsโ don't use the standard system libraries when linking ๐ Only the libraries you specify get passed to the linker, and options specifying linkage of the system libraries, like-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. When this option is specified, these entry points should be supplied through some other mechanism ๐ซ
-nolibcโ don't use the C library or the system libraries tightly coupled with it when linking ๐งธ It still links with the startup files, libgcc, or toolchain-provided language support libraries such aslibgnat,libgfortran, orlibstdc++, unless options preventing their inclusion are used as well. This typically removes-lcfrom the link command line, along with the system libraries that normally go with it and become meaningless when a C library is assumed to be absent, for example-lpthreador-lmin some configurations. This is intended for bare-board targets where 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 get passed to the linker. Options specifying linkage of the system libraries, like-static-libgccor-shared-libgcc, are ignored.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These entries are usually resolved by entries in libc. When this option is specified, these entry points should be supplied through some other mechanism ๐ซ
One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines which GCC uses to work around shortcomings of particular machines or to meet special needs for some languages ๐งฉ
In most cases you still need libgcc.a, even when you want to avoid other standard libraries. In other words, when you specify -nostdlib or -nodefaultlibs, you should usually specify -lgcc as well. This makes sure you have no unresolved references to internal GCC library subroutines. (An example of such an internal subroutine is "__main", which is used to make sure C++ constructors get called โจ)
-e entry,--entry=entryโ specifies that the program entry point isentry๐ฏ The argument is interpreted by the linker. The GNU linker accepts either a symbol name or an address.-pieโ produces a dynamically linked position independent executable on targets that support it ๐ฆ For predictable results, you must also specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you specify this linker option.-no-pieโ don't produce a dynamically linked position independent executable ๐ โโ๏ธ-static-pieโ produces a static position independent executable on targets that support it ๐ A static position independent executable is similar to a static executable, but it can be loaded at any address without a dynamic linker. For predictable results, you must also specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you specify this linker option.-pthreadโ okay so this one links with the POSIX threads library ๐งต It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. Heads up, bestie: on some targets it also sets flags for the preprocessor, so use it consistently for both compiling and linking ๐-rโ produces a relocatable object as output. This is also known as partial linking ๐งฉ-rdynamicโ passes the flag-export-dynamicto the ELF linker on targets that support it ๐ This tells the linker to add all symbols, not just the used ones, to the dynamic symbol table. It's needed for some uses ofdlopen, or if you want backtraces from inside a program ๐ช-sโ removes all symbol table and relocation information from the executable โ๏ธ-staticโ on systems that support dynamic linking, this overrides-pieand prevents linking with the shared libraries ๐ง On other systems, it does absolutely nothing.-sharedโ produces a shared object that can be linked with other objects to form an executable. Not all systems support this, so heads up ๐ For predictable results, you must also specify the same set of options you used for compilation (-fpic,-fPIC, or model suboptions) when you use this linker option.[1]-shared-libgcc,-static-libgccโ on systems that provide libgcc as a shared library, these force the use of the shared or static version, respectively ๐ If no shared version of libgcc was built when the compiler was configured, these have no effect.
There are a few situations where an application should use the shared libgcc instead of the static version. The most common one is when the app wants to throw and catch exceptions across different shared libraries. In that case, each of the libraries and the application itself should use the shared libgcc ๐ง
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable, because C++ programs typically use exceptions. That's the right move, periodt ๐
If instead you use the GCC driver to create shared libraries, they might not always get linked with the shared libgcc ๐คทโโ๏ธ If GCC finds at 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, so it links with the static version of libgcc by default. This lets exceptions propagate through such shared libraries without incurring relocation costs at library load time โจ
Not optional, bestie: 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, this links against the shared version. The-static-libasanoption directs 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, this links against the shared version. The-static-libtsanoption directs 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, this links against the shared version. The-static-liblsanoption directs 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, this links against the shared version. The-static-libubsanoption directs the GCC driver to link libubsan statically, without necessarily linking other libraries statically.-static-libstdc++โ when theg++program links a C++ program, it normally links against libstdc++ automatically ๐ If libstdc++ is available as a shared library, and-staticisn't used, this links against the shared version, which is normally fine. Sometimes, though, it's useful to freeze the version of libstdc++ your program uses without going all the way to a fully static link. The-static-libstdc++option directs theg++driver to link libstdc++ statically, without necessarily linking other libraries statically.-symbolicโ binds references to global symbols when building a shared object ๐ฏ It warns about any unresolved references (unless overridden by the link editor option-Xlinker -z -Xlinker defs). Only a few systems support this option.-T scriptโ uses script as the linker script ๐ This is supported by most systems using the GNU linker. On some targets, like bare-board targets without an operating system,-Tmay be required when linking to avoid references to undefined symbols.-Xlinker optionโ passes option on to the linker. It's perfect for system-specific linker options that GCC doesn't recognize ๐ ๏ธ
If you want to pass an option that takes a separate argument, you must use -Xlinker twice: once for the option and once for the argument. For example, to pass -assert definitions, you must write -Xlinker -assert -Xlinker definitions. Writing -Xlinker "-assert definitions" does not work, because it passes the whole string as a single argument, which is not what the linker expects ๐
โโ๏ธ
With the GNU linker, it's usually way easier to pass arguments to linker options using the option=value syntax instead of separate arguments. For example, you can specify -Xlinker -Map=output.map rather than -Xlinker -Map -Xlinker output.map. Other linkers may not support this syntax for command-line options.
-Wl,optionโ passes option to the linker too ๐ If option contains commas, it gets split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example,-Wl,-Map,output.mappasses-Map output.mapto the linker. When using the GNU linker, you can also get the same effect with-Wl,-Map=output.map.-u symbolโ pretends the symbol symbol is undefined, which forces linking of library modules that define it ๐ซ You can use-umultiple times with different symbols to force loading of additional library modules.-z keywordโ-zgets passed directly on to the linker, along with the keyword. Check the documentation for your linker for permitted values and what they mean ๐
โจ Options for Directory Search โจ
These options specify directories to search for header files, for libraries and for parts of the compiler ๐ธ
-I dir,-iquote dir,-isystem dir,-idirafter dirโ adds the directory dir to the list of directories searched for header files during preprocessing ๐๏ธ If dir begins with=or$SYSROOT, then the=or$SYSROOTis replaced by the sysroot prefix. See--sysrootand-isysroot.
Directories given with -iquote only apply to the quote form of the directive, #include "file". Directories given with -I, -isystem, or -idirafter apply to the lookup for both #include "file" and #include <file> directives.
You can mix and match any number of these options on the command line to search for header files in several directories. The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first.
- For the quote form of the include directive, the directories specified by
-iquoteoptions are searched in left-to-right order, as they appear on the command line. - Directories specified with
-Ioptions are scanned in left-to-right order. - Directories specified with
-isystemoptions are scanned in left-to-right order. - Standard system directories are scanned.
- Directories specified with
-idirafteroptions are scanned in left-to-right order.
You can use -I to override a system header file and swap in your own version, since these directories get searched before the standard system header file directories. However, you should not use this option to add directories that contain vendor-supplied system header files. Use -isystem for that ๐ซ
The -isystem and -idirafter options also mark the directory as a system directory, so it gets the same special treatment that's applied to the standard system directories ๐
If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option is ignored. The directory is still searched, but as a system directory at its normal position in the system include chain. This is to make sure GCC's procedure for fixing buggy system headers and the ordering for the #include_next directive don't get changed by accident. If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options ๐
-I-โ splits the include path ๐ This option has been deprecated.
Please use-iquoteinstead for-Idirectories before the-I-, and remove the-I-option.
Any directories specified with -I options before -I- are searched only for headers requested with #include "file". They are not searched for #include <file>. If additional directories are specified with -I options after the -I-, those directories are searched for all #include directives โจ
In addition, -I- is lowkey a plot twist ๐. It stops the directory of the current file from being the first directory searched for #include "file", and there is no way to override this effect of -I- ๐, so use it with care, bestie.
-iprefix prefixโ Setsprefixas the prefix for any-iwithprefixoptions that come after it ๐ธ. If the prefix is a directory, make sure you include the final/.-iwithprefix dir,-iwithprefixbefore dirโ Tacksdironto the prefix you set earlier with-iprefixand adds the result to the include search path โจ.-iwithprefixbeforeputs it in the same spot-Iwould, while-iwithprefixputs it where-idirafterwould.-isysroot dirโ This one is basically the--sysrootoption, but it only affects header files ๐. The exception is Darwin targets, where it covers headers and libraries. Check out the--sysrootoption for more deets.-imultilib dirโ Usesdiras a subdirectory of the directory that holds target-specific C++ headers ๐ง.-nostdincโ Doesn't search the standard system directories for header files ๐ โโ๏ธ. Only the directories you explicitly pass with-I,-iquote,-isystem, and/or-idirafterget searched, plus the directory of the current file if it's relevant.-nostdinc++โ Skips the C++-specific standard directories when hunting for header files, but still searches the other standard ones ๐. (This one gets used when building the C++ library.)-iplugindir=dirโ Sets the directory to search for plugins that get passed with-fplugin=nameinstead of-fplugin=path/name.so. This one isn't really meant for you to use ๐, it's only passed along by the driver.-Ldirโ Adds directorydirto the list of directories searched for-l๐.-Bprefixโ This is how you tell the compiler where to find its own stuff: executables, libraries, include files, and data files ๐ .
The compiler driver program runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for each program it tries to run, both with and without machine/version/ for the corresponding target machine and compiler version ๐งฉ.
For each subprogram, the driver first tries the -B prefix, if there is one. If that name isn't found, or if -B isn't specified, it tries two standard prefixes, /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those turns up a file, the unmodified program name gets searched for using the directories in your PATH environment variable ๐ฃ๏ธ.
The compiler checks whether the path given by -B refers to a directory, and if necessary it adds a directory separator character at the end of the path.
-B prefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into -L options for the linker. They also apply to include files in the preprocessor, because the compiler translates these options into -isystem options for the preprocessor. In this case, the compiler appends include to the prefix.
The runtime support file libgcc.a can also be searched for using the -B prefix, if needed. If it isn't found there, the two standard prefixes above are tried, and that's all. The file gets left out of the link if it isn't found by those means.
Another way to specify a prefix much like the -B prefix is to use the environment variable GCC_EXEC_PREFIX ๐.
As a special kludge (no cap, it's a weird one ๐), if the path given by -B is [dir/]stageN/, where N is a number in the range 0 to 9, then it gets replaced by [dir/]include. This is to help with boot-strapping the compiler ๐ฅพ.
-no-canonical-prefixesโ Don't expand any symbolic links, resolve references to/../or/./, or make the path absolute when generating a relative prefix ๐ โโ๏ธ.--sysroot=dirโ Usesdiras the logical root directory for headers and libraries ๐ณ. For example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it searchesdir/usr/includeanddir/usr/libinstead.
If you use both this option and -isysroot, 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 part of --sysroot still works, but the library part does not.
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory given with--sysroot, depending on the other options you use. That means headers might show up indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off adding that suffix ๐ซ.
โจ Options for Code Generation Conventions โจ
These machine-independent options control the interface conventions used in code generation ๐ .
Most of them have both positive and negative forms, and the negative form of -ffoo is -fno-foo. In the list below, only one of the forms is shown, the one that is not the default. You can figure out the other form by either removing no- or adding it ๐ง .
-fstack-reuse=reuse-levelโ 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 it 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 does not overlap with it.
โ ๏ธ Legacy code that extends local lifetime is likely to break with the stack reuse optimization. Be careful, bestie ๐.
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 does not overlap with it. However, some of the legacy code relies on the behavior of older compilers, in which temporaries' stack space is not reused, so aggressive stack reuse can lead to runtime errors ๐ญ. This option is used to control the temporary stack reuse optimization.
-ftrapvโ This 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โ This tells the compiler to assume that signed arithmetic overflow of addition, subtraction, and multiplication wraps around using twos-complement representation ๐. This flag enables some optimizations and disables others. The options-ftrapvand-fwrapvoverride each other, so 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-pointerโ This tells the compiler to assume that pointer arithmetic overflow on addition and subtraction wraps around using twos-complement representation ๐งญ. This flag disables some optimizations which assume pointer overflow is invalid.-fstrict-overflowโ This implies-fno-wrapv -fno-wrapv-pointer, and when negated it implies-fwrapv -fwrapv-pointer๐.-fexceptionsโ Enables exception handling ๐ก๏ธ. It generates the extra code needed to propagate exceptions. For some targets, this implies GCC generates frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution.
If you don't specify this option, GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that don't normally require it. You may still need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++ ๐ค. You may also wish to disable this option if you're compiling older C++ programs that don't use exception handling.
-fnon-call-exceptionsโ Generates code that allows trapping instructions to throw exceptions โก. Note that this requires platform-specific runtime support, which does not exist everywhere. Moreover, it only allows trapping instructions to throw exceptions, i.e. memory references or floating-point instructions. It does not allow exceptions to be thrown from arbitrary signal handlers such as "SIGALRM". This enables-fexceptions.-fdelete-dead-exceptions: okay so this one is lowkey iconic ๐ . Instructions that might throw exceptions but don't actually contribute to what the program does can be optimized away โจ. It doesn't affect calls to functions unless they have thepureorconstattributes. It's on by default for the Ada and C++ compilers because the language specs allow it ๐ธ. Optimization passes that remove dead exceptions are switched on separately at different optimization levels ๐ฅ.-funwind-tables: this is giving similar to-fexceptions, except it only generates any static data that's needed and doesn't touch the generated code in any other way ๐ฆ. You normally don't have to turn it on yourself. A language processor that needs this handling enables it for you ๐ซถ.-fasynchronous-unwind-tables: generates an unwind table in DWARF format, if the target machine supports it ๐. The table is exact at each instruction boundary, so it can be used for stack unwinding from asynchronous events (like a debugger or a garbage collector) ๐ง.-fno-gnu-unique: okay this one's a little drama ๐. On systems with a recent GNU assembler and C library, the C++ compiler uses theSTB_GNU_UNIQUEbinding so that definitions of template static data members and static local variables in inline functions stay unique, even whenRTLD_LOCALis involved. That's needed to avoid problems with a library used by two differentRTLD_LOCALplugins, where one depends on a definition in one plugin and the other disagrees about how the symbol is bound ๐.
But here's the tea: this causes dlclose to be ignored for affected DSOs. If your program relies on reinitializing a DSO through dlclose and dlopen, you can use -fno-gnu-unique ๐.
-fpcc-struct-return: returnsshortstructandunionvalues in memory, like the longer ones, instead of in registers ๐งธ. It's less efficient, but it lets GCC-compiled files play nicely with files built by other compilers, especially the Portable C Compiler (pcc) ๐ค.
The exact convention for returning structures in memory depends on the target configuration macros. Short structures and unions are the ones whose size and alignment match some integer type ๐.
โ ๏ธ Warning: code compiled with-fpcc-struct-returnis not binary compatible with code compiled with-freg-struct-return. Use it to conform to a non-default application binary interface ๐ โโ๏ธ.
-freg-struct-return: returnsstructandunionvalues in registers when possible ๐. It's more efficient for small structures than-fpcc-struct-returnโจ.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever convention is standard for the target. If there's no standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases, we get to choose the standard, and we went with the more efficient register return alternative ๐.
โ ๏ธ Warning: code compiled with-freg-struct-returnis not binary compatible with code compiled with-fpcc-struct-return. Use it to conform to a non-default application binary interface ๐ .
-fshort-enums: gives anenumtype only as many bytes as it needs for its declared range of values ๐ท. Specifically, theenumtype ends up equivalent to the smallest integer type that has enough room ๐ฆ.
โ ๏ธ Warning: the -fshort-enums switch makes GCC generate code that isn't binary compatible with code generated without it. Use it to conform to a non-default application binary interface ๐ญ.
-fshort-wchar: overrides the underlying type forwchar_tso it'sshort unsigned intinstead of the target's default ๐ญ. This one is super useful for building programs that run under WINE ๐.
โ ๏ธ Warning: the -fshort-wchar switch makes GCC generate code that isn't binary compatible with code generated without it. Use it to conform to a non-default application binary interface ๐.
-fcommon: in C code, this controls where global variables defined without an initializer get placed. These are called tentative definitions in the C standard ๐ง. They're different from declarations using theexternkeyword, 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 if the same variable is accidentally defined in more than one compilation unit, you get a multiple-definition error. Honestly a good safety net ๐.
-fcommon puts uninitialized global variables in a common block instead. That lets the linker resolve all the tentative definitions of the same variable across different compilation units to the same object, or to a non-tentative definition. This behavior is inconsistent with C++, and on many targets it comes with a speed and code size penalty on global variable references ๐ฌ. It's mainly useful for getting legacy code to link without errors ๐ซ .
-fno-ident: ignores the#identdirective ๐.-finhibit-size-directive: don't output a.sizeassembler directive, or anything else that would cause trouble if the function gets split in the middle and the two halves end up far apart in memory ๐งญ. This option is used when compilingcrtstuff.c. 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 mostly for people who actually need to read the generated assembly, like when debugging the compiler itself ๐งโ๐ป.
-fno-verbose-asm, which is the default, leaves the extra info out, and that's handy when you're comparing two assembler files ๐.
The added comments include:
- information on the compiler version and command-line options,
- the source code lines associated with the assembly instructions, in the form
FILENAME:LINENUMBER:CONTENT OF LINE, - hints on which high-level expressions correspond to the various assembly instruction operands.
For example, given this C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
Compiling to (x86_64) assembly via -S and emitting the result straight to stdout via -o - looks like this:
gcc -S test.c -fverbose-asm -Os -o -
And it gives output similar to this ๐งโโ๏ธ:
.file "test.c"
# GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
[...snip...]
# options passed:
[...snip...]
.text
.globl test
.type test, @function
test:
.LFB0:
.cfi_startproc
# test.c:4: int total = 0;
xorl %eax, %eax # <retval>
# test.c:6: for (i = 0; i < n; i++)
xorl %edx, %edx # i
.L2:
# test.c:6: for (i = 0; i < n; i++)
cmpl %edi, %edx # n, i
jge .L5 #,
# test.c:7: total += i * i;
movl %edx, %ecx # i, tmp92
imull %edx, %ecx # i, tmp92
# test.c:6: for (i = 0; i < n; i++)
incl %edx # i
# test.c:7: total += i * i;
addl %ecx, %eax # tmp92, <retval>
jmp .L2 #
.L5:
# test.c:10: }
ret
.cfi_endproc
.LFE0:
.size test, .-test
.ident "GCC: (GNU) 7.0.0 20160809 (experimental)"
.section .note.GNU-stack,"",@progbits
The comments are meant for humans rather than machines, so the precise format of them is subject to change ๐ซถ.
-frecord-gcc-switches: this makes the command line used to invoke the compiler get recorded into the object file being created ๐ผ. It's only implemented on some targets, and the exact format of the recording depends on the target and the binary file format. Usually it takes the form of a section containing ASCII text ๐ค. This switch is related to-fverbose-asm, but that one only records info in the assembler output file as comments, so it never reaches the object file ๐ . See also-grecord-gcc-switchesfor another way of storing compiler options in the object file ๐.
-fpic: generates position-independent code (PIC) that's suitable for a shared library, if the target machine supports it ๐. This code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts. (The dynamic loader isn't part of GCC; it's part of the operating system ๐ฅ๏ธ.) If the GOT size for the linked executable goes past a machine-specific maximum, the linker gives you an error saying-fpicdoesn't work. In that case, recompile with-fPICinstead ๐ค. (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit ๐.)
Position-independent code needs special support, so it only works on certain machines. For the x86, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent ๐ฆ.
When this flag is set, the macros __pic__ and __PIC__ are defined to 1 ๐ธ.
-fPIC: if the target machine supports it, emits position-independent code that's suitable for dynamic linking and avoids any limit on the size of the global offset table ๐ฅ. This option makes a difference on AArch64, m68k, PowerPC and SPARC ๐.
Position-independent code needs special support, so it only works on certain machines ๐.
When this flag is set, the macros __pic__ and __PIC__ are defined to 2 โจ.
-fpie,-fPIEโ okay so these are the cousins of-fpicand-fPIC๐ฆ, but the position-independent code they make can ONLY be linked into executables ๐ . You'll usually reach for these when compiling stuff that's getting linked with the-pieGCC option โจ.-fpieand-fPIEboth define the macros__pie__and__PIE__๐. They have the value1for-fpieand2for-fPIE๐ฅ.
-fno-pltโ bestie, don't go through the PLT ๐ for external function calls in position-independent code ๐. Instead, grab the callee address at the call sites from the GOT and branch to it ๐ฆ. It's more efficient because it kills the PLT stubs and lets the optimizations see the GOT loads ๐. On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in a specific register, this gives the compiler more register allocation freedom ๐ . Lazy binding needs the PLT though, so with-fno-pltall external symbols get resolved at load time ๐ธ.- Alternatively, the function attribute
nopltcan be used to avoid calls through the PLT for specific external functions ๐ง. - In position-dependent code, a few targets also convert calls to functions marked to not use the PLT into calls that go through the GOT instead ๐.
- Alternatively, the function attribute
-fno-jump-tablesโ don't use jump tables forswitchstatements, even where they'd be more efficient than other code generation strategies ๐. This is useful alongside-fpicor-fPICwhen you're building code that forms part of a dynamic linker and can't reference the address of a jump table ๐งฉ. On some targets, jump tables don't need a GOT, so this option isn't needed there โจ.-fno-bit-testsโ don't use bit tests forswitchstatements, even where they'd be more efficient than other code generation strategies ๐.-ffixed-regโ treat the register namedregas a fixed register ๐. Generated code should never refer to it, except maybe as a stack pointer, frame pointer, or in some other fixed role ๐งฑ.regmust be the name of a register. The accepted register names are machine-specific and are defined in theREGISTER_NAMESmacro in the machine description macro file ๐๏ธ.- This flag has no negative form, because it's a three-way choice ๐.
-fcall-used-regโ treatregas an allocable register that gets clobbered by function calls ๐ธ. It can be allocated for temporaries or variables that don't live across a call. Functions compiled this way do not save and restore the registerreg๐ .- It is an error to use this flag with the frame pointer or stack pointer โ.
- Using this flag for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results ๐.
- This flag has no negative form, because it's a three-way choice ๐.
-fcall-saved-regโ treatregas an allocable register that's saved by functions ๐. It can be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restoreregif they use it ๐พ.- It is an error to use this flag with the frame pointer or stack pointer โ.
- Using this flag for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results ๐.
- A different sort of disaster results from using this flag on a register where function values may be returned ๐.
- This flag has no negative form, because it's a three-way choice ๐.
-fpack-struct[=n]โ without a value, pack all structure members together with no holes ๐ฆ. When you give a value (which must be a small power of two), members get packed according to that value, which is the maximum alignment. Objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location ๐งฉ.
Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch ๐จ. 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 use is helping to link with legacy assembly code ๐๏ธ.
Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch ๐จ. Use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch ๐.
-ftls-model=modelโ alter the thread-local storage model that's used ๐งต. Themodelargument should be one ofglobal-dynamic,local-dynamic,initial-execorlocal-exec๐. The choice is subject to optimization, though: the compiler may use a more efficient model for symbols not visible outside the translation unit, or if-fpicisn't given on the command line โจ.- The default without
-fpicisinitial-exec; with-fpicthe default isglobal-dynamic๐.
- The default without
-ftrampolinesโ for targets that normally need trampolines for nested functions, always generate them instead of using descriptors ๐. Otherwise, for targets that don't need them, like for example HP-PA or IA-64, it does nothing ๐คท.- A trampoline is a small piece of code that's 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 ๐ง . That means the stack has to be made executable for the program to work properly โ ๏ธ.
-fno-trampolinesis enabled by default on a language-by-language basis, so the compiler can avoid generating trampolines if it computes that's safe and replace them with descriptors ๐ฆ. Descriptors are made up of data only, but the generated code must be prepared to deal with them ๐ . As of this writing,-fno-trampolinesis enabled by default only for Ada ๐.- Code compiled with
-ftrampolinesand code compiled with-fno-trampolinesare not binary compatible if nested functions are present โ ๏ธ. This option must therefore be used on a program-wide basis and be manipulated with extreme care ๐ซฃ. - For languages other than Ada, the
-ftrampolinesand-fno-trampolinesoptions currently have no effect, and trampolines are always generated on platforms that need them for nested functions ๐.
-fvisibility=[default|internal|hidden|protected]โ set the default ELF image symbol visibility to the specified option. All symbols are marked with this unless they're overridden within the code ๐. Using this can very substantially improve linking and load times of shared object libraries, produce more optimized code, provide 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,
defaultalways means public, i.e., available to be linked against from outside the shared object ๐ฃ.protectedandinternalare pretty useless in real-world usage, so the only other commonly used option ishidden๐. If-fvisibilityisn't specified, the default isdefault, i.e., make every symbol public ๐ธ. - A good explanation of the benefits of ensuring ELF symbols have the correct visibility is given in "How To Write Shared Libraries" by Ulrich Drepper, which can be found at
<https://www.akkadia.org/drepper/>๐. However, a superior solution made possible by this option, instead of marking things hidden when the default is public, is to make the default hidden and mark things public ๐ง . This is the norm with DLLs on Windows, and with-fvisibility=hiddenand__attribute__ ((visibility("default")))instead of__declspec(dllexport), you get almost identical semantics with identical syntax ๐ช. This is a great boon to those working with cross-platform projects ๐ซถ. - For those adding visibility support to existing code, you may find
#pragma GCC visibilityuseful ๐ ๏ธ. It works by enclosing the declarations you want to set visibility for with, for example,#pragma GCC visibility push(hidden)and#pragma GCC visibility pop๐. Bear in mind that symbol visibility should be viewed as part of the API interface contract, so all new code should always specify visibility when it isn't the default ๐. Declarations only for use within the local DSO should always be marked explicitly ashiddento avoid PLT indirection overheads, and making this abundantly clear also aids readability and self-documentation of the code ๐ . Note that due to ISO C++ specification requirements,operator newandoperator deletemust always be of default visibility โ ๏ธ. - Be aware that headers from outside your project, in particular system headers and headers from any other library you use, may not be expecting to be compiled with visibility other than the default ๐. You may need to explicitly say
#pragma GCC visibility push(default)before including any such headers ๐ซ . externdeclarations are not affected by-fvisibility, so a lot of code can be recompiled with-fvisibility=hiddenwith no modifications โจ. However, this means calls toexternfunctions with no explicit visibility use the PLT, so it's more effective to use__attribute ((visibility))and/or#pragma GCC visibilityto tell the compiler whichexterndeclarations should be treated as hidden ๐ง.-fvisibilitydoes affect C++ vague linkage entities ๐งฉ. This means that, for instance, an exception class that is thrown between DSOs must be explicitly marked with default visibility so that thetype_infonodes are unified between the DSOs ๐.- An overview of these techniques, their benefits, and how to use them is at
<https://gcc.gnu.org/wiki/Visibility>๐.
- Despite the nomenclature,
-fstrict-volatile-bitfieldsโ ๐ Turn this on when you want volatile bit-fields (or other struct fields, though the compiler usually respects those types anyway) to be read or written in a single access as wide as the field's type, lined up to natural alignment when possible. Targets with memory-mapped peripheral registers might need every access to be 16 bits wide. If you declare those bit-fields as"unsigned short"(assumingshortis 16 bits on those targets), GCC sticks to 16-bit accesses instead of grabbing a fancier 32-bit one. ๐
If this option is disabled, the compiler goes for the most efficient instruction ๐โโ๏ธ. In the example above, that could be a 32-bit load, even though it touches bytes that don't hold 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 on a structure field, there may be no single read or write that's correctly aligned for the target machine. Then GCC falls back to generating multiple accesses instead of code that would fault or truncate the result at run time. ๐ซถ
๐จ Note: Because of restrictions in the C/C++11 memory model, write accesses aren't allowed to touch non bit-field members. So it's recommended to define all bits of the field's type as bit-field members. Don't skip this one, bestie!
The default value of this option is set by the application binary interface for the target processor. ๐ธ
-fsync-libcallsโ ๐ 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.
This one is enabled by default, so the only useful form is -fno-sync-libcalls. It's used in the implementation of the libatomic runtime library. โจ
โจ GCC Developer Options โจ
This section is all about command-line options that mostly matter to GCC developers ๐งโ๐ป. That includes options for compiler testing, digging into compiler bugs, and compile-time performance problems. You'll find options that produce debug dumps at various points in the compilation, options that print stats like memory use and execution time, and options that print info about GCC's configuration, like where it searches for libraries. ๐ You should rarely need any of these for ordinary compiling and linking, so don't stress! ๐
Lots of developer options that make GCC dump output to a file take an optional =filename suffix. You can specify stdout or - to dump to standard output, and stderr for standard error. ๐ค
If =filename is left off, GCC builds a default dump file name by sticking together the base dump file name, a pass number, a phase letter, and the pass name. The base dump file name is the name of the output file the compiler produced if you explicitly specified one and it isn't an executable. Otherwise, it's the source file name. ๐
The pass number comes from the order passes get registered with the compiler's pass manager. That's usually the same as the order they run in, but passes registered by plugins, target-specific passes, or passes that get registered late are numbered higher than the pass named final, even if they actually run earlier. ๐คฏ
The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree). The files get created in the directory of the output file. ๐
-fcallgraph-info,-fcallgraph-info=MARKERSโ ๐ธ๏ธ Makes the compiler output callgraph information for the program, one file per object file. The info is generated in the common VCG format. You can decorate it with extra per-node and/or per-edge info by passing a comma-separated list of markers. With thesumarker, the callgraph gets stack usage info, which is equivalent to-fstack-usage. With thedamarker, it gets info about dynamically allocated objects. ๐ง
When you compile with -flto, no callgraph info is output alongside the object file. At LTO link time, -fcallgraph-info may generate multiple callgraph info files next to the intermediate LTO output files. ๐
-dletters,-fdump-rtl-pass,-fdump-rtl-pass=filenameโ ๐๏ธ Tells GCC to make debugging dumps during compilation at the times specified by the letters. This is for debugging the RTL-based passes of the compiler. ๐
Some -dletters switches mean something different when you use -E 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 the pass and letters, and what they mean: ๐
-fdump-rtl-alignmentsโ Dumps after branch alignments have been computed. ๐-fdump-rtl-asmconsโ Dumps after fixing RTL statements that have unsatisfied in/out constraints. ๐ง-fdump-rtl-auto_inc_decโ Dumps after auto-inc-dec discovery. This pass only runs on architectures that have auto inc or auto dec instructions. ๐๏ธ-fdump-rtl-barriersโ Dumps after cleaning up the barrier instructions. ๐งน-fdump-rtl-bbpartโ Dumps after partitioning hot and cold basic blocks. ๐ฅ๐ง-fdump-rtl-bbroโ Dumps after block reordering. ๐-fdump-rtl-btl1,-fdump-rtl-btl2โ These two enable dumping after the two branch target load optimization passes. ๐ฏ-fdump-rtl-bypassโ Dumps after jump bypassing and control flow optimizations. ๐ฆ-fdump-rtl-combineโ Dumps after the RTL instruction combination pass. ๐งฉ-fdump-rtl-compgotosโ Dumps after duplicating the computed gotos. ๐ฆถ-fdump-rtl-ce1,-fdump-rtl-ce2,-fdump-rtl-ce3โ These three enable dumping after the three if conversion passes. ๐-fdump-rtl-cprop_hardregโ Dumps after hard register copy propagation. ๐-fdump-rtl-csaโ Dumps after combining stack adjustments. ๐ฅ-fdump-rtl-cse1,-fdump-rtl-cse2โ These two enable dumping after the two common subexpression elimination passes. ๐-fdump-rtl-dceโ Dumps after the standalone dead code elimination passes. ๐-fdump-rtl-dbrโ Dumps after delayed branch scheduling. โณ-fdump-rtl-dce1,-fdump-rtl-dce2โ These two enable dumping after the two dead store elimination passes. ๐๏ธ-fdump-rtl-ehโ Dumps after finalization of EH handling code. ๐-fdump-rtl-eh_rangesโ Dumps after conversion of EH handling range regions. ๐บ๏ธ-fdump-rtl-expandโ Dumps after RTL generation. ๐ฑ-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ These two enable dumping after the two forward propagation passes. โก๏ธ-fdump-rtl-gcse1,-fdump-rtl-gcse2โ These two enable dumping after global common subexpression elimination. ๐-fdump-rtl-init-regsโ Dumps after the initialization of the registers. ๐-fdump-rtl-initvalsโ Dumps after the computation of the initial value sets. ๐งฎ-fdump-rtl-into_cfglayoutโ Dumps after converting to cfglayout mode. ๐งญ-fdump-rtl-iraโ Dumps after iterated register allocation. ๐๏ธ-fdump-rtl-jumpโ Dumps after the second jump optimization. ๐ฆ-fdump-rtl-loop2โ Enables dumping after the RTL loop optimization passes. ๐-fdump-rtl-machโ Dumps after the machine dependent reorganization pass, if that pass exists. ๐ค-fdump-rtl-mode_swโ Dumps after removing redundant mode switches. โ๏ธ-fdump-rtl-rnregโ Dumps after register renumbering. ๐ข-fdump-rtl-outof_cfglayoutโ Dumps after converting from cfglayout mode. ๐งญ-fdump-rtl-peephole2โ Dumps after the peephole pass. ๐ฌ-fdump-rtl-postreloadโ Dumps after post-reload optimizations. ๐-fdump-rtl-pro_and_epilogueโ Dumps after generating the function prologues and epilogues. ๐ฌ-fdump-rtl-sched1,-fdump-rtl-sched2โ These two enable dumping after the basic block scheduling passes. ๐-fdump-rtl-reeโ Dumps after sign/zero extension elimination. ๐ข-fdump-rtl-seqabstrโ Dumps after common sequence discovery. ๐งต-fdump-rtl-shortenโ Dumps after shortening branches. ๐-fdump-rtl-siblingโ Dumps after sibling call optimizations. ๐ฏ-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ These options enable dumping after five rounds of instruction splitting. โ๏ธ-fdump-rtl-smsโ Dumps after modulo scheduling. This pass only runs on some architectures. ๐ถ-fdump-rtl-stackโ Dumps after converting GCC's "flat register file" registers to the x87's stack-like registers. This pass only runs on x86 variants. ๐ฅ-fdump-rtl-subreg1,-fdump-rtl-subreg2โ These 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 dumps are defined but always produce empty files. ๐ป
โ ๏ธ Heads up: The five dumps above are defined, but they will always give you empty files. Don't waste your time staring at them! ๐
-da,-fdump-rtl-allโ Produces 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 ๐ง okay so this one annotates the assembler output with a comment showing which pattern and alternative got picked, and it also prints the length and cost of each instruction โจ
-dP๐ dumps the RTL into the assembler output as a comment right before each instruction, and it also turns on-dpannotation, so you get both, bestie ๐ซถ-dx๐ฆ skips the full compile and just generates RTL for a function. It's usually paired with-fdump-rtl-expand๐ธ
Debug dumps are next, and they're giving main character energy ๐
-fdump-debug๐ dumps the debugging info generated during the debug generation phase-fdump-earlydebug๐ same deal, but for the early debug generation phase-fdump-noaddr๐ when you're doing debugging dumps, this suppresses address output. It makes it way more doable todiffdumps from different compiler binaries and/or different text / bss / data / heap / stack / dso start locations, and honestly that's so smart ๐ง-freport-bug๐ญ if an internal compiler error (ICE) hits, this gathers up debug info and dumps it into a temporary file so the bug report isn't empty-fdump-unnumbered๐ข suppresses instruction numbers and address output in debugging dumps. This is perfect fordiff-ing dumps from compiler invocations with different options, especially with and without-g๐-fdump-unnumbered-links๐ in debugging dumps (see the-doption above), this suppresses the instruction numbers for the links to the previous and next instructions in a sequence-fdump-ipa-switch,-fdump-ipa-switch-options๐ controls dumping the inter-procedural analysis language tree at various stages, and the dump goes into a file. The file name is made by appending a switch-specific suffix to the source file name, and the file lands in the same directory as the output file. These are the dumps you can ask for:allโ enables all inter-procedural analysis dumps ๐cgraphโ dumps info about call-graph optimization, unused function removal, and inlining decisionsinlineโ dumps after function inlining
Plus, you can tack on -optimized, -missed, -note, and -all. They mean the same thing as they do for -fopt-info, and the default is -optimized โจ
For example, -fdump-ipa-inline-optimized-missed will emit info on the callsites that got inlined, along with the callsites that didn't. ๐ง
By default, the dump has messages about successful optimizations (same as -optimized) together with the low-level details about the analysis.
-fdump-lang๐ท dumps language-specific info. The file name is made by appending.langto the source file name-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filename๐ control dumping language-specific info. The options and filename parts work exactly like they do in the-fdump-treeoption. Here are the switch values:allโ enables all language-specific dumpsclassโ dumps class hierarchy info. Virtual table info gets emitted unlessslimis specified. This is C++ only ๐ซถmoduleโ dumps module info. The optionslineno(locations),graph(reachability),blocks(clusters),uid(serialization),alias(mergeable),asmname(Elrond),eh(mapper) &vops(macros) can add extra info. This is C++ only toorawโ dumps the raw internal tree data. C++ only ๐
-fdump-passes๐ prints the list of optimization passes that your current command-line options turn on and off, and it prints it on stderr-fdump-statistics-option๐ enables and controls dumping pass statistics into a separate file. The file name gets a suffix ending in.statisticsappended to the source file name, and it's created in the same directory as the output file. If you use the-optionform,-statssums the counters over the whole compilation unit, while-detailsdumps every event as the passes generate them. With no option at all, the counters get summed for each function compiled.
๐ณ Tree dumps
-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filename๐ณ control the dumping at various stages of processing the intermediate language tree, and the output goes to a file. If you use the-optionsform, options is a list of--separated options that control the details of the dump. Not every option applies to every dump, so the ones that don't make sense just get ignored. These are the options you can use:address๐ prints the address of each node. This usually isn't meaningful, since it changes depending on the environment and source file. Its main job is tying a dump file to a debug environmentasmname๐ช ifDECL_ASSEMBLER_NAMEhas been set for a given decl, this uses that in the dump instead ofDECL_NAME. It's handy for working backward from mangled names in the assembly fileslim๐ง when dumping front-end intermediate representations, this stops members of a scope or body of a function from being dumped just because that scope got reached. Those items only show up when some other path directly reaches them. When dumping pretty-printed trees, it stops the bodies of control structures from being dumped. When dumping RTL, it prints the RTL in slim (condensed) form instead of the default LISP-like representationraw๐งพ prints a raw representation of the tree. By default, trees get pretty-printed into a C-like representationdetails๐ enables more detailed dumps (not every dump option honors this). It also includes info from the optimization passesstats๐ enables dumping various statistics about the pass (not every dump option honors this one either)blocks๐งฑ enables showing basic block boundaries (disabled in raw dumps)graph๐ธ for each of the other indicated dump files (-fdump-rtl-pass), this dumps a representation of the control flow graph that's suitable for viewing with GraphViz, to a file namedfile.passid.pass.dot. Each function in the file gets pretty-printed as a subgraph, so GraphViz can render them all in a single plot. This currently only works for RTL dumps, and the RTL is always dumped in slim formvops๐ enables showing virtual operands for every statementlineno๐ enables showing line numbers for statementsuid๐ enables showing the unique ID (DECL_UID) for each variableverbose๐ enables showing the tree dump for each statementeh๐ enables showing the EH region number holding each statementscev๐ enables showing scalar evolution analysis detailsoptimizedโ enables showing optimization info (only available in certain passes)missedโ enables showing missed optimization info (only available in certain passes)note๐ enables other detailed optimization info (only available in certain passes)all๐ฏ turns on all options, exceptraw,slim,verboseandlinenooptall๐ซง turns on all optimization options, i.e.,optimized,missed, andnote
To figure out which tree dumps are available, or to find the dump for a pass you care about, follow these steps ๐ต๏ธโโ๏ธ
- Invoke GCC with
-fdump-passes, then look in the stderr output for a code that matches the pass you're interested in. For example, the codestree-evrp,tree-vrp1, andtree-vrp2correspond to the three Value Range Propagation passes. The number at the end tells apart the different invocations of the same pass. - To enable the creation of the dump file, append the pass code to the
-fdump-option prefix and invoke GCC with it. For example, to enable the dump from the Early Value Range Propagation pass, invoke GCC with the-fdump-tree-evrpoption. You can optionally specify the name of the dump file. If you don't specify one, GCC creates one as described below. - Find the pass dump in a file whose name is made of three parts separated by periods: the name of the source file GCC was invoked to compile, a numeric suffix showing the pass number followed by the letter
tfor tree passes (and the letterrfor RTL passes), and finally the pass code. For example, the Early VRP pass dump might be in a file namedmyfile.c.038t.evrpin the current working directory.
The numeric codes are not stable, so they may change from one version of GCC to another. Don't hardcode them, bestie ๐ โโ๏ธ
๐ฎ Optimization info
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโจ controls optimization dumps from the various optimization passes. If you use the-optionsform, options is a list of--separated option keywords that select the dump details and the optimizations.
The options can be split into three groups ๐งฉ:
- options describing what kinds of messages should be emitted,
- options describing the verbosity of the dump, and
- options describing which optimizations should be included.
The options from each group can be freely mixed, since they don't overlap. But if there's ever a conflict, the later options on the command line override the earlier ones ๐ซถ
The following options control which kinds of messages get emitted:
optimized๐ prints info when an optimization is successfully applied. It's up to each pass to decide what info is relevant. For example, the vectorizer passes print the source location of loops that were successfully vectorizedmissed๐ prints info about missed optimizations. Individual passes control what info goes into the outputnote๐ prints verbose info about optimizations, like certain transformations and more detailed messages about decisionsall๐ prints detailed optimization info. This includesoptimized,missed, andnote
Now for the option that controls the dump verbosity ๐
By default, only the "high-level" messages get emitted, bestie ๐ This option unlocks the extra detailed messages, which are lowkey only going to be of interest to GCC developers ๐ค (no judgement, we all have our obsessions ๐ซถ)
You can slap one or more of these option keywords on to describe a whole group of optimizations โจ
ipaโ dumps from all the interprocedural optimizations ๐ธloopโ dumps from all the loop optimizations ๐inlineโ dumps from all the inlining optimizations ๐ฆompโ dumps from all the OMP (Offloading and Multi Processing) optimizations ๐vecโ dumps from all the vectorization optimizations ๐งoptallโ dumps from literally every optimization ๐ It's a superset of the groups above, so it's the main character of the list
If you leave options out, it defaults to optimized-optall, which means it dumps messages about successful optimizations from all the passes, but skips anything treated as "internals" ๐
If you give it a filename, the dumps from all the applicable optimizations get concatenated into that file. Otherwise, the dump is output onto stderr ๐ You're allowed to use multiple -fopt-info options, but only one of them can include a filename ๐ If other filenames show up, all but the first such option get ignored, so pick your favorite and let the rest go ๐ญ
โ ๏ธ Heads up: the output filename gets overwritten in case of multiple translation units. If you want one combined output from multiple translation units, use stderr instead ๐
In the following example, the optimization info is output to stderr โจ
gcc -O3 -fopt-info
This example:
gcc -O3 -fopt-info-missed=missed.all
outputs the missed optimization report from all the passes into missed.all ๐ And this one:
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
prints information about missed optimization opportunities from the vectorization passes on stderr ๐ซถ Note that -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec. The order of the optimization group names and message types listed after -fopt-info does not matter, so you can mix and match ๐
As another example:
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
outputs information about missed optimizations, as well as optimized locations, from all the inlining passes into inline.txt ๐ฆ
Finally, consider:
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Here the two output filenames vec.miss and loop.opt are in conflict, since only one output file is allowed ๐ In this case, only the first option takes effect and the subsequent options are ignored. Thus only vec.miss is produced, which contains dumps from the vectorizer about missed opportunities ๐ฅบ
โจ -fsave-optimization-record โจ
Writes a SRCFILE.opt-record.json.gz file detailing what optimizations were performed, for those optimizations that support -fopt-info ๐ฆ
๐งช This option is experimental, and the format of the data within the compressed JSON file is subject to change. Don't build your whole life on it yet, bestie.
It's roughly equivalent to a machine-readable version of -fopt-info-all, as a collection of messages with source file, line number and column number. On top of that, each message comes with the following extra data ๐
- the execution count of the code being optimized, along with metadata about whether this came from actual profile data or just an estimate, so consumers can prioritize messages by code hotness ๐ฅ
- the function name of the code being optimized, where applicable ๐ง
- the "inlining chain" for the code being optimized, so when a function is inlined into several different places (which might themselves be inlined), the reader can tell the copies apart ๐ช
- objects identifying those parts of the message that refer to expressions, statements or symbol-table nodes, which of these categories they are, and, when available, their source code location ๐
- the GCC pass that emitted the message, and
- the location in GCC's own code from which the message was emitted ๐คฏ
Additionally, some messages are logically nested within other messages, reflecting implementation details of the optimization passes ๐ช
โจ -fsched-verbose=n โจ
On targets that use instruction scheduling, this option controls how much debugging output the scheduler prints to the dump files ๐
- For
ngreater than zero,-fsched-verboseoutputs the same information as-fdump-rtl-sched1and-fdump-rtl-sched2๐ธ - For
ngreater than one, it also outputs basic block probabilities, detailed ready list information and unit/insn info ๐ - For
ngreater than two, it includes RTL at the abort point, control-flow and regions info ๐ - And for
nover four,-fsched-verbosealso includes dependence info ๐คฏ
โจ -fenable-kind-pass / -fdisable-kind-pass=range-list โจ
This is a set of options used to explicitly disable or enable optimization passes ๐๏ธ They're intended for debugging GCC itself. Compiler users should use the regular options for enabling and disabling passes instead, bestie ๐ โโ๏ธ
-fdisable-ipa-passโ Disables the IPA passpass, wherepassis the pass name ๐งฉ If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from1.-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ Disables the RTL passpass, wherepassis the pass name ๐ง If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from1.range-listis a comma-separated list of function ranges or assembler names. Each range is a number pair separated by a colon, and the range is inclusive at both ends. If the range is trivial, the number pair can be simplified to a single number. If the function's call graph node's uid falls within one of the specified ranges, the pass is disabled for that function. The uid is shown in the function header of a dump file, and the pass names can be dumped by using option-fdump-passes๐-fdisable-tree-pass,-fdisable-tree-pass=range-listโ Disables the tree passpass. See-fdisable-rtlfor the description of option arguments ๐ณ-fenable-ipa-passโ Enables the IPA passpass, wherepassis the pass name. If the same pass is statically invoked in the compiler multiple times, the pass name should be appended with a sequential number starting from1โ-fenable-rtl-pass,-fenable-rtl-pass=range-listโ Enables the RTL passpass. See-fdisable-rtlfor option argument description and examples ๐ซ-fenable-tree-pass,-fenable-tree-pass=range-listโ Enables the tree passpass. See-fdisable-rtlfor the description of option arguments ๐ฒ
Here are some examples showing uses of these options ๐
# disable ccp1 for all functions
-fdisable-tree-ccp1
# disable complete unroll for function whose cgraph node uid is 1
-fenable-tree-cunroll=1
# disable gcse2 for functions at the following ranges [1,1],
# [300,400], and [400,1000]
# disable gcse2 for functions foo and foo2
-fdisable-rtl-gcse2=foo,foo2
# disable early inlining
-fdisable-tree-einline
# disable ipa inlining
-fdisable-ipa-inline
# enable tree full unroll
-fenable-tree-unroll
โจ -fchecking / -fchecking=n โจ
Enables internal consistency checking ๐ The default depends on the compiler configuration. -fchecking=2 enables further internal consistency checking that might affect code generation, so it's a bit of a plot twist ๐ญ
โจ -frandom-seed=string โจ
This option provides a seed that GCC uses in place of random numbers when generating 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 the object files that produce them. You can use -frandom-seed to produce reproducibly identical object files, which is honestly so iconic ๐
The string can either be a number (decimal, octal or hex) or an arbitrary string, in which case it's converted to a number by computing CRC32 ๐ข
๐ The string should be different for every file you compile!
โจ -save-temps โจ
Stores the usual "temporary" intermediate files permanently ๐ They get named as auxiliary output files, as specified under -dumpbase and -dumpdir.
When used in combination with the -x command-line option, -save-temps is sensible enough to avoid overwriting an input source file that has the same extension as an intermediate file ๐ If you want the corresponding intermediate file, you can get it by renaming the source file before using -save-temps ๐ซถ
โจ -save-temps=cwd โจ
Equivalent to -save-temps -dumpdir ./ ๐
โจ -save-temps=obj โจ
Equivalent to -save-temps -dumpdir outdir/, where outdir/ is the directory of the output file specified after the -o option, including any directory separators ๐๏ธ If the -o option is not used, the -save-temps=obj switch behaves like -save-temps=cwd ๐ธ
โจ -time[=file] โจ
Reports the CPU time taken by each subprocess in the compilation sequence โฑ๏ธ For C source files, this is the compiler proper and assembler (plus the linker if linking is done) ๐
Without the specification of an output file, the output looks like this:
# cc1 0.12 0.01
# as 0.00 0.01
The first number on each line is the "user time", which is the time spent executing the program itself. The second number is the "system time", which is the time spent executing operating system routines on behalf of the program. Both numbers are in seconds โฐ
With the specification of an output file, the output is appended to the named file, and it looks like this:
0.12 0.01 cc1 <options>
0.00 0.01 as <options>
The "user time" and the "system time" get moved before the program name, and the options passed to the program are displayed too, so you can later tell what file was being compiled, and with which options ๐งพ๐
-fdump-final-insns[=file]: okay so this one dumps the final internal representation (RTL) into a file ๐ โจ. If you leave out the optional argument (orfileis"."), the dump file name gets made by tacking.gkdonto the dump base name, see-dumpbase๐ .-fcompare-debug[=opts]: bestie, this one is a whole vibe ๐ฅ. If nothing errors during compilation, GCC runs the compiler a second time withoptsand-fcompare-debug-secondadded to the second run's args ๐. It dumps the final internal representation from both compilations and prints an error if they don't match ๐ญ. No equal sign? Then the default-gtoggleis used ๐. The environment variableGCC_COMPARE_DEBUG(if it's defined, non-empty, and nonzero) implicitly turns on-fcompare-debug๐. IfGCC_COMPARE_DEBUGis set to a string starting with a dash, that string is used foropts, otherwise the default-gtoggleis used ๐ฆ. Then-fcompare-debug=(equal sign, noopts) is the same as-fno-compare-debug, which turns off the dumping and the second compilation, and stops evenGCC_COMPARE_DEBUGfrom taking effect ๐ซ๐. To check full coverage while testing-fcompare-debug, setGCC_COMPARE_DEBUGto-fcompare-debug-not-overridden. GCC rejects that as an invalid option in any real compilation (rather than preprocessing, assembly, or linking) ๐ง. If you only want a warning, settingGCC_COMPARE_DEBUGto-w%n-fcompare-debug not overriddenwill do ๐ธ.-fcompare-debug-second: this gets passed to the compiler implicitly for the second compilation requested by-fcompare-debug๐ฆ. It comes along with options that silence warnings, and it leaves out any other options that would make the compiler write output to files or to standard output as a side effect ๐ โโ๏ธ. Dump files and preserved temporary files get renamed to include the.gkadditional extension during the second compilation, so they don't overwrite the ones from the first run ๐. When you pass this option to the compiler driver, the first compilation gets skipped, so it's mostly only useful for debugging the compiler itself ๐ ๏ธ.-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 other options are processed, and only once, no matter how many times you give it ๐ซถ. It's mainly meant to be used with-fcompare-debug๐.-fvar-tracking-assignments-toggle: toggles-fvar-tracking-assignmentsthe same way-gtoggletoggles-gโจ.-Q: makes the compiler print out each function name as it gets compiled, and print some statistics about each pass when it finishes ๐.-ftime-report: makes the compiler print some statistics about the time each pass takes when it finishes โฑ๏ธ.-ftime-report-details: records the time spent in infrastructure parts separately for each pass ๐ง.-fira-verbose=n: controls how verbose the dump file for the integrated register allocator is ๐. The default value is5. Ifnis greater than or equal to10, the dump output goes tostderrin the same format asnminus10๐ฅ.-flto-report: prints a report with internal details on how the link-time optimizer is working ๐ต๏ธโโ๏ธ. The contents of this report 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 ๐ .-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-reportand-fpost-ipa-mem-report: makes the compiler print some statistics about permanent memory allocation before or after interprocedural optimization ๐ฆ.-fprofile-report: makes the compiler print some statistics about how consistent the (estimated) profile is and what effect each individual pass has ๐.-fstack-usage: makes the compiler output stack usage information for the program, per function ๐ฅ. 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 isn't an executable, otherwise it's the basename of the source file ๐. Each entry has three fields:- The name of the function.
- A number of bytes.
- One or more qualifiers:
"static","dynamic","bounded".
The "static" qualifier means the function manipulates the stack statically: a fixed number of bytes gets allocated for the frame on function entry and released on function exit, and no other stack adjustments get made in the function ๐งฑ. The second field is that fixed number of bytes ๐ข. The "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 stack used by the function ๐ซง. If it's not present, the amount of those adjustments isn't bounded at compile time, and the second field only represents the bounded part ๐คทโโ๏ธ.
-fstats: emits statistics about front-end processing at the end of compilation ๐. This is only supported by the C++ front end, and the info is generally only useful to the G++ development team ๐ฉโ๐ป.-fdbg-cnt-list: prints the name and the counter upper bound for all debug counters ๐.-fdbg-cnt=counter-value-list: sets the internal debug counter lower and upper bounds ๐ฏ.counter-value-listis a comma-separated list ofname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]tuples, which set the name of the counter and a list of closed intervals ๐ซ. The lower bound is optional and is zero initialized if it's not set 0๏ธโฃ. For example, with-fdbg-cnt=dce:2-4:10-11,tail_call:10,"dbg_cnt(dce)"returns true only for the second, third, fourth, tenth, and eleventh invocation ๐ง. For"dbg_cnt(tail_call)", true is returned for the first 10 invocations ๐.-print-file-name=library: prints the full absolute name of the library filelibrarythat would be used when linking, and then doesn't do anything else ๐จ๏ธ. 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 ๐. This 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;, and each switch starts with an@instead of the-, with no spaces between multiple switches ๐ . This is supposed to make shell processing easier ๐.-print-multi-os-directory: prints the path to OS libraries for the selected multilib, relative to somelibsubdirectory ๐. If OS libraries are in thelibsubdirectory and no multilibs are used, this is usually just.. If OS libraries are inlibsuffixsibling directories, it prints something like../lib64,../lib, or../lib32. If OS libraries are inlib/subdirsubdirectories, it prints something likeamd64,sparcv9, orev6๐ง.-print-multiarch: prints the path to OS libraries for the selected multiarch, relative to somelibsubdirectory ๐ฆ.-print-prog-name=program: like-print-file-name, but it searches for a program such ascpp๐.-print-libgcc-file-name: same as-print-file-name=libgcc.a๐. This is useful when you use-nostdlibor-nodefaultlibsbut you still want to link withlibgcc.a๐ซถ. You can do:
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 doesn't do anything else ๐บ๏ธ.
This is useful when gcc prints the error message installation problem, cannot exec cpp0: No such file or directory. ๐ฑ To fix it, you either need to put cpp0 and the other compiler components where gcc expects to find them, or you can set the environment variable GCC_EXEC_PREFIX to the directory where you installed them ๐ ๏ธ. Don't forget the trailing /! ๐
-print-sysroot: prints the target sysroot directory that's used during compilation ๐ธ. This is the target sysroot specified either at configure time or with the--sysrootoption, possibly with an extra suffix that depends on compilation options ๐งฉ. If no target sysroot is specified, the option prints nothing ๐ซฅ.-print-sysroot-headers-suffix: prints the suffix added to the target sysroot when searching for headers ๐งพ. If the compiler isn't configured with such a suffix, it gives an error instead, and then doesn't do anything else ๐.-dumpmachine: prints the compiler's target machine (for example,i686-pc-linux-gnu), and then doesn't do anything else ๐ฅ๏ธ.-dumpversion: prints the compiler version (for example,3.0,6.3.0or7), and then doesn't do anything else ๐. This is the compiler version used in filesystem paths and specs ๐. Depending on how the compiler was configured, it can be just a single number (major version), two numbers separated by a dot (major and minor version), or three numbers separated by dots (major, minor, and patchlevel version) ๐ข.-dumpfullversion: prints the full compiler version, and then doesn't do anything else ๐. The output is always three numbers separated by dots: major, minor, and patchlevel version ๐งฎ.-dumpspecs: prints the compiler's built-in specs, and then doesn't do anything else ๐. (This is used when GCC itself is being built.) ๐ ๏ธ
โจ Machine-Dependent Options โจ
Each target machine GCC supports can have its own options ๐ฅ๏ธ. For example, they let you compile for a particular processor variant or ABI, or control optimizations specific to that machine ๐ฆ. By convention, the names of machine-specific options start with -m ๐
.
Okay so the compiler has a whole AArch64 wardrobe ๐ฆ and we're about to try on every piece, bestie ๐
๐ AArch64 Options ๐
These options are for AArch64 implementations ๐ธ
-mabi=nameโ picks the data model you want the code generated for ๐ The valid values areilp32(SysV-like, whereint,long intand pointers are all 32 bits) andlp64(SysV-like, whereintis 32 bits butlong intand pointers are 64 bits) โจ The default depends on your target configuration. Also, the LP64 and ILP32 ABIs are not link-compatible, so you have to compile your whole 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 ๐ซถ That means no floating-point or Advanced SIMD registers, but it doesn't put any limits on the assembler.-mlittle-endianโ generates little-endian code ๐ This is the default when GCC is configured for anaarch64-*-*target but not anaarch64_be-*-*one.-mcmodel=tinyโ uses the tiny code model ๐ง The program and its statically defined symbols have to sit within 1MB of each other. It can be statically or dynamically linked.-mcmodel=smallโ uses the small code model ๐ฆ The program and its statically defined symbols have to be within 4GB of each other. It can be statically or dynamically linked. This is the default code model, so you're already on it unless you switch ๐-mcmodel=largeโ uses the large code model, which makes no assumptions about addresses and sizes of sections ๐ Programs can only be statically linked with this one. Also,-mcmodel=largeis incompatible with-mabi=ilp32,-fpicand-fPIC, so don't mix them ๐-mstrict-align,-mno-strict-alignโ the first one avoids (or the second one allows) generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification โจ-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ omits (or keeps) the frame pointer in leaf functions ๐ธ The former behaviour is the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generates stack protection code that uses a canary atguard๐ก๏ธ The supported locations areglobal(for a global canary) orsysreg(for a canary in an appropriate system register).
With the sysreg choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also tell GCC which system register to use as the base register for reading the canary, and what offset from that base register to read from ๐ฅ There's no default register or offset for this, because it's entirely meant for use inside 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โ sets the bit size of immediate TLS offsets ๐ฆ The valid values are12,24,32and48. This option needs binutils 2.26 or newer, so check your toolchain first ๐ซถ-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ turns the workaround for the ARM Cortex-A53 erratum number 835769 on (or off) ๐ฉน The workaround inserts a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions.-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419โ turns the workaround for the ARM Cortex-A53 erratum number 843419 on (or off) ๐ฉน This workaround is applied at link time, so this option just passes the matching flag along to the linker ๐-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ enables (or disables) the reciprocal square root approximation โก This only does anything if-ffast-mathor-funsafe-math-optimizationsis used as well. When it's on, reciprocal square root results drop to about 16 bits of precision for single precision and about 32 bits for double precision ๐-mlow-precision-sqrt,-mno-low-precision-sqrtโ enables (or disables) the square root approximation โก This also only works alongside-ffast-mathor-funsafe-math-optimizations. When it's on, square root results drop to about 16 bits for single precision and about 32 bits for double precision. If you enable it, it implies-mlow-precision-recip-sqrt.-mlow-precision-div,-mno-low-precision-divโ enables (or disables) the division approximation โ Again, it only has an effect alongside-ffast-mathor-funsafe-math-optimizations. When it's on, division results drop to about 16 bits for single precision and about 32 bits for double precision.-mtrack-speculation,-mno-track-speculationโ enables (or disables) extra code that tracks speculative execution through conditional branches ๐ต๏ธโโ๏ธ The tracking state can then be used by the compiler when it expands calls to"__builtin_speculation_safe_copy", so it can make 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 in the base ARMv8.0 ISA. This option is only applicable when compiling for the base ARMv8.0 instruction set. If you're on a later revision, like-march=armv8.1-aor-march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for-mcpu=when the selected CPU supports thelsefeature. This option is on by default ๐-march=nameโ specifies the target architecture and, optionally, one or more feature modifiers ๐๏ธ This option has the form-march=arch{+[no]feature}*.
Here's the rundown of the permissible arch values and the features each one turns on by default ๐
armv8-aโ Armv8-A โ includes by default:+fp,+simdarmv8.1-aโ Armv8.1-A โ includes by 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.7-aโ Armv8.7-A โ includes by default:armv8.6-a,+ls64armv8.8-aโ Armv8.8-a โ includes by default:armv8.7-a,+mopsarmv9-aโ Armv9-A โ includes by default:armv8.5-a,+sve,+sve2armv8-rโ Armv8-R โ includes by default:armv8-r
The value native works on native AArch64 GNU/Linux and tells the compiler to pick the architecture of the host system. This option has no effect if the compiler can't recognise 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 decide what kind of instructions it can emit when generating assembly code ๐ง If -march is specified without -mtune or -mcpu also being specified, the code is tuned to perform well across a range of target processors that implement the target architecture ๐
-mtune=nameโ specifies 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, qdf24xx, saphira, phecda, xgene1, vulcan, octeontx, octeontx81, octeontx83, octeontx2, octeontx2t98, octeontx2t96 octeontx2t93, octeontx2f95, octeontx2f95n, octeontx2f95mm, a64fx, thunderx, thunderxt88, thunderxt88p1, thunderxt81, tsv110, thunderxt83, thunderx2t99, thunderx3t110, zeus, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55, cortex-r82, cortex-x1, cortex-x2, cortex-a510, cortex-a710, ampere1, native.
The values cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55 and cortex-a76.cortex-a55 tell GCC to tune for a big.LITTLE system ๐งฉ
The value neoverse-512tvb tells GCC to tune for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle ๐ช In other words, it tunes for Neoverse cores that can run 4 128-bit Advanced SIMD arithmetic instructions a cycle, and an equivalent number of SVE arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE). This is more general than tuning for one specific core like Neoverse V1, but more specific than the default tuning described below ๐ธ
On native AArch64 GNU/Linux systems, the value native also tunes performance to the host system. This option has no effect if the compiler can't recognise the processor of the host system ๐ฅ๏ธ
If none of -mtune=, -mcpu= or -march= are specified, the code is tuned to perform well across a range of target processors ๐ซถ
This option can't be suffixed by feature modifiers ๐ โโ๏ธ
-mcpu=nameโ specifies the target processor, optionally suffixed by one or more feature modifiers ๐ This option has the form-mcpu=cpu{+[no]feature}*, where the permissible values forcpuare the same as those for-mtune. The permissible values forfeatureare documented in the sub-section onaarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. Same rule as before: if feature modifiers conflict, the right-most one is used ๐ซฐ
okay so -mcpu=name is the big boss ๐ GCC uses name to figure out which kinds of instructions it can emit when generating assembly code (as if by -march) and which target processor to tune performance for (as if by -mtune). If you use -march or -mtune alongside it, those two win and override the matching part of this option ๐
-mcpu=neoverse-512tvb is lowkey special ๐ฆ It doesn't point to one specific core. Instead it covers all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle. Unless -march overrides it, -mcpu=neoverse-512tvb generates code that can run on a Neoverse V1 core, since Neoverse V1 is the first Neoverse core with these properties. Unless -mtune overrides it, -mcpu=neoverse-512tvb tunes code the same way as -mtune=neoverse-512tvb โจ
-moverride=stringโ this one lets you override the tuning decisions the back-end makes in response to a-mtune=switch. The syntax, semantics, and accepted values forstringare not guaranteed to stay consistent across releases ๐
โ ๏ธ bestie, this one is only really useful when you're developing GCC itself, so don't go poking it for fun.
-mverbose-cost-dumpโ turns on verbose cost model dumping in the debug dump files. It's there for debugging the compiler ๐-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ these turn PC-relative literal loads on or off. With the first one, literal pools are accessed using a single instruction and emitted after each function. The catch is that this limits the maximum size of functions to 1MB. It's enabled by default for-mcmodel=tiny๐ธ-msign-return-address=scopeโ picks the function scope where return address signing gets applied. The permissible values arenone, which disables return address signing,non-leaf, which enables pointer signing for functions that are not leaf functions, andall, which enables pointer signing for all functions. The default isnone. This option has been deprecated by-mbranch-protection๐-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 of them, and for any feature with extra tuning options,standardsets it to its standard level.pac-ret[+leaf]turns on return address signing to its standard level, signing functions that save the return address to memory (non-leaf functions will practically always do this) using the a-key. The optional argumentleafextends the signing to include leaf functions. The optional argumentb-keysigns 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:retbrblr
Also, -mharden-sls=all enables all SLS hardening, while -mharden-sls=none disables all of it ๐
-msve-vector-bits=bitsโ specifies the number of bits in an SVE vector register. This option only has an effect when SVE is enabled ๐
GCC supports two forms of SVE code generation. There's "vector-length agnostic" output that works with any size of vector register, and "vector-length specific" output that lets GCC make assumptions about the vector length when that helps optimization. The possible values of bits are scalable, 128, 256, 512, 1024 and 2048. Specifying scalable selects vector-length agnostic output. Right now, -msve-vector-bits=128 also generates vector-length agnostic output for big-endian targets. All other values generate vector-length specific code. These values might change in future releases, so no value except scalable should 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, along with their inverses nofeature. ๐
crcโ enables the CRC extension. This is on by default for-march=armv8.1-a.cryptoโ enables the Crypto extension. This also enables Advanced SIMD and floating-point instructions.fpโ enables floating-point instructions. This is on by default for all possible values for-marchand-mcpu.simdโ enables Advanced SIMD instructions. This also enables floating-point instructions. It's on by default for all possible values for-marchand-mcpu.sveโ enables Scalable Vector Extension instructions. This also enables Advanced SIMD and floating-point instructions.lseโ enables Large System Extension instructions. This is on by default for-march=armv8.1-a.rdmaโ enables Round Double Multiply Accumulate instructions. This is on by default for-march=armv8.1-a.fp16โ enables the FP16 extension. This also enables floating-point instructions.fp16fmlโ 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 extension.dotprodโ enables the Dot Product extension. This also enables Advanced SIMD instructions.aesโ enables the Armv8-a aes and pmull crypto extension. This also enables Advanced SIMD instructions.sha2โ enables the Armv8-a sha2 crypto extension. This also enables Advanced SIMD instructions.sha3โ enables the sha512 and sha3 crypto extension. This also enables Advanced SIMD instructions. Using this with architectures prior to Armv8.2-A is not supported.sm4โ enables the sm3 and sm4 crypto extension. This also enables Advanced SIMD instructions. Using this with architectures prior to Armv8.2-A is not supported.profileโ enables the Statistical Profiling extension. This is only to turn the extension on at the assembler level, and it doesn't affect code generation ๐rngโ enables the Armv8.5-a Random Number instructions. This is only to enable the extension at the assembler level and doesn't affect code generation.memtagโ enables the Armv8.5-a Memory Tagging Extensions. Using this with architectures prior to Armv8.5-A is not supported.sbโ enables the Armv8-a Speculation Barrier instruction. This is only to enable the extension at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a.ssbsโ enables the Armv8-a Speculative Store Bypass Safe instruction. This is only to enable the extension at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a.predresโ enables the Armv8-a Execution and Data Prediction Restriction instructions. This is only to enable the extension at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a.sve2โ enables the Armv8-a Scalable Vector Extension 2. This also enables SVE instructions.sve2-bitpermโ enables SVE2 bitperm instructions. This also enables SVE2 instructions.sve2-sm4โ enables SVE2 sm4 instructions. This also enables SVE2 instructions.sve2-aesโ enables SVE2 aes instructions. This also enables SVE2 instructions.sve2-sha3โ enables SVE2 sha3 instructions. This also enables SVE2 instructions.tmeโ 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 supported.f64mmโ 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โ enables brain half-precision floating-point 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.ls64โ enables the 64-byte atomic load and store instructions for accelerators. It's enabled by default for-march=armv8.7-a.mopsโ enables the instructions that speed up memory operations like "memcpy", "memmove", "memset". It's enabled by default for-march=armv8.8-aflagmโ enables the Flag Manipulation instructions Extension.pauthโ enables the Pointer Authentication Extension.
Feature 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โ doesn't allocate any register in the range"r32"..."r63". That lets code run on hardware variants that lack these registers.-mprefer-short-insn-regsโ preferentially allocates registers that allow short instruction generation. This can increase the instruction count, so it may either reduce or increase overall code size.-mbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions. This cost is only a heuristic and isn't guaranteed to give consistent results across releases.-mcmoveโ enables the generation of conditional moves ๐-mnops=numโ emitsnumNOPs before every other generated instruction.-mno-soft-cmpsfโ okay so this one's a speed-vs-accuracy trade-off ๐ For single-precision float comparisons, GCC emits anfsubinstruction and checks the flags instead. That's faster than a software comparison, BUT it can give wrong answers with NaNs, or when two different tiny numbers subtract to zero. The default is-msoft-cmpsf, which is slower but IEEE-compliant (the safe, responsible choice ๐ซถ).-mstack-offset=numโ sets the offset between the top of the stack and the stack pointer. For example, a value of8means the eight bytes in the rangesp+0...sp+7can be used by leaf functions without any stack allocation โจ Values other than8or16are untested and probably won't work ๐ Heads up, this one changes the ABI, so programs built with a different stack offset than the libraries generally won't work together ๐ญ It's handy for checking whether a different offset gives you better code, but if you actually want working programs with one, the recommended move is configuring the toolchain with the matching--with-stack-offset=numoption ๐-mno-round-nearestโ tells the scheduler to assume the rounding mode has been set to truncating ๐ธ The default is-mround-nearest.-mlong-callsโ if an attribute doesn't say otherwise, GCC assumes every call might be out of range of theb/blinstructions. So it loads the function address into a register first, then does the (otherwise direct) call. This is the default ๐-mshort-callsโ if an attribute doesn't say otherwise, GCC assumes all direct calls are in range of theb/blinstructions, 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 that have-mlong-callssemantics in effect.-mfp-mode=modeโ sets the prevailing mode of the floating-point unit. This decides which FPU mode is provided and expected at function call and return time. If you match this to the mode you mostly need at function start, your programs can be smaller and faster because you skip unnecessary mode switches ๐
mode can be set to one of the following values:
callerโ any mode at function entry is valid, and it's kept or restored when the function returns and when it calls other functions. This one's super useful for libraries or other compilation units you want to drop into programs with different FPU modes. You get one object file, and that convenience outweighs the extra size and speed cost of any mode switching you'd need compared to a more specific choice ๐truncateโ the mode used for floating-point calculations with truncating (round towards zero) rounding. That includes float-to-integer conversion ๐round-nearestโ the mode used for floating-point calculations with round-to-nearest-or-even rounding ๐ธintโ the mode used to do integer calculations in the FPU, like integer multiply or integer multiply-and-accumulate ๐ฅ
The default is -mfp-mode=caller.
-mno-split-lohi,-mno-postinc,-mno-postmodifyโ three code generation tweaks with a shared vibe ๐ They respectively disable splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses. The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify.-mnovect-doubleโ changes the preferred SIMD mode toSImode๐ The default is-mvect-double, which usesDImodeas the preferred SIMD mode.-max-vect-align=numโ the maximum alignment for SIMD vector mode types โจnummay be4or8, and the default is8. Be warned, this is an ABI change! Though plenty of library function interfaces are unaffected, as long as they don't use SIMD vector modes in places that change the size or alignment of relevant types ๐ญ-msplit-vecmove-earlyโ splits vector moves into single word moves before reload ๐ฆ In theory this could give better register allocation, but so far the reverse seems to be generally true ๐-m1reg-regโ specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster ๐ง Allowable values forregarer43andr63, which use that register as a fixed register, andnone, which means no register is used for this purpose. The default is-m1reg-none.
๐ฆ AMD GCN Options ๐ฆ
These options are defined specifically for the AMD GCN port ๐
-march=gpu,-mtune=gpuโ sets the architecture type or tuning forgpu๐ The supported values forgpuare:fijiโ compiles for GCN3 Fiji devices (gfx803).gfx900โ compiles for GCN5 Vega 10 devices (gfx900).gfx906โ compiles 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 ๐ฅ Some devices let you enable this per-process, and the compiled code has to match the device mode. The default isany, for devices that support it.-mstack-size=bytesโ specifies how many bytes of stack space get requested for each GPU thread (wave-front) ๐ญ Be careful, since there may be lots of threads and limited memory available! The size of the stack allocation can also affect run-time performance. The default is32KBwhen using OpenACC or OpenMP, and1MBotherwise.-mxnackโ compiles binaries suitable for devices with the XNACK feature enabled ๐ Some devices always require XNACK, and some let the user configure it. The compiled code has to match the device mode. The default is-mno-xnack. Right now this option is just a placeholder for support that isn't implemented yet ๐
โจ ARC Options โจ
The following options control the architecture variant that code is being compiled for ๐ง
-mbarrel-shifterโ generates instructions supported by the barrel shifter ๐ธ This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ forces a function call using thejli_sinstruction ๐ This option is only valid for the ARCv2 architecture.-mcpu=cpuโ sets the architecture type, register usage, and instruction scheduling parameters forcpu๐ There are also shortcut alias options for backward compatibility and convenience. The supported values forcpuare:arc600โ compiles for ARC600. Aliases:-mA6,-mARC600.arc601โ compiles for ARC601. Alias:-mARC601.arc700โ compiles for ARC700. Aliases:-mA7,-mARC700. This is the default when configured with--with-cpu=arc700.arcemโ compiles for ARC EM.archsโ compiles for ARC HS.emโ compiles for ARC EM CPU with no hardware extensions ๐ฆem4โ compiles for ARC EM4 CPU.em4_dmipsโ compiles for ARC EM4 DMIPS CPU.em4_fpusโ compiles for ARC EM4 DMIPS CPU with the single-precision floating-point extension.em4_fpudaโ compiles for ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions.hsโ compiles for ARC HS CPU with no hardware extensions except the atomic instructions.hs34โ compiles for ARC HS34 CPU.hs38โ compiles for ARC HS38 CPU.hs38_linuxโ compiles for ARC HS38 CPU with all hardware extensions on.arc600_normโ compiles for ARC 600 CPU withnorminstructions enabled.arc600_mul32x16โ compiles for ARC 600 CPU withnormand 32x16-bit multiply instructions enabled.arc600_mul64โ compiles for ARC 600 CPU withnormandmul64-family instructions enabled.arc601_normโ compiles for ARC 601 CPU withnorminstructions enabled.arc601_mul32x16โ compiles for ARC 601 CPU withnormand 32x16-bit multiply instructions enabled.arc601_mul64โ compiles for ARC 601 CPU withnormandmul64-family instructions enabled.nps400โ compiles for ARC 700 on the NPS400 chip.em_miniโ compiles for ARC EM minimalist configuration, featuring a reduced register set ๐
-mdpfp,-mdpfp-compactโ generates double-precision FPX instructions, tuned for the compact implementation ๐-mdpfp-fastโ generates double-precision FPX instructions, tuned for the fast implementation โญ-mno-dpfp-lrsrโ disableslrandsrinstructions from using FPX extension aux registers ๐-meaโ generates extended arithmetic instructions ๐ฅ Right now onlydivaw,adds,subs, andsat16are supported. Only valid for-mcpu=ARC700.-mno-mpyโ doesn't generatempy-family instructions for ARC700 ๐ This option is deprecated, so please don't build new stuff around it.-mmul32x16โ generates 32x16-bit multiply and multiply-accumulate instructions โจ-mmul64โ generatesmul64andmulu64instructions ๐ง Only valid for-mcpu=ARC600.-mnormโ generatesnorminstructions ๐ธ This is the default if-mcpu=ARC700is in effect.-mspfp,-mspfp-compactโ generates single-precision FPX instructions, tuned for the compact implementation ๐-mspfp-fastโ generates single-precision FPX instructions, tuned for the fast implementation ๐-msimdโ enables generation of ARC SIMD instructions through target-specific builtins ๐ฆ Only valid for-mcpu=ARC700.-msoft-floatโ this option is ignored! It's only here for compatibility ๐ Software floating-point code is emitted by default, and that default can be overridden by the FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision.-mswapโ generatesswapinstructions ๐-matomicโ enables use of the locked load/store conditional extension to implement atomic memory built-in functions โจ Not available for ARC 6xx or ARC EM cores.-mdiv-remโ enablesdivandreminstructions for ARCv2 cores ๐
Okay bestie, we're still in the ARC pit ๐ฆ and it's giving tiny-chip energy, so let's go ๐
-mcode-densityโ โจ Turns on the code density instructions for ARC EM. It's already on by default for ARC HS, so you're probably set ๐ธ-mll64โ ๐ Unlocks double load/store operations for ARC HS cores. Lowkey a glow-up ๐ฅ-mtp-regno=regnoโ ๐ง Lets you pick the thread pointer register number. You give it theregnoyou want.-mmpy-option=multoโ ๐ฅ Compiles ARCv2 code with a multiplier design option. You can passmultoas either a string or a number, andwlh1is the default ๐ Here's the menu:0,noneโ No multiplier at all, bestie ๐1,wโ 16x16 multiplier, fully pipelined. Turns on"mpyw"and"mpyuw"๐ธ2,wlh1โ 32x32 multiplier, fully pipelined (1 stage). Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s"โจ This is the default3,wlh2โ 32x32 multiplier, fully pipelined (2 stages). Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s"๐4,wlh3โ Two 16x16 multipliers, blocking and sequential. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s"๐ฆ5,wlh4โ One 16x16 multiplier, blocking and sequential. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s"๐ซถ6,wlh5โ One 32x4 multiplier, blocking and sequential. Also turns on"mpy","mpyu","mpym","mpymu", and"mpy_s"๐7,plus_dmpyโ ARC HS SIMD support ๐8,plus_macdโ ARC HS SIMD support ๐9,plus_qmacwโ ARC HS SIMD support ๐
โ ๏ธ This option only works on ARCv2 cores, so don't try it on the others ๐
-mfpu=fpuโ ๐ฅ Turns on support for specific floating-point hardware extensions on ARCv2 cores. Here are thefpuvalues you can pick:fpusโ Single-precision floating-point hardware extensions ๐fpudโ Double-precision floating-point hardware extensions. The single-precision one comes along for the ride too. Not available for ARC EM ๐ โโ๏ธfpudaโ Double-precision hardware extensions using double-precision assist instructions. Single-precision comes with it. Only for ARC EM โจfpuda_divโ Double-precision with double-precision assist instructions, plus the single-precision floating-point, square-root, and divide extensions. Only for ARC EM ๐งฎfpuda_fmaโ Double-precision with double-precision assist instructions, plus single-precision floating-point and fused multiply and add. Only for ARC EM ๐ฆfpuda_allโ Double-precision with double-precision assist instructions, and every single-precision floating-point extension too. Only for ARC EM ๐fpus_divโ Single-precision floating-point, square-root, and divide extensions ๐ธfpud_divโ Double-precision floating-point, square-root, and divide extensions. This one includesfpus_div. Not available for ARC EM ๐fpus_fmaโ Single-precision floating-point and fused multiply and add extensions ๐ซถfpud_fmaโ Double-precision floating-point and fused multiply and add extensions. This one includesfpus_fma. Not available for ARC EM ๐fpus_allโ Every single-precision floating-point hardware extension ๐fpud_allโ Every single- and double-precision floating-point hardware extension. Not available for ARC EM ๐ฅ
-mirq-ctrl-saved=register-range, blink, lp_countโ ๐ก๏ธ Picks the general-purpose registers the processor automatically saves and restores on interrupt entry and exit. Theregister-rangeis two registers separated by a dash. It always starts at"r0", and the upper limit is the"fp"register.blinkandlp_countare optional. This option is only valid for ARC EM and ARC HS cores โจ-mrgf-banked-regs=numberโ ๐ฆ Sets how many registers get replicated into the second register bank when a fast interrupt fires. 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 doing fast interrupts on an ARC V2 family processor. The allowed values are4,8,16, and32๐-mlpc-width=widthโ ๐ข Sets the width of the"lp_count"register. Valid widths are8,16,20,24,28, and32bits. The default is locked at 32 bits. If the width is under 32, the compiler won't try to transform your loops into the zero-delay loop mechanism unless it knows"lp_count"can actually hold the loop counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for 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. This option defines the"__ARC_RF16__"preprocessor macro ๐ธ-mbranch-indexโ ๐ Enables the use of"bi"or"bih"instructions to implement jump tables ๐
The following options are passed through to the assembler, and also define preprocessor macro symbols. Main character energy, no notes ๐
-mdsp-packaโ Passed down to the assembler to enable the DSP Pack A extensions. Also sets the preprocessor symbol"__Xdsp_packa". > โ ๏ธ This option is deprecated ๐-mdvbfโ Passed down to the assembler to enable the dual Viterbi butterfly extension. Also sets the preprocessor symbol"__Xdvbf". > โ ๏ธ This option is deprecated ๐-mlockโ Passed down to the assembler to enable the locked load/store conditional extension. Also sets the preprocessor symbol"__Xlock"๐-mmac-d16โ Passed down to the assembler. Also sets the preprocessor symbol"__Xxmac_d16". > โ ๏ธ This option is deprecated ๐-mmac-24โ Passed down to the assembler. 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. Also sets the preprocessor symbol"__Xrtsc". > โ ๏ธ This option is deprecated ๐-mswapeโ Passed down to the assembler to enable the swap byte ordering extension instruction. Also sets the preprocessor symbol"__Xswape"๐-mtelephonyโ Passed down to the assembler to enable dual- and single-operand instructions for telephony. Also sets the preprocessor symbol"__Xtelephony". > โ ๏ธ This option is deprecated ๐-mxyโ Passed down to the assembler to enable the XY memory extension. Also sets the preprocessor symbol"__Xxy"๐ง
The following options control how the assembly code is annotated ๐
-misizeโ Annotates assembler instructions with estimated addresses ๐-mannotate-alignโ Explains what 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 the"arclinux"emulation. This is on by default in tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is not requested ๐-marclinux_profโ Passed through to the linker to specify use of the"arclinux_prof"emulation. This is on by default in tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is requested ๐
The following options control the semantics of generated code ๐ง
-mlong-callsโ Generates calls as register indirect calls, so you get 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 an unconditional branch-and-link instruction has. Conditional execution of function calls is suppressed so the 25-bit range can be used, instead of the 21-bit range you'd get with conditional branch-and-link. This is the default for tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets ๐ฆ-G numโ Puts definitions of externally-visible data in a small data section if that data is no bigger thannumbytes. The defaultnumis 4 for any ARC configuration, or 8 when you have double load/store operations ๐ฆ-mno-sdataโ Doesn't generate sdata references. This is the default for tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets ๐ซ-mvolatile-cacheโ Uses ordinarily cached memory accesses for volatile references. This is the default ๐-mno-volatile-cacheโ Enables cache bypass for volatile references ๐โโ๏ธ
The following options fine tune code generation ๐๏ธ
-malign-callโ Does nothing. It's only kept for backward compatibility ๐ฐ๏ธ-mauto-modify-regโ Enables the use of pre/post modify with register displacement ๐ช-mbbit-peepholeโ Enables bbit peephole2 โจ-mno-brccโ Disables a target-specific pass inarc_reorgthat generates compare-and-branch ("brcc") instructions. It has no effect on generating these instructions when they're driven by the combiner pass ๐ โโ๏ธ-mcase-vector-pcrelโ Uses PC-relative switch case tables to enable case table shortening. This is the default for-Os๐ง-mcompact-casesiโ Enables the compact"casesi"pattern. This is the default for-Os, and it's only available for ARCv1 cores. > โ ๏ธ This option is deprecated ๐-mno-cond-execโ Disables the ARCompact-specific pass that generates conditional execution instructions ๐ซ
okay so the ARC port has this special pass that's basically a glow-up for conditional execution ๐ฆ. The normal target-independent pass is kinda lacking ๐ญ because delay slot scheduling, operand numbers, literal sizes, instruction lengths, and conditional execution support are all tangled together. So the ARC folks made a pass that goes back in after register allocation, branch shortening, and delay slot scheduling are all done, and hunts for extra conditional execution chances โจ. It usually improves performance and code size ๐ฅ, but not always, and the tradeoff is extra compile time, which is why there's an option to switch it off ๐. If your call instructions are going out of their allowable offset range because they got conditionalized, try -mmedium-calls instead ๐ซถ.
-mearly-cbranchsiโ turns on pre-reload use of thecbranchsipattern, so it kicks in early ๐ธ.-mexpand-adddiโ expandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. ๐ This one is deprecated, so don't build your whole personality around it.-mindexed-loadsโ enables indexed loads. Hmm, this one is kinda messy ๐ because some optimizers assume indexed stores exist, and they don't.
โ ๏ธ -mindexed-loads can be problematic, bestie. Some optimizers assume indexed stores exist, which is not the case.
-mlraโ enables Local Register Allocation. It's still experimental for ARC ๐งช, so by default the compiler sticks with standard reload (-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 you're optimizing for size with-Os, prologues and epilogues that have to save or restore a ton of registers get shortened by calling a special libgcc function, which is called a millicode call โจ. These calls can cause performance issues and/or linking issues if you link 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โ does nothing ๐. It's just kept around for backward compatibility.-mq-classโ deprecated ๐. Enables q instruction alternatives, and this is the default for-Os.-mRcqโ enables Rcq constraint handling ๐. Most short code generation depends on this, and it's the default.-mRcwโ enables Rcw constraint handling ๐. Most ccfsm condexec depends on this, and it's the default.-msize-level=levelโ fine-tunes size optimization with regards to instruction lengths and alignment ๐ฆ. The recognized values forlevelare:0โ no size optimization. This level is deprecated and treated like1.1โ short instructions get used opportunistically.2โ on top of that, alignment of loops and of code after barriers gets dropped.3โ on top of that, optional data alignment gets dropped, and the optionOsis enabled ๐ฅ.
This defaults to 3 when -Os is in effect. Otherwise, when this isn't set, the behavior is equivalent to level 1.
-mtune=cpuโ sets instruction scheduling parameters forcpu, overriding anything implied by-mcpu=๐. The supported values forcpuare:ARC600โ tunes for the ARC600 CPU.ARC601โ tunes for the ARC601 CPU.ARC700โ tunes for the ARC700 CPU with the standard multiplier block.ARC700-xmacโ tunes for the ARC700 CPU with the XMAC block.ARC725Dโ tunes for the ARC725D CPU.ARC750Dโ tunes for the ARC750D CPU.
-mmultcost=numโ sets the cost to assume for a multiply instruction, where 4 is equal to a normal instruction โญ.-munalign-prob-threshold=probabilityโ does nothing ๐. It's only preserved for backward compatibility.
The following options are maintained for backward compatibility, but they're now deprecated and will be removed in a future release ๐:
-margonautโ obsolete FPX ๐ฅ.-mbig-endian,-EBโ compiles code for big-endian targets. Using these is now deprecated ๐. Big-endian code is supported by configuring GCC to buildarceb-elf32andarceb-linux-uclibctargets, and for those, big endian is the default.-mlittle-endian,-ELโ compiles code for little-endian targets. Using these is now deprecated ๐. Little-endian code is supported by configuring GCC to buildarc-elf32andarc-linux-uclibctargets, and for those, 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. The permissible values areapcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt.-mapcs-frameโ generates a stack frame that's compliant with the ARM Procedure Call Standard for all functions ๐, even if it isn't strictly necessary for the code to run correctly. Specifying-fomit-frame-pointerwith this option means stack frames won't 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 can't be reliably used inside one program. The default is-mno-thumb-interwork, since slightly larger code gets generated when-mthumb-interworkis specified. In AAPCS configurations this option is meaningless ๐.-mno-sched-prologโ stops the reordering of instructions in the function prologue, and also stops those instructions from being merged with the instructions in the function's body ๐งฑ. This means all functions start with a recognizable set of instructions (or one of a choice from a small set of different prologues), so you can use that info to find where functions start inside a chunk of executable code. The default is-msched-prolog.-mfloat-abi=nameโ picks which floating-point ABI to use ๐. The permissible values aresoft,softfpandhard.softmakes GCC generate output containing library calls for floating-point operations.softfpallows code using hardware floating-point instructions, but still uses the soft-float calling conventions.hardallows floating-point instructions and uses FPU-specific calling conventions.
The default depends on the specific target configuration.
โ ๏ธ The hard-float and soft-float ABIs are not link-compatible, bestie. You have to compile your entire program with the same ABI, and link with a compatible set of libraries.
-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers ๐ง . This stops the compiler from using floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler.-mlittle-endianโ generates code for a processor running in little-endian mode ๐. This is the default for all standard configurations.-mbig-endianโ generates code for a processor running in big-endian mode ๐. The default is to compile for a little-endian processor.-mbe8,-mbe32โ when linking a big-endian image, these select between the BE8 and BE32 formats โจ. The option has no effect on little-endian images and is ignored there. The default depends on the selected target architecture: for ARMv6 and later it's BE8, and for older architectures it's BE32. BE32 has been deprecated by ARM ๐.
โ ๏ธ BE32 format has been deprecated by ARM, so maybe go with BE8 if you can ๐ซถ.
-march=name[+extension...]โ specifies the name of the target ARM architecture ๐. GCC uses this name to figure out what kind of instructions it can emit when generating assembly code. This option can be used together with the-mcpu=option or instead of it.
The permissible names are armv4t, armv5t, armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk, armv7, armv7-a, armv7ve, armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv8.6-a, armv9-a, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, armv8.1-m.main, armv9-a, iwmmxt and iwmmxt2.
On top of that, the following architectures, which don't support the Thumb execution state, are recognized but support for them is deprecated ๐: armv4.
Lots of these architectures support extensions ๐งฉ. You can add them by appending +extension to the architecture name. Extension options are processed in order and their capabilities accumulate. An extension will also enable any base extensions it depends on. For example, the +crypto extension will always enable the +simd extension. The exception to the additive setup is extensions prefixed with +no...: these disable the specified option and any other extensions that depend on it being there ๐ซ.
For example, -march=armv7-a+simd+nofp+vfpv4 is equivalent to writing -march=armv7-a+vfpv4, since the +simd option is entirely disabled by the +nofp option that follows it ๐.
Most extension names are generic, but what they actually do depends on the architecture they're applied to ๐. For example, the +simd option can be applied to both armv7-a and armv8-a architectures, but it'll enable the original ARMv7-A Advanced SIMD (Neon) extensions for armv7-a, and the ARMv8-A variant for armv8-a ๐
.
The table below lists the supported extensions for each architecture ๐. Architectures that aren't mentioned don't support any extensions.
armv5te,armv6,armv6j,armv6k,armv6kz,armv6t2,armv6z,armv6zk๐ธ these all share the same little extension menu below+fpโ the VFPv2 floating-point instructions, which are giving main character energy ๐+vfpv2works as an alias for this one โจ+nofpโ turns the floating-point instructions off ๐ โโ๏ธ
armv7๐ the common subset of the ARMv7-A, ARMv7-R and ARMv7-M architectures+fpโ the VFPv3 floating-point instructions with 16 double-precision registers ๐ฅ+vfpv3-d16is an alias for this one. Ngl, floating-point isn't supported by the base ARMv7-M architecture, but it does work with both ARMv7-A and ARMv7-R ๐+nofpโ turns the floating-point instructions off ๐ โโ๏ธ
armv7-a๐ฆ+mpโ the multiprocessing extension ๐ซถ+secโ the security extension ๐+fpโ the VFPv3 floating-point instructions with 16 double-precision registers ๐+vfpv3-d16is an alias for this one+simdโ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions ๐+neonand+neon-vfpv3are aliases for this one+vfpv3โ the VFPv3 floating-point instructions with 32 double-precision registers ๐+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv3-fp16โ the VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv4-d16โ the VFPv4 floating-point instructions with 16 double-precision registers โจ+vfpv4โ the VFPv4 floating-point instructions with 32 double-precision registers โจ+neon-fp16โ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations ๐ง+neon-vfpv4โ the Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions ๐ฅ+nosimdโ disables the Advanced SIMD instructions (this does not turn off floating point, so don't panic) ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐ โโ๏ธ
armv7ve๐ the extended version of the ARMv7-A architecture, with support for virtualization+fpโ the VFPv4 floating-point instructions with 16 double-precision registers ๐ธ+vfpv4-d16is an alias for this one+simdโ the Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions ๐+neon-vfpv4is an alias for this one+vfpv3-d16โ the VFPv3 floating-point instructions with 16 double-precision registers ๐ฆ+vfpv3โ the VFPv3 floating-point instructions with 32 double-precision registers ๐ฆ+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv3-fp16โ the VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv4-d16โ the VFPv4 floating-point instructions with 16 double-precision registers โจ+vfpv4โ the VFPv4 floating-point instructions with 32 double-precision registers โจ+neonโ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions ๐+neon-vfpv3is an alias for this one+neon-fp16โ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations ๐ง+nosimdโ disables the Advanced SIMD instructions (floating point stays on) ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐ โโ๏ธ
armv8-a๐ฅ+crcโ the Cyclic Redundancy Check (CRC) instructions โจ+simdโ the ARMv8-A Advanced SIMD and floating-point instructions ๐+cryptoโ the cryptographic instructions ๐+nocryptoโ disables the cryptographic instructions ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ โโ๏ธ+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ
armv8.1-a๐+simdโ the ARMv8.1-A Advanced SIMD and floating-point instructions ๐+cryptoโ the cryptographic instructions ๐ this one also turns on the Advanced SIMD and floating-point instructions, iykyk ๐+nocryptoโ disables the cryptographic instructions ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ โโ๏ธ+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ
armv8.2-a,armv8.3-a๐ฆ both of these share the list below+fp16โ the half-precision floating-point data processing instructions ๐ this also enables the Advanced SIMD and floating-point instructions+fp16fmlโ the half-precision floating-pointfmlaextension ๐ง this also enables the half-precision floating-point extension, plus the Advanced SIMD and floating-point instructions+simdโ the ARMv8.1-A Advanced SIMD and floating-point instructions ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions+dotprodโ enables the Dot Product extension ๐ this also enables Advanced SIMD instructions+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ โโ๏ธ+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ+i8mmโ the 8-bit Integer Matrix Multiply instructions ๐ธ this also enables Advanced SIMD and floating-point instructions+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions
armv8.4-a๐+fp16โ the half-precision floating-point data processing instructions ๐ this also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-pointfmlaextension+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ โโ๏ธ+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ+i8mmโ the 8-bit Integer Matrix Multiply instructions ๐ธ this also enables Advanced SIMD and floating-point instructions+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions
armv8.5-a๐+fp16โ the half-precision floating-point data processing instructions ๐ this also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-pointfmlaextension+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ โโ๏ธ+i8mmโ the 8-bit Integer Matrix Multiply instructions ๐ธ this also enables Advanced SIMD and floating-point instructions+bf16โ the Brain half-precision floating-point instructions ๐ง this also enables Advanced SIMD and floating-point instructions
armv8.6-a๐+fp16โ the half-precision floating-point data processing instructions ๐ this also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-pointfmlaextension+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ this also enables the Advanced SIMD and floating-point instructions, plus the Dot Product extension+nocryptoโ disables the cryptographic extension ๐ โโ๏ธ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐ โโ๏ธ
+i8mm โ 8-bit Integer Matrix Multiply instructions ๐งฎโจ This also enables Advanced SIMD and floating-point instructions, so the whole glam package comes with it ๐
+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 ๐ฆ+vfpv3xdworks as an alias for this one ๐+fpโ the VFPv3 floating-point instructions with 16 double-precision registers โจ+vfpv3-d16can be used as an alias for this one ๐+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 and the half-precision floating-point conversion operations ๐+nofpโ disables the floating-point extension ๐ซ+idivโ the ARM-state integer division instructions โ+noidivโ disables the ARM-state integer division extension ๐
armv7e-m
+fpโ the single-precision VFPv4 floating-point instructions ๐ฅ+fpv5โ the single-precision FPv5 floating-point instructions โญ+fp.dpโ the single- and double-precision FPv5 floating-point instructions ๐+nofpโ disables the floating-point extensions ๐ซ
armv8.1-m.main
+dspโ the DSP instructions ๐ถ+mveโ the M-Profile Vector Extension (MVE) integer instructions ๐ฆ+mve.fpโ the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions ๐+fpโ the single-precision floating-point instructions โจ+fp.dpโ the single- and double-precision floating-point instructions ๐+nofpโ disables the floating-point extension ๐ซ+cdecp0, +cdecp1, ... , +cdecp7โ enables the Custom Datapath Extension (CDE) on selected coprocessors, based on the numbers given in the options in the range 0 to 7 ๐ง
armv8-m.main
+dspโ the DSP instructions ๐ถ+nodspโ disables the DSP extension ๐+fpโ the single-precision floating-point instructions โจ+fp.dpโ the single- and double-precision floating-point instructions ๐+nofpโ disables the floating-point extension ๐ซ+cdecp0, +cdecp1, ... , +cdecp7โ enables the Custom Datapath Extension (CDE) on selected coprocessors, based on the numbers given in the options in the range 0 to 7 ๐ง
armv8-r
+crcโ the Cyclic Redundancy Check (CRC) instructions ๐+fp.spโ the single-precision FPv5 floating-point instructions ๐ฆ+simdโ the ARMv8-A Advanced SIMD and floating-point instructions ๐ธ+cryptoโ the cryptographic instructions ๐+nocryptoโ disables the cryptographic instructions ๐ซ+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐
-march=native makes the compiler auto-detect 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 ๐ซ
-mtune=name
This one tells GCC which target ARM processor to tune the performance of the code for ๐ฏ On some ARM implementations you can get better performance by using this option ๐ The permissible names are: arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi, arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, ares, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-r52plus, cortex-m0, cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-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.
It also works for big.LITTLE systems ๐ค The names for those 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 for a blend of processors within the architecture arch ๐ The goal is code that runs well on the most popular processors right now, balancing the CPUs that benefit from certain optimizations against avoiding the performance pitfalls of others. Heads up that this can change in future GCC versions as CPU models come and go ๐
-mtune accepts the same extension options as -mcpu, but the extension options don't affect how the generated code gets tuned ๐
-mtune=native makes the compiler auto-detect the CPU of the build computer ๐ฅ๏ธ Same deal as before: right now it's only supported on GNU/Linux, not every architecture is recognized, and if the auto-detect fails the option has no effect ๐
-mcpu=name[+extension...]
This specifies the name of the target ARM processor ๐ GCC uses that name to figure out the target ARM architecture (as if you'd used -march) and the ARM processor type to tune for (as if you'd used -mtune). If you use this option together with -march or -mtune, those options take precedence over the matching part of this one ๐
A lot of the supported CPUs have optional architectural extensions ๐งฉ Those extensions are usually enabled by default. If implementations without the extension exist, you can use the extension syntax to turn off the ones that have been left out ๐
โโ๏ธ For floating-point and Advanced SIMD (Neon) instructions, you also have to think about -mfloat-abi and -mfpu: floating-point and Advanced SIMD instructions only get used if -mfloat-abi isn't set to soft, and any -mfpu setting other than auto will override the available floating-point and SIMD extension instructions ๐
For example, cortex-a9 shows up in three main configurations: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD ๐ซง By default all the instructions are enabled, but you can use +nosimd to disable just the SIMD instructions, or +nofp to disable both SIMD and floating-point instructions ๐ซถ
The permissible names for this option are the same as the ones for -mtune ๐
These extension options are shared by the listed CPUs:
+nodspโ disables the DSP instructions oncortex-m33andcortex-m35p๐+nofpโ disables the floating-point instructions onarm9e, arm946e-s, arm966e-s, arm968e-s, arm10e, arm1020e, arm1022e, arm926ej-s, arm1026ej-s, cortex-r5, cortex-r7, cortex-r8, cortex-m4, cortex-m7, cortex-m33andcortex-m35p. Ongeneric-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a32, cortex-a35, cortex-a53andcortex-a55, it disables the floating-point and SIMD instructions ๐ซ+nofp.dpโ disables the double-precision part of the floating-point instructions oncortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-r52plusandcortex-m7๐+nosimdโ disables the SIMD instructions (but not floating-point) ongeneric-armv7-a, cortex-a5, cortex-a7andcortex-a9๐ถ+cryptoโ enables the cryptographic instructions oncortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, exynos-m1, xgene1, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53andcortex-a75.cortex-a55๐
On top of that, the generic-armv7-a pseudo target defaults to VFPv3 with 16 double-precision registers ๐ง It supports these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16, neon-vfpv4. The meanings are the same as for the extensions to -march=armv7-a ๐
-mcpu=generic-arch is allowed too, and it's the same as -march=arch -mtune=generic-arch. Check out -mtune for more info ๐ธ
-mcpu=native makes the compiler auto-detect the CPU of the build computer ๐ค Right now that only works on GNU/Linux, not every architecture is recognized, and if the auto-detect doesn't work the option has no effect ๐ญ
-mfpu=name
This specifies what floating-point hardware (or hardware emulation) is available on the target ๐ง The permissible names are: auto, vfpv2, vfpv3, vfpv3-fp16, vfpv3-d16, vfpv3-d16-fp16, vfpv3xd, vfpv3xd-fp16, neon-vfpv3, neon-fp16, vfpv4, vfpv4-d16, fpv4-sp-d16, neon-vfpv4, fpv5-d16, fpv5-sp-d16, fp-armv8, neon-fp-armv8 and crypto-neon-fp-armv8. Fun fact: neon is just an alias for neon-vfpv3, and vfp is an alias for vfpv2 ๐ฆ
The auto setting is the default and it's lowkey special ๐
It tells the compiler to pick the floating-point and Advanced SIMD instructions based on your -mcpu and -march settings โจ
If your floating-point hardware includes the NEON extension (like -mfpu=neon), bestie, pay attention ๐ GCC's auto-vectorization pass won't generate floating-point operations unless you also add -funsafe-math-optimizations. NEON hardware doesn't fully implement IEEE 754 for floating-point arithmetic (denormal values get treated as zero), so using NEON instructions can cost you precision ๐ญ
Heads up: NEON can lose precision, so -funsafe-math-optimizations is needed before auto-vectorization generates floating-point operations on NEON hardware.
You can also set the fpu name at function level with the target("fpu=") function attributes or pragmas ๐
-mfp16-format=nameโ Picks the format of the__fp16half-precision floating-point type ๐ธ The valid names arenone,ieeeandalternative. The default isnone, which means__fp16isn't defined at all.-mstructure-size-boundary=nโ Every struct and union gets rounded up to a multiple ofnbits ๐ The valid values are8,32and64. The default depends on your toolchain (the COFF toolchain defaults to8), and64is only allowed if the underlying ABI supports it. Bigger numbers can make code faster and more efficient, but the program can also get bigger ๐ Different values are potentially incompatible, so code built with one value might not play nice with code or libraries built with another if they swap info through structs or unions ๐
This option is deprecated ๐ซ
-mabort-on-noreturnโ At the end of anoreturnfunction, GCC generates a call to the functionabort. It runs if the function tries to return ๐-mlong-calls,-mno-long-callsโ Tells the compiler to load the function's address into a register first, then make the subroutine call through that register ๐งญ You need this if the target function is outside the 64-megabyte addressing range of the offset-based subroutine call instruction. Even with this on, not every call turns into a long call. Static functions, functions with theshort_callattribute, functions inside a#pragma no_long_callsscope, and functions already compiled within the current compilation unit stay as normal calls ๐ The exceptions are weak function definitions, functions with thelong_callorsectionattribute, and functions inside a#pragma long_callsscope, which are always long calls ๐ This feature isn't enabled by default.-mno-long-callsrestores the default behavior, as does putting function calls inside a#pragma long_calls_offscope. These switches have no effect on how calls through function pointers are generated.-msingle-pic-baseโ Treats the register used for PIC addressing as read-only, instead of loading it in the prologue for each function ๐ The runtime system is responsible for setting this register to an appropriate value before execution begins.-mpic-register=regโ Picks the register used for PIC addressing ๐ฏ For the standard PIC base case, the default is any suitable register the compiler chooses. For the single PIC base case, the default isR9if the target is EABI based or stack-checking is enabled, otherwise it'sR10.-mpic-data-is-text-relativeโ Assumes the displacement between the text and data segments is fixed at static link time ๐ฆ That lets PC-relative addressing access data known to be in the data segment. For non-VxWorks RTP targets, this is enabled by default. When it's disabled on those targets,-msingle-pic-basegets enabled by default.-mpoke-function-nameโ Writes the name of each function into the text section, right before the function prologue ๐ง The generated code looks like this:
t0
.ascii "arm_poke_function_name", 0
.align
t1
.word 0xff000000 + (t1 - t0)
arm_poke_function_name
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
When doing a stack backtrace, code can inspect the value of pc stored at fp + 0. If the trace function then looks at location pc - 12 and the top 8 bits are set, we know there's a function name embedded right before this location, and its length is ((pc[-3]) & 0xff000000) โจ
-mthumb,-marmโ Pick between generating code that runs in ARM state or Thumb state ๐ Most configurations default to ARM state, but you can change that by configuring GCC with the--with-mode=stateconfigure option. You can also override ARM and Thumb mode for each function with thetarget("thumb")andtarget("arm")function attributes or pragmas ๐-mflip-thumbโ Switches ARM/Thumb modes on alternating functions ๐ It's there for regression testing of mixed Thumb/ARM code generation and is NOT intended for ordinary use when compiling code.-mtpcs-frameโ Generates a stack frame that's compliant with the Thumb Procedure Call Standard for all non-leaf functions. (A leaf function is one that doesn't call any other functions ๐ฟ) The default is-mno-tpcs-frame.-mtpcs-leaf-frameโ Generates a stack frame that's 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 switches to Thumb mode before running the rest of the function ๐ช That lets these functions get called from non-interworking code. This option isn't valid in AAPCS configurations, because interworking is enabled by default there.-mcaller-super-interworkingโ Lets calls via function pointers (including virtual functions) execute correctly whether or not the target code was compiled for interworking ๐ค There's a small overhead when executing a function pointer with this enabled. This option isn't valid in AAPCS configurations either, since interworking is enabled by default.-mtp=nameโ Specifies 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 selected processor. The default isauto.-mtls-dialect=dialectโ Picks the dialect for accessing thread local storage ๐ Two dialects are supported:gnuandgnu2. Thegnudialect selects the original GNU scheme for local and global dynamic TLS models. Thegnu2dialect selects the GNU descriptor scheme, which gives better performance for shared libraries ๐ The descriptor scheme is compatible with the original one, but it needs new assembler, linker and library support. Initial and local exec TLS models aren't affected by this option and always use the original scheme.-mword-relocationsโ Only generates absolute relocations on word-sized values (i.e.R_ARM_ABS32) ๐ This is enabled by default on targets (uClinux, SymbianOS) where the runtime loader imposes this restriction, and when-fpicor-fPICis specified. This option conflicts with-mslow-flash-data.-mfix-cortex-m3-ldrdโ Some Cortex-M3 cores can cause data corruption whenldrdinstructions with overlapping destination and base registers are used ๐ฑ This option avoids generating those instructions. It's enabled by default when-mcpu=cortex-m3is specified.-mfix-cortex-a57-aes-1742098,-mno-fix-cortex-a57-aes-1742098,-mfix-cortex-a72-aes-1655431,-mno-fix-cortex-a72-aes-1655431โ Enables (or disables) the mitigation for an erratum on Cortex-A57 and Cortex-A72 that affects the AES cryptographic instructions ๐ก๏ธ This option is enabled by default when either-mcpu=cortex-a57or-mcpu=cortex-a72is specified.-munaligned-access,-mno-unaligned-accessโ Enables (or disables) reading and writing 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 it isn't enabled, words in packed data structures are accessed one byte at a time. The ARM attributeTag_CPU_unaligned_accessis set in the generated object file to either true or false, depending on this option's setting ๐ท๏ธ If unaligned access is enabled, the preprocessor symbol__ARM_FEATURE_UNALIGNEDis also defined.-mneon-for-64bitsโ Deprecated and has no effect ๐-mslow-flash-dataโ Assumes loading data from flash is slower than fetching instructions, so literal loads get minimized for better performance ๐ข This option is only supported when compiling for ARMv7 M-profile and it's off by default. It conflicts with-mword-relocations.-masm-syntax-unifiedโ Assumes inline assembler is using unified asm syntax ๐ The default is currently off, which implies divided syntax. This option has no impact on Thumb2, but that may change in future releases of GCC.
Divided syntax should be considered deprecated ๐
-mrestrict-itโ Restricts generation of IT blocks so they conform to the rules of ARMv8-A ๐ IT blocks can only contain a single 16-bit instruction from a select set of instructions. This option is on by default for ARMv8-A Thumb mode.-mprint-tune-infoโ okay bestie, this one drops the CPU tuning info as a comment in the assembler file ๐ It's only for regression testing the compiler, so it's NOT something you need for everyday code ๐ It's off by default โจ-mverbose-cost-dumpโ turns on verbose cost model dumping in the debug dump files ๐ It's there for debugging the compiler itself, so it's giving compiler-nerd energy ๐ค-mpure-codeโ no constant data gets stuffed into code sections ๐ซ Also, when you're compiling for ELF object format, every text section gets the ELF processor-specific section attributeSHF_ARM_PURECODE๐ This option is only available when generating non-pic code for M-profile targets ๐ซถ-mcmseโ generates secure code following the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification" ๐ You can find that spec athttps://developer.arm.com/documentation/ecm0359818/latest/๐ฆ-mfix-cmse-cve-2021-35465โ mitigates a potential security issue with the "VLLDM" instruction on some M-profile devices when you're using CMSE (CVE-2021-365465) ๐ก๏ธ This one is enabled by default when-mcpu=is used with "cortex-m33", "cortex-m35p" or "cortex-m55". Want to turn the mitigation off? Use-mno-fix-cmse-cve-2021-35465๐ โโ๏ธ-mstack-protector-guard=guard,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary at guard ๐ก๏ธ The supported locations areglobalfor a global canary, ortlsfor a canary accessible via the TLS register ๐งต The-mstack-protector-guard-offset=option is for use with-fstack-protector-guard=tlsand NOT for user-land code ๐ซ-mfdpic,-mno-fdpicโ picks the FDPIC ABI, which uses 64-bit function descriptors to represent pointers to functions ๐ When the compiler is configured forarm-*-uclinuxfdpiceabitargets, this is on by default and implies-fPIEif none of the PIC/PIE-related options is provided. On other targets it only turns on the FDPIC-specific code generation features, so you should explicitly pass the PIC/PIE-related options as needed ๐ง
Static linking isn't supported, ngl, because it would still involve the dynamic linker when the program self-relocates ๐ If that behavior is acceptable, 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 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 the "MOVW" instruction. mcu =attiny13,attiny13a,attiny24,attiny24a,attiny25,attiny261,attiny261a,attiny2313,attiny2313a,attiny43u,attiny44,attiny44a,attiny45,attiny48,attiny441,attiny461,attiny461a,attiny4313,attiny84,attiny84a,attiny85,attiny87,attiny88,attiny828,attiny841,attiny861,attiny861a,ata5272,ata6616c,at86rf401๐ฆavr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory. mcu =at76c711,at43usb355๐avr31โ "Classic" devices with 128 KiB of program memory. mcu =atmega103,at43usb320๐ฅavr35โ "Classic" devices with 16 KiB up to 64 KiB of program memory and the "MOVW" instruction. mcu =attiny167,attiny1634,atmega8u2,atmega16u2,atmega32u2,ata5505,ata6617c,ata664251,at90usb82,at90usb162๐avr4โ "Enhanced" devices with up to 8 KiB of program memory. mcu =atmega48,atmega48a,atmega48p,atmega48pa,atmega48pb,atmega8,atmega8a,atmega8hva,atmega88,atmega88a,atmega88p,atmega88pa,atmega88pb,atmega8515,atmega8535,ata6285,ata6286,ata6289,ata6612c,at90pwm1,at90pwm2,at90pwm2b,at90pwm3,at90pwm3b,at90pwm81โญavr5โ "Enhanced" devices with 16 KiB up to 64 KiB of program memory. mcu =atmega16,atmega16a,atmega16hva,atmega16hva2,atmega16hvb,atmega16hvbrevb,atmega16m1,atmega16u4,atmega161,atmega162,atmega163,atmega164a,atmega164p,atmega164pa,atmega165,atmega165a,atmega165p,atmega165pa,atmega168,atmega168a,atmega168p,atmega168pa,atmega168pb,atmega169,atmega169a,atmega169p,atmega169pa,atmega32,atmega32a,atmega32c1,atmega32hvb,atmega32hvbrevb,atmega32m1,atmega32u4,atmega32u6,atmega323,atmega324a,atmega324p,atmega324pa,atmega324pb,atmega325,atmega325a,atmega325p,atmega325pa,atmega328,atmega328p,atmega328pb,atmega329,atmega329a,atmega329p,atmega329pa,atmega3250,atmega3250a,atmega3250p,atmega3250pa,atmega3290,atmega3290a,atmega3290p,atmega3290pa,atmega406,atmega64,atmega64a,atmega64c1,atmega64hve,atmega64hve2,atmega64m1,atmega64rfr2,atmega640,atmega644,atmega644a,atmega644p,atmega644pa,atmega644rfr2,atmega645,atmega645a,atmega645p,atmega649,atmega649a,atmega649p,atmega6450,atmega6450a,atmega6450p,atmega6490,atmega6490a,atmega6490p,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 a 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 the assembler only. mcu =attiny11,attiny12,attiny15,attiny28,at90s1200๐
-mabsdataโ assumes all data in static storage can be accessed byLDS/STSinstructions ๐ฏ This option only has an effect on reduced Tiny devices like ATtiny40. See also the "absdata" AVR Variable Attributes,variable attribute ๐-maccumulate-argsโ accumulates outgoing function arguments and acquires/releases the needed stack space for them once, in the function prologue/epilogue โจ Without this option, outgoing arguments are pushed before calling a function and popped afterwards ๐ฆ
Popping the arguments after the function call can be expensive on AVR, so accumulating the stack space might lead to smaller executables, because arguments don't need to be removed from the stack after each call ๐งน
This option can lead to reduced code size for functions that make several calls to functions that get their arguments on the stack, like calls to printf-like functions ๐
-mbranch-cost=costโ sets the branch costs for conditional branch instructions tocost๐ Reasonable values forcostare small, non-negative integers. The default branch cost is0๐ซถ-mcall-prologuesโ function prologues/epilogues get expanded as calls to appropriate subroutines, so the code size is smaller ๐ฆ-mdouble=bits,-mlong-double=bitsโ okay so these two let you set the size (in bits) of the "double" and "long double" types, respectively ๐ The only values for bits are32and64๐. Whether a value is allowed depends on the--with-double=and--with-long-double=configure options (https://gcc.gnu.org/install/configure.html#avr) ๐ธ, and the default values follow the same rule ๐ซถ.-mgas-isr-prologuesโ ISRs (interrupt service routines) can use the__gcc_isrpseudo instruction that GNU Binutils supports โจ If this option is on, you can still turn the feature off for individual ISRs with the "no_gccisr" function attribute (see AVR Function Attributes) ๐ฆ It's turned on by default when optimization is on, but not with-Og(see Optimize Options), and only if GNU Binutils supports PR21683 (https://sourceware.org/PR21683) ๐-mint8โ this one makes "int" an 8-bit integer ๐ It changes the size of all the types: a "char" is 1 byte, an "int" is 1 byte, a "long" is 2 bytes, and a "long long" is 4 bytes ๐ญ Please note that this does not conform to the C standards ๐ but the upside is smaller code size ๐-mmain-is-OS_taskโ don't save registers in "main" ๐ฅ It does the same thing as slapping the AVR Function Attributes "OS_task" attribute onto "main" ๐ This is turned on by default when optimization is on โญ-mn-flash=numโ tells the compiler to assume the flash memory isnumtimes 64 KiB big ๐ง-mno-interruptsโ the generated code is not compatible with hardware interrupts ๐ The payoff is that the code size comes out smaller ๐ซง-mrelaxโ this tries to swap aCALL(orJMP) for the shorterRCALL(orRJMP) whenever that's possible โจ Setting-mrelaxjust adds--mlink-relaxto the assembler's command line and--relaxto the linker's command line ๐ฆ
Jump relaxing is done by the linker, since jump offsets aren't known until the code is located ๐ง So the assembler code the compiler generates is the same, but the instructions in the executable might look different from what's in the assembler code ๐
Relaxing must be turned on if linker stubs are needed. Check out the section on "EIND" and linker stubs below ๐
-mrmwโ assume the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT๐-mshort-callsโ assume thatRJMPandRCALLcan reach the whole program memory ๐ธ
This one is used internally for multilib selection ๐ซถ It's not an optimization option, so you don't need to set it by hand, bestie ๐
-msp8โ treat the stack pointer register as an 8-bit register, which means assuming the high byte of the stack pointer is zero ๐ Generally you don't need to set this 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 ๐ That's because the compiler then knows whether the device or architecture has an 8-bit stack pointer (and therefore no SPH register) or not ๐
-mstrict-Xโ use the address registerXthe way the hardware intends ๐ฆ That meansXis only used for indirect, post-increment, or pre-decrement addressing ๐
Without this option, the X register can be used the same way as Y or Z, but that gets emulated with extra instructions ๐ญ For example, loading a value with X+const addressing (with a small non-negative const < 64) into a register Rn gets done like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-mtiny-stackโ only change the lower 8 bits of the stack pointer ๐ท-mfract-convert-truncateโ allow truncation instead of rounding towards zero for fractional fixed-point types ๐-nodevicelibโ don't link against AVR-LibC's device specific librarylib<mcu>.a๐-nodevicespecsโ don't add-specs=device-specs/specs-mcuto the compiler driver's command line ๐ You're taking full responsibility for the subprocesses (compiler proper, assembler and linker) and their appropriate command line options ๐ค That means you have to supply your own private device specs file with-specs=path-to-specs-file๐ง And there's no more need for-mmcu=mcu๐ซถ
This option can also replace the older way of specifying custom device-specs files. That old way needed -B some-path to point to a directory containing a folder named "device-specs", and that folder had to contain a specs file named "specs-mcu", where mcu was the value given with -mmcu=mcu ๐ฐ๏ธ
-Waddr-space-convertโ warn about conversions between address spaces when the resulting address space is not contained in the incoming address space โ ๏ธ-Wmisspelled-isrโ warn if the ISR is misspelled, meaning it's missing the__vectorprefix ๐ This is enabled by default โ
โจ "EIND" and Devices with More Than 128 Ki Bytes of Flash โจ
Pointers in the implementation are 16 bits wide ๐ง The address of a function or label is represented as a word address, so indirect jumps and calls can target any code address in the range of 64 Ki words ๐
To make indirect jumps work on devices with more than 128 Ki bytes of program memory, there's a special function register called "EIND" ๐ It serves as the most significant part of the target address whenever EICALL or EIJMP instructions are used ๐ฅ
Indirect jumps and calls on these devices are handled as follows by the compiler, and they come with some limitations ๐ซ
- The compiler never sets
EIND. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or it might readEINDdirectly in order to emulate an indirect call/jump by means of aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved/restored in function or interrupt service routine prologue/epilogue. - For indirect calls to functions and computed goto, the linker generates stubs ๐งธ Stubs are jump pads, sometimes also called trampolines. So the indirect call/jump jumps to such a stub, and the stub contains a direct jump to the desired address.
- Linker relaxation must be turned on so that the linker generates the stubs correctly in all situations. See the compiler option
-mrelaxand the linker option--relax. There are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message ๐ฑ - The default linker script is arranged for code with
EIND = 0. If code is supposed to work for a setup withEIND != 0, you have to use a custom linker script to place the sections whose name starts with.trampolinesinto the segment whereEINDpoints to ๐บ๏ธ - The startup code from libgcc never sets
EIND. Notice that startup code is a blend of code from libgcc and AVR-LibC. For the impact of AVR-LibC onEIND, see the AVR-LibC user manual (http://nongnu.org/avr-libc/user-manual/) ๐ - It's 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 this is not supported ๐ซ
int main (void)
{
/* Call function at word address 0x2 */
return ((int(*)(void)) 0x2)();
}
Instead, a stub has to be set up, i.e. the function has to be called through a symbol ("func_4" in the example) ๐
int main (void)
{
extern int func_4 (void);
/* Call function at byte address 0x4 */
return func_4();
}
and the application has to be linked with -Wl,--defsym,func_4=0x4. Alternatively, func_4 can be defined in the linker script ๐ฆ
โจ Handling of the "RAMPD", "RAMPX", "RAMPY" and "RAMPZ" Special Function Registers โจ
Some AVR devices support memories larger than the 64 KiB range that can be accessed with 16-bit pointers ๐ง To reach memory locations outside that 64 KiB range, the content of a "RAMP" register is used as the high part of the address ๐ The "X", "Y" and "Z" address registers are concatenated with the "RAMPX", "RAMPY" and "RAMPZ" special function registers, respectively, to get a wide address ๐ Similarly, "RAMPD" is used together with direct addressing โจ
- The startup code initializes the "RAMP" special function registers with zero ๐ธ
- If a named address space (see AVR Named Address Spaces) other than generic or
__flashis used, thenRAMPZis set as needed before the operation ๐ซถ - ๐
If the device supports RAM larger than 64 KiB and the compiler needs to change
"RAMPZ"to get an operation done,"RAMPZ"gets reset to zero afterwards. โจ - If the device comes with a specific
"RAMP"register, the ISR prologue/epilogue saves and restores that SFR and sets it to zero in case the ISR code might (implicitly) use it. ๐ซถ
๐ญ Warning, bestie: RAM larger than 64 KiB is not supported by GCC for AVR targets. If you use inline assembler to read from locations outside the 16-bit address range and change one of the "RAMP" registers, you must reset it to zero after the access. Don't skip this part or it's giving chaos. ๐
โจ AVR Built-in Macros โจ
GCC defines several built-in macros so your code can check whether a feature is there or not. ๐ Almost any of the following built-in macros are deduced from device capabilities, so they get triggered by the -mmcu= command-line option. ๐ธ
For even more AVR-specific built-in macros, check out AVR Named Address Spaces and AVR Built-in Functions. ๐ง
"__AVR_ARCH__"โ This is a built-in macro that resolves to a decimal number identifying the architecture. It depends on the-mmcu=mcuoption. The possible values are:2, 25, 3, 31, 35, 4, 5, 51, 6formcu="avr2","avr25","avr3","avr31","avr35","avr4","avr5","avr51","avr6", respectively.100, 102, 103, 104, 105, 106, 107formcu="avrtiny","avrxmega2","avrxmega3","avrxmega4","avrxmega5","avrxmega6","avrxmega7", respectively.
If mcu specifies a device, this macro gets set accordingly. For example, with -mmcu=atmega8 the macro is defined to 4. ๐
"__AVR_Device__"โ Setting-mmcu=devicedefines this macro, which reflects the device's name. For example,-mmcu=atmega8defines"__AVR_ATmega8__"and-mmcu=attiny261adefines"__AVR_ATtiny261A__", etc. ๐ฆ
The names follow the scheme "__AVR_Device__", where Device is the device name as it appears in the AVR user manual. The difference between Device in the macro and device in -mmcu=device is that the latter is always lowercase. ๐
If device is not an actual device but only a core architecture like avr51, this macro is not defined.
"__AVR_DEVICE_NAME__"โ Setting-mmcu=devicedefines this 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 the"ELPM"instruction. ๐ฅ"__AVR_HAVE_ELPMX__"โ The device has the"ELPM Rn,Z"and"ELPM Rn,Z+"instructions. ๐"__AVR_HAVE_MOVW__"โ The device has the"MOVW"instruction, which does 16-bit register-to-register moves. โญ"__AVR_HAVE_LPMX__"โ The device has the"LPM Rn,Z"and"LPM Rn,Z+"instructions. ๐"__AVR_HAVE_MUL__"โ The device has a hardware multiplier. ๐"__AVR_HAVE_JMP_CALL__"โ The device has the"JMP"and"CALL"instructions. This is the case for devices with more than 8 KiB of program memory. ๐ฆ"__AVR_HAVE_EIJMP_EICALL__"and"__AVR_3_BYTE_PC__"โ The device has the"EIJMP"and"EICALL"instructions. This is the case for devices with more than 128 KiB of program memory. It also means the program counter (PC) is 3 bytes wide. ๐ง"__AVR_2_BYTE_PC__"โ The program counter (PC) is 2 bytes wide. This is the case for devices with up to 128 KiB of program memory. ๐ธ"__AVR_HAVE_8BIT_SP__"and"__AVR_HAVE_16BIT_SP__"โ The compiler treats the stack pointer (SP) register as an 8-bit or 16-bit register, respectively. The definition of these macros is affected by-mtiny-stack. ๐ซถ"__AVR_HAVE_SPH__"and"__AVR_SP8__"โ The device has the SPH (high part of stack pointer) special function register, or has an 8-bit stack pointer, respectively. The definition of these macros is affected by-mmcu=, and in the cases of-mmcu=avr2and-mmcu=avr25also by-msp8. โจ"__AVR_HAVE_RAMPD__","__AVR_HAVE_RAMPX__","__AVR_HAVE_RAMPY__"and"__AVR_HAVE_RAMPZ__"โ The device has the"RAMPD","RAMPX","RAMPY"and"RAMPZ"special function registers, respectively. ๐"__NO_INTERRUPTS__"โ This macro reflects the-mno-interruptscommand-line option. ๐"__AVR_ERRATA_SKIP__"and"__AVR_ERRATA_SKIP_JMP_CALL__"โ Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum. The skip instructions are"SBRS","SBRC","SBIS","SBIC"and"CPSE". The second macro is only defined if"__AVR_HAVE_JMP_CALL__"is also set. ๐"__AVR_ISA_RMW__"โ The device has Read-Modify-Write instructions (XCH, LAC, LAS and LAT). ๐"__AVR_SFR_OFFSET__=offset"โ Instructions that can address I/O special function registers directly, like"IN","OUT","SBI", etc., may use a different address than an instruction accessing RAM, like"LD"or"STS". 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 with"LD*"instructions. The flash memory is seen in the data address space at an offset of"__AVR_PM_BASE_ADDRESS__". If this macro is not defined, this feature is not available. If it is defined, the address space is linear and there is no need to put".rodata"into RAM. This is handled by the default linker description file and is currently available for"avrtiny"and"avrxmega3". Even more convenient, there is no need to use address spaces like"__flash"or features like the attribute"progmem"and"pgm_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__"and"__HAVE_DOUBLE64__"โ Defined if the compiler supports 32-bit double or 64-bit double, respectively. The actual layout is specified by the-mdouble=option. ๐ซถ"__DEFAULT_DOUBLE__"โ The size in bits of"double"if-mdouble=is not set. To test the layout of"double"in a program, use the built-in macro"__SIZEOF_DOUBLE__". โจ"__HAVE_LONG_DOUBLE32__","__HAVE_LONG_DOUBLE64__","__HAVE_LONG_DOUBLE_MULTILIB__"and"__DEFAULT_LONG_DOUBLE__"โ Same as above, but for"long double"instead of"double". ๐"__WITH_DOUBLE_COMPARISON__"โ 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__"and"__WITH_LIBF7_MATH_SYMBOLS__"โ Reflect 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. Right now, cpu can be one ofbf512,bf514,bf516,bf518,bf522,bf523,bf524,bf525,bf526,bf527,bf531,bf532,bf533,bf534,bf536,bf537,bf538,bf539,bf542,bf544,bf547,bf548,bf549,bf542m,bf544m,bf547m,bf548m,bf549m,bf561orbf592. ๐ฅ
The optional sirevision specifies the silicon revision of the target Blackfin processor. Any workarounds available for the targeted silicon revision get 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: support forbf561is incomplete. Forbf561, only the preprocessor macro is defined.
-msimโ Specifies that the program will run on the simulator. This causes the simulator BSP provided by libgloss to be linked in. This option only has an effect for thebfin-elftoolchain. Certain other options, such as-mid-shared-libraryand-mfdpic, imply-msim. ๐ฆ-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions. This avoids the instructions that save, set up and restore frame pointers, and it makes an extra register available in leaf functions. ๐ซถ-mspecld-anomalyโ When enabled, the compiler makes sure the generated code does not contain speculative loads after jump instructions. If this option is used,"__WORKAROUND_SPECULATIVE_LOADS"is defined. ๐-mno-specld-anomalyโ Don't generate extra code to prevent speculative loads from happening. ๐-mcsync-anomalyโ When enabled, the compiler makes sure the generated code does not contain CSYNC or SSYNC instructions too soon after conditional branches. If this option is used,"__WORKAROUND_SPECULATIVE_SYNCS"is defined. โจ-mno-csync-anomalyโ Don't generate extra code to prevent CSYNC or SSYNC instructions from happening too soon after a conditional branch. ๐-mlow64kโ When enabled, the compiler is free to take advantage of the knowledge that the entire program fits into the low 64k of memory. ๐-mno-low64kโ Assume that the program is arbitrarily large. This is the default. ๐-mstack-check-l1โ Does stack checking using information placed into L1 scratchpad memory by the uClinux kernel. ๐-mid-shared-libraryโ Generates code that supports shared libraries via the library ID method. This allows for execute in place and shared libraries in an environment without virtual memory management. This option implies-fPIC. With abfin-elftarget, this option implies-msim. ๐ง-mno-id-shared-libraryโ Generates code that doesn't assume ID-based shared libraries are being used. This is the default. ๐-mleaf-id-shared-libraryโ okay so this one makes code that works with ID shared libraries using the library ID method ๐ฆ but assumes your library or executable won't link against any other ID shared libraries. That assumption lets the compiler use faster code for jumps and calls โจ-mno-leaf-id-shared-libraryโ the opposite energy ๐ this doesn't assume the code avoids linking with ID shared libraries, so you get slower code for jump and call insns ๐ข-mshared-library-id=nโ sets the identification number of the ID-based shared library you're compiling ๐ A value of0gives you more compact code ๐ Any other value forces that number onto the current library, but it's no more space- or time-efficient than just leaving this option out ๐-msep-dataโ lowkey iconic: this lets the data segment live in a different area of memory from the text segment ๐ง That makes execute in place possible in an environment without virtual memory management, because it gets rid of relocations against the text section โญ-mno-sep-dataโ this one assumes the data segment follows the text segment ๐ธ This is the default ๐-mlong-calls,-mno-long-callsโ the vibe here is calling a function by first loading its address into a register and then doing a subroutine call on that register ๐ซถ You need this if the target function sits outside the 24-bit addressing range of the offset-based subroutine call instruction ๐ญ It's not enabled by default, and-mno-long-callsputs you back on the default behaviour ๐ Heads up though: these switches don't change how function calls through function pointers get generated ๐-mfast-fpโ links with the fast floating-point library โก It relaxes some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN) ๐ฅ all for performance, bestie-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally ๐ฆ Fun fact: it does nothing without-mfdpic๐-mmulticoreโ builds a standalone application for multicore Blackfin processors ๐ This makes the compiler use proper start files and link scripts that support multicore, and it defines the macro"__BFIN_MULTICORE"๐ It can only be used with-mcpu=bf561[-sirevision]โจ
This one plays nicely with -mcorea or -mcoreb, which pick the one-application-per-core programming model ๐ Without either of those, you get the single-application/dual-core programming model ๐ธ In that model, the main function of Core B should be named "coreb_main" ๐ง
If you skip this option entirely, you get the single-core application programming model ๐
-mcoreaโ builds a standalone application for Core A of BF561 when you're using the one-application-per-core programming model ๐ซถ Proper start files and link scripts support Core A, and the macro"__BFIN_COREA"gets defined ๐ฅ Only usable together with-mmulticoreโญ-mcorebโ same vibe, but for Core B of BF561 ๐ฆ It defines"__BFIN_COREB", and when you use this,"coreb_main"should be used instead of"main"๐ Only usable together with-mmulticore๐-msdramโ builds a standalone application for SDRAM ๐ Proper start files and link scripts put the application into SDRAM, and the macro"__BFIN_SDRAM"is defined ๐ The loader needs to initialize SDRAM before loading the application ๐ญ-micplbโ assumes ICPLBs are enabled at run time ๐ This affects certain anomaly workarounds ๐ง For Linux targets, the default is to assume ICPLBs are enabled, but for standalone applications the default is off ๐
๐ฆ C6X Options ๐ฆ
-march=nameโ this specifies the name of the target architecture ๐ง GCC uses that name to figure out what kinds of instructions it's allowed to emit when generating assembly code โจ The permissible names are:c62x,c64x,c64x+,c67x,c67x+,c674x๐-mbig-endianโ generates code for a big-endian target ๐ธ-mlittle-endianโ generates code for a little-endian target ๐ This is the default ๐-msimโ picks startup files and a linker script that suit the simulator ๐-msdata=defaultโ puts small global and static data in the".neardata"section, which is pointed to by registerB14๐ซถ Small uninitialized global and static data goes in the".bss"section, which sits right next to".neardata"๐ฅ Small read-only data goes in the".rodata"section ๐ The matching sections for big chunks of data are".fardata",".far"and".const"โจ-msdata=allโ puts all data, not just the small stuff, into the sections reserved for small data ๐ It also uses addressing relative to theB14register to get to them ๐ฆ-msdata=noneโ makes no use of the sections reserved for small data, and uses absolute addresses to access all data ๐ All initialized global and static data goes in".fardata", and all uninitialized data goes in".far"๐ All constant data goes in the".const"section ๐
๐ธ 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 for architecture-type arev3,v8andv10, which are for ETRAX 4, ETRAX 100, and ETRAX 100 LX respectively ๐ The default isv0, except forcris-axis-linux-gnu, where the default isv10๐-mtune=architecture-typeโ tunes everything applicable about the generated code to architecture-type, except for the ABI and the set of available instructions ๐ฆ The choices are the same as for-march=architecture-type๐-mmax-stack-frame=nโ warns when the stack frame of a function goes over n bytes ๐ญ-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 for CPU models where it applies ๐ง This option is disabled by default ๐-mpdebugโ enables CRIS-specific verbose debug-related information in the assembly code ๐ซถ It also turns off the#NO_APPformatted-code indicator to the assembler at the beginning of the assembly file ๐-mcc-initโ don't use condition-code results from previous instructions ๐ธ Always emit compare and test instructions before using condition codes โจ-mno-side-effectsโ doesn't emit instructions with side effects in addressing modes other than post-increment ๐ง-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ these (theno-ones eliminate the arrangement) make the stack frame, individual data and constants aligned to the maximum single data access size for the chosen CPU model ๐ The default is 32-bit alignment ๐ ABI details such as structure layout aren't affected by these options ๐-m32-bit,-m16-bit,-m8-bitโ kinda like the stack, data and const align options above ๐ฆ These arrange for the stack frame, writable data and constants to all be 32-bit, 16-bit or 8-bit aligned ๐ The default is 32-bit alignment ๐-mno-prologue-epilogue,-mprologue-epilogueโ with-mno-prologue-epilogue, the normal function prologue and epilogue that set up the stack frame are left out ๐ญ No return instructions or return sequences get generated either ๐
โ ๏ธ Use this option only together with visual inspection of the compiled code ๐ No warnings or errors are generated when call-saved registers must be saved, or when storage for local variables needs to be allocated.
-mno-gotplt,-mgotpltโ with-fpicand-fPIC,-mno-gotpltmeans don't generate instruction sequences that load addresses for functions from the PLT part of the GOT, and-mgotpltmeans do generate them ๐ฅ The traditional approach on other architectures is calls to the PLT instead ๐ The default is-mgotpltโจ-melfโ a legacy no-op option that's only recognized with thecris-axis-elfandcris-axis-linux-gnutargets ๐ฐ๏ธ-mlinuxโ another legacy no-op option, only recognized with thecris-axis-linux-gnutarget ๐ฐ๏ธ-simโ recognized for thecris-axis-elftarget ๐ฎ It links with input-output functions from a simulator library ๐ธ Code, initialized data and zero-initialized data are allocated consecutively ๐ง-sim2โ like-sim, but it passes linker options to locate initialized data at0x40000000and zero-initialized data at0x80000000๐
๐ CR16 Options ๐
These options are defined specifically for the CR16 ports ๐ซถ
-mmacโ enables the use of multiply-accumulate instructions ๐ฅ Disabled by default ๐-mcr16cplus,-mcr16cโ generates code for the CR16C or CR16C+ architecture ๐ The CR16C+ architecture is the default โจ-msimโ links the librarylibsim.a, which is compatible with the simulator ๐ Applicable to the ELF compiler only ๐ง-mint32โ chooses the integer type to be 32-bit wide ๐ฆ-mbit-opsโ generates"sbit"/"cbit"instructions for bit manipulations ๐-mdata-model=modelโ chooses a data model ๐ธ The choices for model arenear,farormedium, andmediumis the default ๐ Heads up:faris not 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 for arch are:ck801,ck802,ck803,ck807, andck810๐ The default isck810๐-mcpu=cpuโ specifies the C-SKY target processor ๐ฅ Valid values for cpu are:ck801,ck801t,ck802,ck802t,ck802j,ck803,ck803h,ck803t,ck803ht,ck803f,ck803fh,ck803e,ck803eh,ck803et,ck803eht,ck803ef,ck803efh,ck803ft,ck803eft,ck803efht,ck803r1,ck803hr1,ck803tr1,ck803htr1,ck803fr1,ck803fhr1,ck803er1,ck803ehr1,ck803etr1,ck803ehtr1,ck803efr1,ck803efhr1,ck803ftr1,ck803eftr1,ck803efhtr1,ck803s,ck803st,ck803se,ck803sf,ck803sef,ck803seft,ck807e,ck807ef,ck807,ck807f,ck810e,ck810et,ck810ef,ck810eft,ck810,ck810v,ck810f,ck810t,ck810fv,ck810tv,ck810ft, andck810ftv๐-mbig-endian,-EB,-mlittle-endian,-ELโ okay so you get to pick your byte order ๐ Big-endian or little-endian, your call. Little-endian is the default, so you don't have to do anything if you're happy with that ๐ธ-mfloat-abi=nameโ ๐ฆ this one picks the floating-point ABI. Your choices aresoft,softfp, andhard:softmakes GCC spit out library calls for floating-point operations.softfplets it use hardware floating-point instructions but still sticks with the soft-float calling conventions.hardgives you floating-point instructions and FPU-specific calling conventions.
The default depends on your target configuration.
โ ๏ธ bestie, the hard-float and soft-float ABIs are NOT link-compatible. You have to compile your entire program with the same ABI and link it against a compatible set of libraries, or it's going to be a whole mess ๐
-mhard-float,-msoft-floatโ pick hardware or software floating-point implementations. The default is soft float โจ-mdouble-float,-mno-double-floatโ when-mhard-floatis in effect, this turns on generation of double-precision float instructions. It's the default except when compiling for CK803 ๐-mfdivdu,-mno-fdivduโ when-mhard-floatis in effect, this enables generation of"frecipd","fsqrtd", and"fdivd"instructions. Also the default except when compiling for CK803 ๐-mfpu=fpuโ selects the floating-point processor. This can only be used with-mhard-float๐ฅ The values for fpu are:fpv2_sf, which is the same as-mno-double-float -mno-fdivdufpv2, which is-mdouble-float -mno-divdufpv2_divd, which is-mdouble-float -mdivdu
-melrw,-mno-elrwโ enables the extended"lrw"instruction. It's on by default for CK801 and off for everything else ๐ง-mistack,-mno-istackโ turns on interrupt stack instructions. Default is off.
-mistackis required if you want to handle the"interrupt"and"isr"function attributes, so don't skip it!
-mmpโ enables multiprocessor instructions. Default is off ๐-mcpโ enables coprocessor instructions. Default is off ๐ฆ-mcacheโ also enables coprocessor instructions. Default is off ๐-msecurityโ enables C-SKY security instructions. Default is off ๐-mtrustโ enables C-SKY trust instructions. Default is off ๐ซถ-mdsp,-medsp,-mvdspโ enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively. All three default to off ๐-mdiv,-mno-divโ generates divide instructions. Default is off โจ-msmart,-mno-smartโ generates code for Smart Mode, which only uses registers numbered 0-7 so 16-bit instructions can be used ๐ This gets ignored for CK801, where it's already required, and it defaults to on for CK802. For other targets, it's off.-mhigh-registers,-mno-high-registersโ generates 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โ generates code using global anchor symbol addresses ๐ธ-mpushpop,-mno-pushpopโ generates code using"push"and"pop"instructions. Defaults to on ๐-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ generates code using"stm"and"ldm"instructions. This isn't supported on CK801, but it's enabled by default on other processors ๐-mconstpool,-mno-constpoolโ creates constant pools in the compiler instead of handing that job off to the assembler. This is the default and is required for correct code generation on CK801 and CK802. It's optional on other processors ๐ง-mstack-size,-mno-stack-sizeโ emits".stack_size"directives for each function in the assembly output. Defaults to off โจ-mccrt,-mno-ccrtโ generates code for the C-SKY compiler runtime instead of libgcc. Defaults to off ๐ฆ-mbranch-cost=nโ sets the branch costs to roughly"n"instructions. The default is 1 ๐-msched-prolog,-mno-sched-prologโ lets the scheduler move around function prologue and epilogue sequences. โ ๏ธ This can give you code that doesn't follow the C-SKY V2 ABI prologue requirements, and that code can't be debugged or backtraced. It's disabled by default, so please don't turn it on unless you know exactly why ๐-msimโ links the librarylibsemi.a, which works 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 doesn't make "fat" object files. It makes an object file for the single architecture GCC was built to target ๐ซถ Apple's GCC is different, though: it does make fat files when you use multiple -arch options. It does that by running the compiler or linker multiple times and then joining the results together with lipo ๐ง
The subtype of the file (like ppc7400, ppc970, or i686) gets decided by the flags that specify the ISA GCC is targeting, like -mcpu or -march. The -force_cpusubtype_ALL option can override this ๐
The Darwin tools act differently when they hit an ISA mismatch. The assembler, as, only lets you use instructions that are valid for the subtype of the file it's generating. So you literally cannot put 64-bit instructions in a ppc750 object file ๐ The linker for shared libraries, /usr/bin/libtool, fails and prints an error if you ask it to make 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 left-to-right ๐ฆ
A framework directory is a directory full of frameworks. A framework is a directory that has a Headers and/or PrivateHeaders directory sitting directly inside it, and its name ends in .framework. The name of a framework is just the directory name without the .framework part. Headers for the framework live in one of those two directories, and Headers gets searched first ๐
A subframework is a framework directory that lives inside a framework's Frameworks directory. Includes of subframework headers can only show up in a header from the framework that contains the subframework, or in a sibling subframework header. Two subframeworks are siblings if they're in the same framework ๐ฏ
A subframework shouldn't have the same name as a framework, and GCC will warn you if it does. Right now a subframework can't have subframeworks of its own, but that might get added later ๐
The standard frameworks live in /System/Library/Frameworks and /Library/Frameworks. An example include looks like #include <Framework/header.h>, where Framework is the framework's name and header.h is found in either the PrivateHeaders or Headers directory ๐
-iframeworkdirโ works like-F, except the directory gets treated as a system directory. The big difference is that with-iframework, the compiler won't warn you about constructs inside header files found throughdir. This option is only valid for the C family of languages ๐-gusedโ emits debugging info for symbols that are used. For the stabs debugging format, this enables-feliminate-unused-debug-symbols. It's on by default โจ-gfullโ emits debugging info for all symbols and types ๐-mmacosx-version-min=versionโ the earliest version of MacOS X this executable will run on isversion. Typical values include10.1,10.2, and10.3.9๐ If the compiler was built to use the system's headers by default, the default for this option is the system version the compiler is running on. Otherwise, the default 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-rttiwhere 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 that"sizeof(bool)==1". By default,"sizeof(bool)"is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86. That means this option does nothing on x86 ๐
๐จ Warning, bestie: the -mone-byte-bool switch makes GCC generate code that isn't binary compatible with code generated without it. You might have to recompile all the other modules in your program, including system libraries. Only use this switch to conform to a non-default data model.
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ generates code that's good for fast turnaround development, like letting GDB dynamically load.ofiles into programs that are already running ๐ฅ-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 errors about files with the wrong architecture fatal ๐-bind_at_loadโ marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched ๐ฆ-bundleโ produces a Mach-o bundle format file. Seeman ld(1)for more information ๐-bundle_loader executableโ specifies the executable that will load the build output file being linked. Seeman ld(1)for more information ๐ง-dynamiclibโ when you pass this, GCC produces a dynamic library instead of an executable when linking, using the Darwinlibtoolcommand ๐-force_cpusubtype_ALLโ gives GCC's output file the ALL subtype, instead of one controlled by the-mcpuor-marchoption ๐-allowable_client client_name-client_name-compatibility_version-current_version-dead_strip-dependency-file-dylib_file-dylinker_install_name-dynamic-exported_symbols_list-filelist-flat_namespace-force_flat_namespace-headerpad_max_install_names-image_base-init-install_name-keep_private_externs-multi_module-multiply_defined-multiply_defined_unused-noall_load-no_dead_strip_inits_and_terms-nofixprebinding-nomultidefs-noprebind-noseglinkedit-pagezero_size-prebind-prebind_all_twolevel_modules-private_bundle-read_only_relocs-sectalign-sectobjectsymbols-whyload-seg1addr-sectcreate-sectobjectsymbols-sectorder-segaddr-segs_read_only_addr-segs_read_write_addr-seg_addr_table-seg_addr_table_filename-seglinkedit-segprot-segs_read_only_addr-segs_read_write_addr-single_module-static-sub_library-sub_umbrella-twolevel_namespace-umbrella-undefined-unexported_symbols_list-weak_reference_mismatches-whatsloaded
These options are passed straight through to the Darwin linker ๐โจ. The Darwin linker man page is where you'll find the full tea on all of them, bestie ๐ .
๐ DEC Alpha Options
These -m options are defined for the DEC Alpha implementations ๐ฆ:
-mno-soft-float,-msoft-floatโ Okay so these two are opposites ๐.-mno-soft-floatsays "yes, use the hardware floating-point instructions," and-msoft-floatsays "nope, don't." When you use-msoft-float, the floating-point operations get handled by functions inlibgcc.a๐ง. Unless those get swapped out for routines that emulate the floating-point stuff, or they're compiled to call those emulation routines, the functions in there will actually issue floating-point operations. So if you're compiling for an Alpha without floating-point operations, you absolutely have to make sure the library is built so it doesn't call them ๐ญ.
Also, Alpha implementations without floating-point operations are still required to have floating-point registers ๐.
-mfp-reg,-mno-fp-regsโ These tell GCC to generate code that uses (or doesn't use) the floating-point register set ๐ธ.-mno-fp-regsautomatically implies-msoft-float๐ซถ. If the floating-point register set isn't being used, floating-point operands get passed in integer registers as if they were integers, and floating-point results come back 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-regshas to be compiled with that option too, or it's a whole mess ๐.
A typical use of this option is building a kernel that doesn't use (and therefore doesn't need to save and restore) any floating-point registers ๐.
-mieeeโ The Alpha architecture has floating-point hardware that's optimized for maximum performance, and it's mostly IEEE compliant ๐ฅ. For full compliance, though, it needs some software help ๐ค. This option generates code that's fully IEEE-compliant, except the inexact-flag doesn't get maintained (more on that below โฌ๏ธ). If you turn this on, the preprocessor macro"_IEEE_FP"gets defined during compilation โจ. The resulting code is slower, but it can correctly support denormalized numbers and exceptional IEEE values like not-a-number and plus/minus infinity ๐. Other Alpha compilers call this option-ieee_with_no_inexact.
DEBIAN SPECIFIC: This option is on by default for alpha-linux-gnu, unless-ffinite-math-only(which is part of the-ffast-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 ๐. Along with"_IEEE_FP", the macro"_IEEE_FP_EXACT"gets defined too โจ. On some Alpha implementations the code can run significantly slower than the default output ๐ข. Since there's very little code that depends on the inexact-flag, you should normally not specify this option ๐. Other Alpha compilers call this option-ieee_with_inexact.-mfp-trap-mode=trap-modeโ This controls which floating-point related traps are enabled ๐จ. Other Alpha compilers call this option-fptm trap-mode. The trap mode can be set to one of four values:nโ This is the default (normal) setting ๐ธ. The only traps that get enabled are the ones that can't be disabled in software, like division by zero.uโ In addition to everythingnenables, underflow traps are enabled as well ๐ฆ.suโ Likeu, but the instructions are marked as safe for software completion (check the Alpha architecture manual for the deets ๐).suiโ Likesu, but inexact traps are enabled as well ๐ .
-mfp-rounding-mode=rounding-modeโ This selects the IEEE rounding mode ๐. Other Alpha compilers call this option-fprm rounding-mode. Therounding-modecan be one of:nโ Normal IEEE rounding mode ๐. Floating-point numbers 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,dbasically means round towards plus infinity โญ.
-mtrap-precision=trap-precisionโ Okay, real talk: in the Alpha architecture, floating-point traps are imprecise ๐ญ. Without software help, it's impossible to recover from a floating trap, and the program usually 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โ This option 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 looks at a 32- or 64-bit integer constant to see if it can build it from smaller constants in two or three instructions ๐งฉ. If it can't, it outputs the constant as a literal and generates code to load it from the data segment at run time. With this option, you're telling GCC to build all integer constants using code, even if that takes more instructions (the maximum is six) ๐ ๏ธ. You typically use this when building a shared library dynamic loader ๐. Since it's itself a shared library, it has to relocate itself in memory before it can find the variables and constants in its own data segment ๐คฏ.-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ These 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 the CPU that GCC was built on if you don't specify one ๐.-mfloat-vax,-mfloat-ieeeโ These generate 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 ๐. Using those macros doesn'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 capabilities of the assembler when it's built and sets the default accordingly ๐.-msmall-data,-mlarge-dataโ When-mexplicit-relocsis in effect, static data is accessed via gp-relative relocations ๐ธ. When-msmall-datais used, objects 8 bytes long or smaller are placed in a small data area (the".sdata"and".sbss"sections) and 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 directly accessed 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 ๐.
-msmall-text,-mlarge-textโ When-msmall-textis used, the compiler assumes the code of the entire program (or shared library) fits in 4MB, so it's reachable with a branch instruction ๐โโ๏ธ. When-msmall-datais used, the compiler can assume all local symbols share the same$gpvalue, which cuts the number of instructions needed for a function call from 4 to 1 ๐ค.
The default is -mlarge-text ๐.
-mcpu=cpu_typeโ okay bestie, this one sets the instruction set AND the scheduling parameters for machine typecpu_type๐. You can name it with the EV style name or the matching chip number, both work โจ. GCC has scheduling params for the EV4, EV5, and EV6 family and picks the default instruction set from whatever processor you specify ๐ฅ. No processor type? It defaults to the processor the compiler was built on ๐. Supported values forcpu_typeare:ev4,ev45,21064โ schedules as an EV4 and has no instruction set extensions ๐ธev5,21164โ schedules as an EV5 and has no instruction set extensions ๐ธev56,21164aโ schedules as an EV5 and supports the BWX extension ๐ฆpca56,21164pc,21164PCโ schedules as an EV5 and supports the BWX and MAX extensions ๐ฆev6,21264โ schedules as an EV6 and supports the BWX, FIX, and MAX extensions ๐ev67,21264aโ schedules as an EV6 and supports the BWX, CIX, FIX, and MAX extensions ๐
Native toolchains also support the value native, which picks the best architecture option for the host processor, it's giving convenience ๐
. -mcpu=native has no effect if GCC does not recognize the processor ๐.
-mtune=cpu_typeโ this one is lowkey the chill sibling ๐ซถ. It sets ONLY the instruction scheduling parameters for machine typecpu_type, and the instruction set stays exactly the same โจ.
Native toolchains also support the value native, which picks the best architecture option for the host processor ๐. -mtune=native has no effect if GCC does not recognize the processor ๐ญ.
-mmemory-latency=timeโ this sets the latency the scheduler should assume for typical memory references as the application sees them ๐ง. The number is highly dependent on the application's memory access patterns and the size of the external cache on the machine, so it's a whole vibe check ๐ฅ. Valid options fortimeare: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 ๐. Note thatL3is only valid for EV5 ๐.
๐ง eBPF Options ๐ง
-mframe-limit=bytesโ this is the hard limit for frame sizes, in bytes ๐. Right now the value you pass should be less than or equal to32767. It defaults to whatever limit is imposed by the version of the Linux kernel being targeted ๐ง.-mkernel=versionโ this is the minimum kernel version that'll run your compiled program โจ. GCC uses it to decide which instructions to use, which kernel helpers to allow, etc. ๐ Currently,versioncan be one of4.0,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,4.10,4.11,4.12,4.13,4.14,4.15,4.16,4.17,4.18,4.19,4.20,5.0,5.1,5.2,latestandnative๐ธ.-mbig-endianโ generate code for a big-endian target ๐ฆ.-mlittle-endianโ generate code for a little-endian target. This is the default, so you're already good ๐ซถ.-mjmpextโ enable generation of extra conditional-branch instructions. Enabled for CPU v2 and above ๐.-mjmp32โ enable 32-bit jump instructions. Enabled for CPU v3 and above โญ.-malu32โ enable 32-bit ALU instructions. Enabled for CPU v3 and above โญ.-mcpu=versionโ this picks which version of the eBPF ISA you're targeting ๐. Newer versions may not be supported by all kernels, so check your vibes first ๐. The default isv3. Supported values forversionare:v1โ the first stable eBPF ISA, with no special features or extensions ๐ฑv2โ supports the jump extensions, as in-mjmpext๐ฆv3โ all features of v2, plus:-<32-bit jump operations, as in -mjmp32>๐-<32-bit ALU operations, as in -malu32>๐
-mco-reโ enable BPF Compile Once - Run Everywhere (CO-RE) support ๐. It requires and is implied by-gbtf.-mno-co-reโ disable BPF Compile Once - Run Everywhere (CO-RE) support ๐ซ. BPF CO-RE support is enabled by default when generating BTF debug information for the BPF target, so you'd have to opt out on purpose ๐.-mxbpfโ generate code for an expanded version of BPF that relaxes some of the restrictions imposed by the BPF architecture ๐ฅ. Like, it does things such as:-<Save and restore callee-saved registers at function entry and exit, respectively.>โจ
๐ฆ FR30 Options ๐ฆ
These options are defined specifically for the FR30 port, bestie ๐.
-msmall-modelโ use the small address space model ๐ธ. This can produce smaller code, but it does assume that all symbolic values and addresses fit into a20-bitrange ๐.-mno-lsimโ assume runtime support has been provided, so there's no need to include the simulator library (libsim.a) on the linker command line ๐.
๐ FT32 Options ๐
These options are defined specifically for the FT32 port ๐ง.
-msimโ this says the program will run on the simulator ๐ฅ๏ธ. It causes an alternate runtime startup and library to be linked.
โ ๏ธ Bestie, you must NOT use this option when generating programs that will run on real hardware! You have to provide your own runtime library for whatever I/O functions are needed ๐ญ.
-mlraโ enable Local Register Allocation ๐. It's still experimental for FT32, so by default the compiler uses standard reload ๐งช.-mnodivโ do not usedivandmodinstructions ๐ซ.-mft32bโ enable use of the extended instructions of the FT32B processor โญ.-mcompressโ compress all code using the Ft32B code compression scheme ๐๏ธ.-mnopmโ do not generate code that reads program memory ๐ โโ๏ธ.
๐ FRV Options ๐
-mgpr-32โ only use the first 32 general-purpose registers ๐.-mgpr-64โ use all 64 general-purpose registers ๐.-mfpr-32โ use only the first 32 floating-point registers ๐ธ.-mfpr-64โ use all 64 floating-point registers ๐ .-mhard-floatโ use hardware instructions for floating-point operations ๐ฅ.-msoft-floatโ use library routines for floating-point operations ๐งธ.-malloc-ccโ dynamically allocate condition code registers โจ.-mfixed-ccโ don't try to dynamically allocate condition code registers. Only useicc0andfcc0๐.-mdwordโ change the ABI to use double word insns ๐.-mno-dwordโ don't use double word instructions ๐ซ.-mdoubleโ use floating-point double instructions ๐ฆ.-mno-doubleโ don't use floating-point double instructions ๐.-mmediaโ use media instructions ๐ถ.-mno-mediaโ don't use media instructions ๐.-mmuladdโ use multiply and add/subtract instructions โ.-mno-muladdโ don't use multiply and add/subtract instructions โ.-mfdpicโ select 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โ enable inlining of PLT entries in function calls to functions that are not known to bind locally ๐. It has no effect without-mfdpic. It's enabled by default if you're optimizing for speed and compiling for shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is in the command line ๐.-mTLSโ assume a large TLS segment when generating thread-local code ๐งต.-mtlsโ do not assume a large TLS segment when generating thread-local code ๐ชก.-mgprel-roโ enable the use of "GPREL" relocations in the FDPIC ABI for data that is known to be in read-only sections ๐. It's enabled by default, except for-fpicor-fpie. Even though it may help make the global offset table smaller, it trades 1 instruction for 4 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โ link 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โ follow the EABI requirement of always creating a frame pointer whenever a stack frame is allocated ๐๏ธ. This option is enabled by default and can be disabled with-mno-linked-fp๐.-mlong-callsโ use indirect addressing to call functions outside the current compilation unit ๐. This allows the functions to be placed anywhere within the 32-bit address space ๐.-malign-labelsโ try to align labels to an 8-byte boundary by inserting NOPs into the previous packet ๐. This option only has an effect when VLIW packing is enabled. It doesn't create new packets; it merely adds NOPs to existing ones ๐ .-mlibrary-picโ generate position-independent EABI code ๐งญ.-macc-4โ use only the first four media accumulator registers 4๏ธโฃ.-macc-8โ use all eight media accumulator registers 8๏ธโฃ.-mpackโ pack VLIW instructions ๐ฆ.-mno-packโ do not pack VLIW instructions ๐ โโ๏ธ.-mno-eflagsโ do not mark ABI switches ine_flags๐ซ.-mcond-moveโ enable the use of conditional-move instructions (default) โจ.
This switch is mainly for debugging the compiler and will likely be removed in a future version ๐.
-mno-cond-moveโ disable the use of conditional-move instructions ๐ซ.
This switch is mainly for debugging the compiler and will likely be removed in a future version ๐.
-msccโ enable the use of conditional set instructions (default) ๐.
This switch is mainly for debugging the compiler and will likely be removed in a future version ๐.
-mno-sccโ disable the use of conditional set instructions ๐ซ.
This switch is mainly for debugging the compiler and will likely be removed in a future version ๐.
-mcond-execโ enable the use of conditional execution (default) ๐ท.
This switch is mainly for debugging the compiler and will likely be removed in a future version ๐.
-mno-cond-execโ disable the use of conditional execution ๐ซ.
This switch is mainly for debugging the compiler and will likely be removed in a future version ๐.
-mvliw-branchโ ๐ Turns on the pass that packs branches into VLIW instructions. This one's the default โจ. It's mainly a compiler-debugging switch and will likely get removed in a future version ๐.-mno-vliw-branchโ ๐ซ Skips that branch-packing pass entirely. Same deal: debugging-only, and it'll probably be yeeted later.-mmulti-cond-execโ ๐ฅ Enables optimization of"&&"and"||"in conditional execution (default). Debugging-only, likely removed down the road.-mno-multi-cond-execโ ๐ Turns that"&&"and"||"conditional execution optimization off. Also mostly for debugging, and likely to be removed.-mnested-cond-execโ ๐ Enables nested conditional execution optimizations (default). Debugging-only, and it'll likely be removed later.-mno-nested-cond-execโ ๐ซถ Disables those nested conditional execution optimizations. Also debugging-only and likely to be removed.-moptimize-membarโ โจ Removes redundant"membar"instructions from the compiler-generated code. It's on by default, so you get the cleanup for free ๐ .-mno-optimize-membarโ ๐ Stops the automatic removal of redundant"membar"instructions, so they stay in the generated code.-mtomcat-statsโ ๐ Makesgasprint out tomcat statistics.-mcpu=cpuโ ๐ Picks the processor type you want code generated for. The possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300andsimple.
โจ GNU/Linux Options โจ
okay so these -m options only exist for GNU/Linux targets ๐ง๐
-mglibcโ ๐ Uses the GNU C library. This is the default, except on*-*-linux-*uclibc*,*-*-linux-*musl*and*-*-linux-*android*targets.-muclibcโ ๐ Uses the uClibc C library. This is the default on*-*-linux-*uclibc*targets.-mmuslโ ๐ง Uses the musl C library. This is the default on*-*-linux-*musl*targets.-mbionicโ ๐ฆ Uses the Bionic C library. This is the default on*-*-linux-*android*targets.-mandroidโ ๐ค Compiles code that's compatible with the Android platform. This is the default on*-*-linux-*android*targets, and it's giving main character energy.- When compiling, it turns on
-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default. - When linking, the GCC driver passes Android-specific options to the linker.
- It also causes the preprocessor macro
__ANDROID__to be defined.
- When compiling, it turns on
-tno-android-ccโ ๐ Turns off the compilation effects of-mandroid, so-mbionic,-fPIC,-fno-exceptionsand-fno-rttiwon't be enabled by default.-tno-android-ldโ ๐ Turns off the linking effects of-mandroid, so the linker just gets standard Linux linking options.
๐ธ H8/300 Options ๐ธ
these -m options are defined for the H8/300 implementations, bestie ๐
-mrelaxโ โฉ Shortens some address references at link time when it's possible. It uses the linker option-relaxto do it.-mhโ ๐ Generates code for the H8/300H.-msโ ๐ Generates code for the H8S.-mnโ ๐ Generates code for the H8S and H8/300H in the normal mode. This one has to be used with either-mhor-ms.-ms2600โ ๐ฆ Generates code for the H8S/2600. This one has to be used with-ms.-mexrโ ๐ Extended registers get stored on the stack before a function with the monitor attribute runs. The default is-mexr, and this option is only valid for H8S targets.-mno-exrโ ๐ Extended registers do NOT get stored on the stack before a function with the monitor attribute runs. The default is-mno-exr, and this option is only valid for H8S targets.-mint32โ ๐ข Makes"int"data 32 bits by default.-malign-300โ ๐ On the H8/300H and H8S, it uses the same alignment rules as the H8/300. By default, the H8/300H and H8S align longs and floats on 4-byte boundaries, but-malign-300moves them to 2-byte boundaries. It has no effect on the H8/300.
๐ HPPA Options ๐
these -m options are defined for the HPPA family of computers, and there's a lot of them, so grab a snack ๐ฟ
-march=architecture-typeโ ๐๏ธ Generates code for the architecture you pick. The choices are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors. To find the right one for your machine on an HP-UX system, check out/usr/lib/sched.models. Code compiled for lower numbered architectures runs on higher numbered ones, but not the other way around ๐.-mpa-risc-1-0,-mpa-risc-1-1,-mpa-risc-2-0โ ๐ฏ These are synonyms for-march=1.0,-march=1.1, and-march=2.0, in that order.-mcaller-copiesโ ๐ฆ The caller copies function arguments that get passed by hidden reference. Use this one with care, because it's not compatible with the default 32-bit runtime.
Heads up, bestie: this one isn't compatible with the default 32-bit runtime, so use it carefully. Only aggregates bigger than eight bytes get passed by hidden reference, though, and the option gives you better compatibility with OpenMP ๐ซถ.
-mjump-in-delayโ ๐ฟ This option gets ignored. It's only here for compatibility purposes.-mdisable-fpregsโ ๐ซ Stops floating-point registers from being used in any way. This is necessary for compiling kernels that do lazy context switching of floating-point registers.
Danger zone! If you use this option and then try to do floating-point operations, the compiler aborts ๐.
-mdisable-indexingโ ๐ Stops the compiler from using indexing address modes. This sidesteps some pretty 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. This kind of code is suitable for level 0 PA systems and kernels.-mfast-indirect-callsโ โก Generates code that assumes calls never cross space boundaries, so GCC can emit code that does faster indirect calls.
This one doesn't work if you have shared libraries or nested functions in the picture ๐ญ.
-mfixed-range=register-rangeโ ๐ Generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use, which is super useful when compiling kernel code. You write a register range as two registers separated by a dash, and you can separate multiple ranges with a comma.-mlong-load-storeโ ๐ Generates 3-instruction load and store sequences, which the HP-UX 10 linker sometimes needs. This is equivalent to the+koption on the HP compilers.-mportable-runtimeโ ๐งณ Uses the portable calling conventions HP proposed for ELF systems.-mgasโ ๐งฉ Enables assembler directives that only GAS understands.-mschedule=cpu-typeโ ๐๏ธ Schedules code according to the constraints for the machine typecpu-type. The choices are700 7100, 7100LC, 7200, 7300 and 8000. Check/usr/lib/sched.modelson an HP-UX system to find the right scheduling option for your machine. The default scheduling is8000.-mlinker-optโ ๐ง Enables the optimization pass in the HP-UX linker.
Big warning, 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 that contains library calls for floating point.
Heads up! The required libraries aren't available for all HPPA targets. Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation. You'll have to make your own arrangements to provide suitable library functions for cross-compilation ๐ฌ.
-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile your whole program with this option.- You also need to compile
libgcc.a, the library that comes with GCC, with-msoft-floatfor this to work.
-msioโ ๐ฅ๏ธ Generates the predefine"_SIO"for server IO. The default is-mwsio, which generates the predefines"__hp9000s700","__hp9000s700__"and"_WSIO"for workstation IO. These options are available under HP-UX and HI-UX.-mgnu-ldโ ๐ฃ Uses options specific to GNU ld. This passes-sharedto ld when building a shared library. It's the default when GCC is configured, explicitly or implicitly, with the GNU linker. This option doesn't affect which ld gets called. It only changes which parameters get passed to that ld. The ld that gets called is determined by the--with-ldconfigure option, GCC's program search path, and finally by the user'sPATH. You can print the linker GCC uses withwhichgcc -print-prog-name=ld. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*.-mhp-ldโ ๐ง Uses options specific to HP ld. This passes-bto ld when building a shared library, and it passes+Accept TypeMismatchto ld on all links. It's the default when GCC is configured, explicitly or implicitly, with the HP linker. Just like-mgnu-ld, it doesn't affect which ld gets called, only the parameters passed to it. The ld that gets called is determined by the--with-ldconfigure option, GCC's program search path, and finally by the user'sPATH. You can print the linker GCC uses withwhichgcc -print-prog-name=ld. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*.-mlong-callsโ ๐ Generates code that uses long call sequences. This makes sure a call can always reach linker generated stubs. By default, long calls only get generated when the distance from the call site to the beginning of the function or translation unit (depending on the case) goes past a predefined limit set by the branch type being used. The limits for normal calls are 7,600,000 and 240,000 bytes, for the PA 2.0 and PA 1.X architectures respectively. Sibcalls are always limited at 240,000 bytes.- Distances get measured from the beginning of functions when you use the
-ffunction-sectionsoption, or when you use the-mgasand-mno-portable-runtimeoptions together under HP-UX with the SOM linker. - > It's normally not a great idea to use this one, because it degrades performance ๐. It may still be useful in large applications, especially when partial linking is used to build the application ๐.
- Distances get measured from the beginning of functions when you use the
The types of long calls you get depend on what your assembler and linker can handle, plus the type of code being generated. Systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, should see a relatively small impact. But on 32-bit ELF systems in pic code, an indirect call gets used, and it's quite long ๐ญ
-munix=unix-stdโ Generates compiler predefines and picks a startfile for the UNIX standard you choose ๐ธ The choices are93,95and98.93works on all HP-UX versions.95is available on HP-UX 10.10 and later.98is available on HP-UX 11.11 and later. The defaults are93for HP-UX 10.00,95for HP-UX 10.10 through 11.00, and98for HP-UX 11.11 and later.
-munix=93 gives you the same predefines as GCC 3.3 and 3.4. -munix=95 adds predefines for "XOPEN_UNIX" and "_XOPEN_SOURCE_EXTENDED", plus the startfile unix95.o. -munix=98 adds predefines for "_XOPEN_UNIX", "_XOPEN_SOURCE_EXTENDED", "_INCLUDE__STDC_A1_SOURCE" and "_INCLUDE_XOPEN_SOURCE_500", plus the startfile unix98.o.
โ ๏ธ bestie, this option changes the interfaces for various library routines, and it also affects how the C library behaves. Be extremely careful with it ๐
Library code that's meant to work with more than one UNIX standard has to test, set and restore the variable __xpg4_extended_mask as needed. Most GNU software doesn't do this, so... just know that ๐
-nolibdldโ Stops the generation of link options that searchlibdld.slwhen-staticis used on HP-UX 10 and later ๐-staticโ Okay so, the HP-UX version ofsetlocalein libc depends onlibdld.sl, and there's no archive version oflibdld.sl. That means that when you use-static, special link options are needed to sort this out ๐ง
On HP-UX 10 and later, the GCC driver adds the link options it needs to link with libdld.sl whenever -static is used. This makes the resulting binary dynamic. On the 64-bit port, the linkers make dynamic binaries by default anyway. You can use -nolibdld to stop the GCC driver from adding these link options ๐
-threadsโ Adds multithreading support using the dce thread library under HP-UX. It sets flags for both the preprocessor and the linker ๐งต
๐ IA-64 Options ๐
These are the -m options defined for the Intel IA-64 architecture. Let's go ๐ฅ
-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 code for the GNU assembler, or doesn't. Using-mgnu-asis the default โจ-mgnu-ld,-mno-gnu-ldโ Generates code for the GNU linker, or doesn't. Using-mgnu-ldis the default ๐ฆ-mno-picโ Generates code that doesn't use a global pointer register. The result isn't position independent code, and it violates the IA-64 ABI. Not the vibe ngl ๐-mvolatile-asm-stop,-mno-volatile-asm-stopโ Generates (or doesn't generate) a stop bit right before and right after volatile asm statements ๐-mregister-names,-mno-register-namesโ Generates (or doesn't generate)in,loc, andoutregister names for the stacked registers. This might make the assembler output more readable ๐-mno-sdata,-msdataโ Disables (or enables) optimizations that use the small data section. This can be handy for working around optimizer bugs ๐ ๏ธ-mconstant-gpโ Generates code that uses a single constant global pointer value. This is useful when compiling kernel code ๐-mauto-picโ Generates code that is self-relocatable. This implies-mconstant-gp. It's useful when compiling firmware code ๐งโโ๏ธ-minline-float-divide-min-latencyโ Generates code for inline divides of floating-point values using the minimum latency algorithm โก-minline-float-divide-max-throughputโ Generates code for inline divides of floating-point values using the maximum throughput algorithm ๐-mno-inline-float-divideโ Doesn't generate inline code for divides of floating-point values ๐ โโ๏ธ-minline-int-divide-min-latencyโ Generates code for inline divides of integer values using the minimum latency algorithm โก-minline-int-divide-max-throughputโ Generates code for inline divides of integer values using the maximum throughput algorithm ๐-mno-inline-int-divideโ Doesn't generate inline code for divides of integer values ๐ โโ๏ธ-minline-sqrt-min-latencyโ Generates code for inline square roots using the minimum latency algorithm ๐-minline-sqrt-max-throughputโ Generates code for inline square roots using the maximum throughput algorithm ๐-mno-inline-sqrtโ Doesn't generate inline code forsqrt๐ โโ๏ธ-mfused-madd,-mno-fused-maddโ Does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions. Using these instructions is the default ๐ฅ-mno-dwarf2-asm,-mdwarf2-asmโ Doesn't (or does) generate assembler code for the DWARF line number debugging info. This might be useful when you're not using the GNU assembler ๐-mearly-stop-bits,-mno-early-stop-bitsโ Allows stop bits to be placed earlier than right before the instruction that triggered the stop bit. This can improve instruction scheduling, but it doesn't always ๐คทโโ๏ธ-mfixed-range=register-rangeโ Generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use. This is useful when compiling kernel code ๐ A register range is written as two registers separated by a dash, and you can specify multiple register ranges by separating them 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โ Disables (or enables) data speculative scheduling before reload. This producesld.ainstructions and the matching check instructions (ld.c/chk.a). The default setting is disabled ๐ง-msched-ar-data-spec,-mno-sched-ar-data-specโ Enables (or disables) data speculative scheduling after reload. This producesld.ainstructions and the matching check instructions (ld.c/chk.a). The default setting is enabled ๐-mno-sched-control-spec,-msched-control-specโ Disables (or enables) control speculative scheduling. This feature is only available during region scheduling (i.e. before reload). It produces theld.sinstructions and the matching check instructionschk.s. The default setting is disabled ๐-msched-br-in-data-spec,-mno-sched-br-in-data-specโ Enables (or disables) speculative scheduling of instructions that depend on the data speculative loads before reload. This only matters when-msched-br-data-specis enabled. The default setting is enabled ๐-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ Enables (or disables) speculative scheduling of instructions that depend on the data speculative loads after reload. This only matters when-msched-ar-data-specis enabled. The default setting is enabled ๐-msched-in-control-spec,-mno-sched-in-control-specโ Enables (or disables) speculative scheduling of instructions that depend on the control speculative loads. This only matters when-msched-control-specis enabled. The default setting is enabled ๐ซถ-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ If enabled, data-speculative instructions only get picked for scheduling when there are no other choices at the moment. This makes 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 only get picked for scheduling when there are no other choices at the moment. This makes 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 get considered when computing instruction priorities. This makes 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 aren't 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 later memory insns that try to schedule in the same instruction group. This is often 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, so no more than that number of memory insns can go in one instruction group. Otherwise the limit is "soft", which means non-memory operations are preferred once the limit is reached, but memory operations can still get scheduled ๐ง
๐ฆ LM32 Options ๐ฆ
These -m options are defined for the LatticeMico32 architecture ๐ธ
-mbarrel-shift-enabledโ Enables barrel-shift instructions โจ
-mdivide-enabled Enable divide and modulus instructions.
Continuing on from the M32C stuff โ the rest of the -m options ๐ฆ
Okay so this is where the M32C options wrap up ๐ ...
-mdivide-enabled Turns on the divide and modulus instructions โจ
-mmultiply-enabled Turns on the multiply instructions ๐ธ
-msign-extend-enabled Turns on the sign extend instructions ๐ซถ
-muser-enabled Turns on user-defined instructions ๐
โจ M32C Options โจ
okay bestie, this is the M32C section and it's giving hardware realness ๐ฅ
-mcpu=nameโ picks which CPU you're making code for ๐namecan ber8c(R8C/Tiny series),m16c(M16C, up to /60),m32cm(M16C/80 series), orm32c(M32C/80 series) ๐-msimโ tells GCC your program is going to run on the simulator ๐ง This links in a different runtime library that handles stuff like file I/O.
โ ๏ธ Do NOT use -msim if your code is going on real hardware! You need to bring your own runtime library for whatever I/O you need ๐ญ
-memregs=numberโ sets how many memory-based pseudo-registers GCC uses while generating code ๐ These act like real registers, so it's a tradeoff: fitting code into registers versus the performance hit from using memory instead ๐ Every module in your program has to be compiled with the same value, and you can't use this with GCC's default runtime libraries ๐
โจ M32R/D Options โจ
these -m options are for Renesas M32R/D architectures ๐
-m32r2โ generates code for the M32R/2 ๐ฆ-m32rxโ generates code for the M32R/X ๐ฆ-m32rโ generates code for the M32R. This is the default ๐-mmodel=smallโ assumes all objects live in the lower 16MB of memory (so their addresses can be loaded with the"ld24"instruction) and that all subroutines are reachable with the"bl"instruction. This is the default โจ
The addressability of a particular object can be set with the "model" attribute ๐
-mmodel=mediumโ assumes objects can be anywhere in the 32-bit address space (the compiler generates"seth/add3"instructions to load their addresses) and that all subroutines are reachable with the"bl"instruction ๐ธ-mmodel=largeโ assumes objects can be anywhere in the 32-bit address space (the compiler generates"seth/add3"instructions to load their addresses) and that subroutines may not be reachable with the"bl"instruction. The compiler generates the much slower"seth/add3/jl"instruction sequence instead ๐-msdata=noneโ disables the small data area ๐ซถ Variables go into one of".data",".bss", or".rodata"(unless the"section"attribute is specified). This is the default.
The small data area is made of the ".sdata" and ".sbss" sections. Objects can be explicitly put in the small data area with the "section" attribute using one of those 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 ofnumis 8. The-msdataoption has to be set tosdataorusefor this to do anything.
All modules should be compiled with the same -G num value ๐ซถ Mixing different values of num may or may not work. If it doesn't, the linker gives an error message, so incorrect code is not generated ๐
-mdebugโ makes the M32R-specific code in the compiler display some statistics that might help you debug programs ๐-malign-loopsโ aligns all loops to a 32-byte boundary ๐-mno-align-loopsโ doesn't enforce 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 used 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 isn't available ๐ธ-mno-flush-funcโ indicates there's no OS function for flushing the cache ๐
โจ M680x0 Options โจ
these are the -m options for M680x0 and ColdFire processors ๐ง The default settings depend on which architecture was picked when the compiler was configured, so the defaults for the most common choices are listed below ๐
-march=archโ generates code for a specific M680x0 or ColdFire instruction set architecture ๐ For M680x0, the valid values ofarchare68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures are picked using Freescale's ISA classification, and the valid values areisaa,isaaplus,isabandisacโจ
GCC defines a macro "__mcfarch__" whenever it's generating code for a ColdFire target. The arch in that macro is one of the -march arguments above ๐ซถ
When -march and -mtune are used together, they select code that runs on a family of similar processors but is optimized for one particular microarchitecture ๐
-mcpu=cpuโ generates code for a specific M680x0 or ColdFire processor. The M680x0 CPUs are68000,68010,68020,68030,68040,68060,68302,68332andcpu32. ColdFire CPUs are in the table below, which also sorts them into families ๐
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
โ ๏ธ-mcpu=cpuoverrides-march=archifarchis compatible withcpu. Other combinations of-mcpuand-marchget rejected ๐ญ
GCC defines the macro "__mcf_cpu_cpu" when a ColdFire target CPU is selected. It also defines "__mcf_family_family", where the value of family comes from the table above ๐
-mtune=tuneโ tunes the code for a particular microarchitecture, within the limits set by-marchand-mcpu๐ฆ The M680x0 microarchitectures are68000,68010,68020,68030,68040,68060andcpu32. The ColdFire microarchitectures arecfv1,cfv2,cfv3,cfv4andcfv4e๐
You can also use -mtune=68020-40 for code that needs to run relatively well on 68020, 68030 and 68040 targets. -mtune=68020-60 is similar but includes 68060 targets too. These two options select the same tuning decisions as -m68020-40 and -m68020-60 respectively ๐ธ
GCC defines the macros "__mcarch" and "__mcarch__" when tuning for 680x0 architecture arch. It also defines "mcarch" unless -ansi or a non-GNU -std option is used. If GCC is tuning for a range of architectures, selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in the range ๐ง
GCC also defines the macro "__muarch__" when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments above ๐
-m68000/-mc68000โ generates output for a 68000. This is the default when the compiler is configured for 68000-based systems. It's equivalent to-march=68000๐
Use this for microcontrollers with a 68000 or EC000 core, including the 68008, 68302, 68306, 68307, 68322, 68328 and 68356 ๐ซถ
-m68010โ generates output for a 68010. This is the default when the compiler is configured for 68010-based systems. It's equivalent to-march=68010๐-m68020/-mc68020โ generates output for a 68020. This is the default when the compiler is configured for 68020-based systems. It's equivalent to-march=68020โจ-m68030โ generates output for a 68030. This is the default when the compiler is configured for 68030-based systems. It's equivalent to-march=68030๐-m68040โ generates output for a 68040. This is the default when the compiler is configured for 68040-based systems. It's equivalent to-march=68040๐ฅ
This option stops the use of 68881/68882 instructions that would have to be emulated in software on the 68040. Use it if your 68040 doesn't have code to emulate those instructions ๐
-m68060โ generates output for a 68060. This is the default when the compiler is configured for 68060-based systems. It's equivalent to-march=68060๐
This option stops the use of 68020 and 68881/68882 instructions that would have to be emulated in software on the 68060. Use it if your 68060 doesn't have code to emulate those instructions ๐
-mcpu32โ generates output for a CPU32. This is the default when the compiler is configured for CPU32-based systems. It's equivalent to-march=cpu32๐ง
Use this 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. This option is now deprecated in favor of the equivalent-mcpu=5206eโ ๏ธ
okay bestie, the M680x0 options are still going strong ๐
-m528xโ generates output for a member of the ColdFire 528X family ๐ธ It's deprecated now, so just use the equivalent-mcpu=528xinstead ๐ซถ-m5307โ generates output for a ColdFire 5307 CPU ๐ฆ Also deprecated, so-mcpu=5307is the move ๐-m5407โ generates output for a ColdFire 5407 CPU โจ Deprecated too, so go with-mcpu=5407๐-mcfv4eโ for a ColdFire V4e family CPU, think 547x/548x ๐ฅ This one includes hardware floating-point instructions. It's the same as-mcpu=547x, and it's deprecated in favor of that option ๐-m68020-40โ generates output for a 68040, but without 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, which are emulated on the 68040. It's equivalent to-march=68020 -mtune=68020-40๐-m68020-60โ same energy, but for a 68060 ๐ No new instructions, and it still runs relatively efficiently on a 68020/68881, a 68030, or a 68040. The generated code does use the 68881 instructions, which are emulated on the 68060. It's equivalent to-march=68020 -mtune=68020-60โจ-mhard-float,-m68881โ turns on floating-point instructions ๐ This is the default for 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โ no floating-point instructions, just library calls instead ๐ซ This is the default for 68000, 68010, and 68832 targets. It's also the default for ColdFire devices with no FPU.-mdiv,-mno-divโ generates (or doesn't generate) the ColdFire hardware divide and remainder instructions โ If-marchis used without-mcpu, the default is "on" for ColdFire architectures and "off" for M680x0 architectures. Otherwise, the default is taken from the target CPU, either the default CPU or whichever one-mcpupicks. For example, it's "off" for-mcpu=5206and "on" for-mcpu=5206e. GCC defines the macro"__mcfhwdiv__"when this option is enabled.-mshortโ makes typeint16 bits wide, just likeshort int๐ Parameters passed on the stack also get aligned to a 16-bit boundary, even on targets whose API mandates promotion to 32-bit.-mno-shortโ don't makeint16 bits wide. This is the default ๐-mnobitfield,-mno-bitfieldโ no bit-field instructions ๐ซ The-m68000,-mcpu32and-m5200options imply-mnobitfield.-mbitfieldโ yes to bit-field instructions โ The-m68020option implies-mbitfield. This is the default if you use a configuration designed for a 68020.-mrtdโ uses a different function-calling convention ๐ Functions that take a fixed number of arguments return with the"rtd"instruction, which pops their arguments while it returns. That saves one instruction in the caller, since there's no need to pop the arguments there. This calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler.
Warning, bestie: you must provide function prototypes for all functions that take variable numbers of arguments (including "printf"), or incorrect code gets generated for calls to those functions. Seriously incorrect code also results if you call a function with too many arguments. Normally, extra arguments are harmlessly ignored, but not here ๐
The "rtd" instruction is supported by the 68010, 68020, 68030, 68040, 68060 and CPU32 processors, but not by the 68000 or 5200. The default is -mno-rtd.
-malign-int,-mno-align-intโ controls whether GCC aligns"int","long","long long","float","double", and"long double"variables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐ Aligning on 32-bit boundaries 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. Be careful with that one ๐
Use the pc-relative addressing mode of the 68000 directly, instead of using a global offset table. At present, this option implies -fpic, allowing at most a 16-bit offset for pc-relative addressing. -fPIC is not presently supported with -mpcrel, though this could be supported for 68020 and higher processors.
-mno-strict-align,-mstrict-alignโ-mno-strict-aligndoes not assume, and-mstrict-aligndoes assume, that unaligned memory references are handled by the system ๐คท-msep-dataโ generates code that lets the data segment live in a different area of memory from the text segment ๐ง This allows execute-in-place in an environment without virtual memory management. It implies-fPIC.-mno-sep-dataโ generates code that assumes the data segment follows the text segment. This is the default.-mid-shared-libraryโ generates code that supports shared libraries via the library ID method ๐ This allows execute-in-place and shared libraries in an environment without virtual memory management. It implies-fPIC.-mno-id-shared-libraryโ generates code that doesn't assume ID-based shared libraries are being used. This is the default.-mshared-library-id=nโ specifies the identification number of the ID-based shared library being compiled ๐ข Specifying a value of0generates more compact code. Specifying other values forces the allocation of that number to the current library, but it's no more space- or time-efficient than omitting this option.-mxgot,-mno-xgotโ for ColdFire position-independent code, generates code that works if the GOT has more than 8192 entries ๐ธ This code is larger and slower than code generated without this option. On M680x0 processors this option isn't needed, since-fPICdoes the job.
GCC normally uses a single instruction to load values from the GOT. That's relatively efficient, but it only works if the GOT is smaller than about 64k. Anything larger causes the linker to report an error such as:
relocation truncated to fit: R_68K_GOT16O foobar
If this happens, recompile your code with -mxgot. It should then work with very large GOTs. However, code generated with -mxgot is less efficient, since it takes 4 instructions to fetch the value of a global symbol.
Note that some linkers, including newer versions of the GNU linker, can create multiple GOTs and sort GOT entries. If you have such a linker, 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 to use 16-bit offsets.
๐ฆ MCore Options ๐ฆ
These are the -m options defined for the Motorola M*Core processors ๐
-mhardlit,-mno-hardlitโ inlines constants into the code stream if it can be done in two instructions or less ๐ช-mdiv,-mno-divโ uses the divide instruction. (Enabled by default). โ-mrelax-immediate,-mno-relax-immediateโ allows arbitrary-sized immediates in bit operations ๐ฟ-mwide-bitfields,-mno-wide-bitfieldsโ always treats bit-fields as"int"-sized ๐-m4byte-functions,-mno-4byte-functionsโ forces all functions to be aligned to a 4-byte boundary ๐-mcallgraph-data,-mno-callgraph-dataโ emits callgraph information ๐ธ๏ธ-mslow-bytes,-mno-slow-bytesโ prefers word access when reading byte quantities ๐-mlittle-endian,-mbig-endianโ generates code for a little-endian target ๐-m210,-m340โ generates code for the 210 processor ๐ง-mno-lsimโ assumes runtime support has been provided, so it omits the simulator library (libsim.a) from the linker command line ๐-mstack-increment=sizeโ sets the maximum amount for a single stack increment operation ๐ Large values can speed up programs that contain functions needing a large amount of stack space, but they can also trigger a segmentation fault if the stack is extended too much. The default value is0x1000.
๐ MeP Options ๐
-mabsdiffโ enables the"abs"instruction, which is the absolute difference between two registers ๐งฎ-mall-optsโ enables all the optional instructions---average, multiply, divide, bit operations, leading zero, absolute difference, min/max, clip, and saturation โจ-maverageโ enables the"ave"instruction, which computes the average of two registers ๐-mbased=nโ variables of sizenbytes or smaller get placed in the".based"section by default ๐ฆ Based variables use the$tpregister as a base register, and there's a 128-byte limit to the".based"section.-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 is placed in.namemay betiny,near, orfar๐-mclipโ enables the"clip"instruction ๐ฆ Note that-mclipis not useful unless you also provide-mminmax.-mconfig=nameโ selects 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 variety of coprocessors, optional instructions, and peripherals. The "MeP-Integrator" tool, which is not part of GCC, provides these configurations through this option. Using this option is the same as using all the corresponding command-line options. The default configuration isdefault.-mcopโ enables the coprocessor instructions. By default, this is a 32-bit coprocessor ๐ค Note that the coprocessor is normally enabled via the-mconfig=option.-mcop32โ enables the 32-bit coprocessor's instructions ๐ค-mcop64โ enables the 64-bit coprocessor's instructions ๐
๐ Machine-dependent options continued ๐
-mivc2โ okay so this turns on IVC2 scheduling ๐ฅ. IVC2 is a 64-bit VLIW coprocessor, which is giving very powerful ๐ช-mdcโ constant variables get placed in the".near"section ๐ฆ-mdivโ unlocks the"div"and"divu"instructions โ-mebโ big-endian code, bestie ๐ธ-melโ little-endian code, bestie ๐ฆ-mio-volatileโ tells the compiler that any variable with the"io"attribute should be treated as volatile. Main character energy for hardware registers ๐-mlโ variables go to the".far"section by default ๐-mleadzโ enables the"leadz"(leading zero) instruction ๐-mmโ variables go 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 that-mall-optsturns on. Not the vibe if you wanted them ๐-mrepeatโ enables the"repeat"and"erepeat"instructions, which are used for low-overhead looping ๐-msโ every variable defaults to the".tiny"section ๐ง. Heads up, there's a 65536-byte limit on this section ๐ญ. Accesses to these variables use the%gpbase register.-msaturโ enables the saturation instructions. Ngl, the compiler doesn't generate these on its own right now ๐. This flag is only here for compatibility with other tools, like"as".-msdramโ links the SDRAM-based runtime instead of the default ROM-based one ๐ง-msimโ links the simulator run-time libraries ๐ฎ-msimnovecโ links the simulator runtime libraries, but skips the built-in support for reset and exception vectors and tables ๐-mtfโ all functions default to the".far"section. Without this flag, functions default to".near"๐-mtiny=nโ variables that arenbytes or smaller get allocated to the".tiny"section ๐ท. They use the$gpbase register. The default for this option is4, but the".tiny"section still has that 65536-byte limit, so don't forget ๐ญ.
๐ MicroBlaze Options ๐
-msoft-floatโ software emulation for floating point. This is the default ๐ซถ-mhard-floatโ uses hardware floating-point instructions โก-mmemcpyโ does not optimize block moves, and usesmemcpyinstead ๐-mno-clearbssโ deprecated ๐ฅ. Use-fno-zero-initialized-in-bssinstead.-mcpu=cpu-typeโ uses features of, and schedules code for, the given CPU โจ. Supported values follow 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โ software multiply emulation. This is the default ๐ข-mxl-soft-divโ software emulation for divides. Also the default ๐ข-mxl-barrel-shiftโ uses the hardware barrel shifter ๐ข๏ธ-mxl-pattern-compareโ uses pattern compare instructions ๐-msmall-dividesโ uses a table lookup optimization for small signed integer divisions ๐-mxl-stack-checkโ deprecated ๐ฅ. Use-fstack-checkinstead.-mxl-gp-optโ uses GP-relative".sdata"/".sbss"sections ๐๏ธ-mxl-multiply-highโ uses multiply high instructions for the high part of a 32x32 multiply ๐ข-mxl-float-convertโ uses hardware floating-point conversion instructions ๐-mxl-float-sqrtโ uses the hardware floating-point square root instruction ๐ฑ-mbig-endianโ generates code for a big-endian target ๐ธ-mlittle-endianโ generates code for a little-endian target ๐ฆ-mxl-reorderโ uses reorder instructions (swap and byte reversed load/store) ๐-mxl-mode-app-modelโ selects the application modelapp-model. The valid models are:executableโ normal executable, and the default ๐ . Uses the startup codecrt0.o.xmdstubโ for use with the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent called xmdstub ๐. This one uses the startup filecrt1.oand sets the start address of the program to0x800.bootstrapโ for applications that get loaded using a bootloader ๐ฅพ. This model uses the startup filecrt2.o, which does not contain a processor reset vector handler. It's suitable for handing control back to the bootloader on a processor reset, instead of the application.novectorsโ for applications that don't need any of the MicroBlaze vectors ๐ซ. This can be handy for apps running inside a monitoring application. This model usescrt3.oas its startup file.
Heads up: -xl-mode-app-model is a deprecated alias for -mxl-mode-app-model ๐ฅ.
-mpic-data-is-text-relativeโ assumes the displacement between the text and data segments is fixed at static link time ๐. This lets data get referenced by offset from the start of the text address instead of through the GOT, since PC-relative addressing isn't supported.
๐ MIPS Options ๐
-EBโ big-endian code ๐ธ-ELโ little-endian code ๐ฆ. This is the default formips*el-*-*configurations.-march=archโ generates code that runs onarch๐. This can be the name of a generic MIPS ISA, or the name of a particular processor. The ISA names aremips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5andmips64r6. The processor names are4kc,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-abipicks the most compatible architecture for the selected ABI. That meansmips1for 32-bit ABIs andmips3for 64-bit ABIs.
The native Linux/GNU toolchain also supports the value native, which picks the best architecture option for the host processor. -march=native has no effect if GCC doesn't recognize the processor ๐คท.
In processor names, a final 000 can be abbreviated as k (for example, -march=r2k) โ๏ธ. Prefixes are optional, and vr may be written r.
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core. Names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core. Names of the form nf3_2 refer to processors with FPUs clocked at a 3:2 ratio with respect to the core. For compatibility reasons, nf is accepted as a synonym for nf2_1, while nx and bfx are accepted as synonyms for nf1_1.
GCC defines two macros based on the value of this option ๐งฉ. The first is "_MIPS_ARCH", which gives the name of the target architecture as a string. The second has the form "_MIPS_ARCH_foo", where foo is the capitalized value of "_MIPS_ARCH". For example, -march=r2000 sets "_MIPS_ARCH" to "r2000" and defines the macro "_MIPS_ARCH_R2000".
Note that the "_MIPS_ARCH" macro uses the processor names given above. In other words, it has the full prefix and doesn't abbreviate 000 as k. In the case of from-abi, the macro names the resolved architecture (either "mips1" or "mips3"). It names the default architecture when no -march option is given.
-mtune=archโ 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 isn't used, GCC optimizes for the processor specified by -march. By using -march and -mtune together, you can generate code that runs on a whole family of processors, but optimize it for one particular member of that family ๐.
-mtune defines the macros "_MIPS_TUNE" and "_MIPS_TUNE_foo", which work the same way as the -march ones described above ๐งฉ.
-mips1โ equivalent to-march=mips1โจ-mips2โ equivalent to-march=mips2โจ-mips3โ equivalent to-march=mips3โจ-mips4โ equivalent to-march=mips4โจ-mips32โ equivalent to-march=mips32โจ-mips32r3โ equivalent to-march=mips32r3โจ-mips32r5โ equivalent to-march=mips32r5โจ-mips32r6โ equivalent to-march=mips32r6โจ-mips64โ equivalent to-march=mips64โจ-mips64r2โ equivalent to-march=mips64r2โจ-mips64r3โ equivalent to-march=mips64r3โจ-mips64r5โ equivalent to-march=mips64r5โจ-mips64r6โ equivalent to-march=mips64r6โจ-mips16,-mno-mips16โ generates (or doesn't generate) MIPS16 code ๐ง. If GCC is targeting a MIPS32 or MIPS64 architecture, it makes use of the MIPS16e ASE.
MIPS16 code generation can also be controlled on a per-function basis using the "mips16" and "nomips16" attributes ๐๏ธ.
-mflip-mips16โ generates MIPS16 code on alternating functions ๐. This option is provided for regression testing of mixed MIPS16/non-MIPS16 code generation. It is not intended for ordinary use when compiling user code, so please don't go using it in your everyday builds ๐ .-minterlink-compressed,-mno-interlink-compressedโ requires (or doesn't require) that code using the standard (uncompressed) MIPS ISA be link-compatible with MIPS16 and microMIPS code, and vice versa ๐.
For example, code using the standard ISA encoding can't jump directly to MIPS16 or microMIPS code. It has to either use a call or an indirect jump. So -minterlink-compressed disables direct jumps unless GCC knows the target of the jump isn't compressed.
-minterlink-mips16,-mno-interlink-mips16โ aliases of-minterlink-compressedand-mno-interlink-compressed๐ฅฐ. These options predate the microMIPS ASE and are kept around for backwards compatibility.-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generates code for the given ABI ๐.
The EABI has a 32-bit and a 64-bit variant. GCC normally generates 64-bit code when you pick a 64-bit architecture, but you can use -mgp32 to get 32-bit code instead ๐.
For info about the O64 ABI, check out <https://gcc.gnu.org/projects/mipso64-abi.html> ๐.
Okay so GCC has this fun little variant of the o32 ABI where the floating-point registers are 64 bits wide instead of 32 ๐ฆ You can pick this combo with -mabi=32 -mfp64. It's lowkey picky, though: it relies on the mthc1 and mfhc1 instructions, so it's only supported on MIPS32R2, MIPS32R3 and MIPS32R5 processors ๐
The register assignments for arguments and return values stay exactly the same, but each scalar value gets passed in one 64-bit register instead of a pair of 32-bit ones. Scalar floating-point values come back in $f0 alone, not a $f0/$f1 pair ๐ The call-saved set doesn't change either, so the even-numbered double-precision registers are still the ones that get saved โจ
Two more o32 variants exist to help you transition from 32-bit to 64-bit registers: FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg). ๐ธ
FPXX is giving "works either way" energy. It mandates that all code must execute correctly whether it's running with 32-bit or 64-bit registers. Code can be interlinked with FP32 or FP64, but not both ๐ซถ
FP64A is FP64's chill cousin, except it forbids the use of 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 switching FPU modes. Iconic ๐
-mabicalls,-mno-abicallsโ Generate (or skip generating) code that's suitable for SVR4-style dynamic objects.-mabicallsis the default on SVR4-based systems ๐-mshared,-mno-sharedโ Generate (or skip generating) code that's fully position-independent, so it can be linked into shared libraries. This option only affects-mabicalls. โจ
All -mabicalls code has traditionally been position-independent, no matter what options like -fPIC and -fpic say. But as an extension, the GNU toolchain lets executables use absolute accesses for locally-binding symbols. It can also use shorter GP initialization sequences and generate direct calls to locally-defined functions. That mode gets selected by -mno-shared ๐ง
-mno-shared depends on binutils 2.16 or higher, and the objects it makes can only be linked by the GNU linker. Still, it doesn't change the ABI of the final executable. It only affects the ABI of relocatable objects. Using -mno-shared generally makes executables both smaller and quicker ๐ -mshared is the default.
-mplt,-mno-pltโ Assume (or don't assume) that the static and dynamic linkers support PLTs and copy relocations. This option only affects-mno-shared -mabicalls. For the n64 ABI, it does nothing without-msym32๐
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt.
-mxgot,-mno-xgotโ Lift (or don't lift) the usual restrictions on the size of the global offset table (GOT) ๐
GCC normally uses a single instruction to load values from the GOT. It's relatively efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker throw 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 a bit less efficient, since it takes three instructions to fetch the value of a global symbol ๐ญ
Some linkers can create multiple GOTs. If you've got one of those, you should only need -mxgot when a single object file accesses more than 64k's worth of GOT entries. Very few linkers do ๐
These options have no effect unless GCC is generating position-independent code.
-mgp32โ Assume general-purpose registers are 32 bits wide. ๐-mgp64โ Assume general-purpose registers are 64 bits wide. ๐-mfp32โ Assume floating-point registers are 32 bits wide. ๐ฆ-mfp64โ Assume floating-point registers are 64 bits wide. ๐ฆ-mfpxxโ Don't assume anything about the width of floating-point registers. ๐ซง-mhard-floatโ Use the floating-point coprocessor instructions. ๐ฅ-msoft-floatโ Don't use the floating-point coprocessor instructions. Do the floating-point math with library calls instead. ๐งธ-mno-floatโ Same vibe as-msoft-float, but it also swears the program doesn't do any floating-point operations at all ๐ โโ๏ธ
-mno-float is only supported by some bare-metal MIPS configurations, where it might pick a special set of libraries that have zero floating-point support. That includes stuff like the floating-point printf formats. If code compiled with -mno-float accidentally has floating-point operations in it, it'll probably fail at link time or run time ๐ฑ
-msingle-floatโ Assume the floating-point coprocessor only supports single-precision operations. ๐ธ-mdouble-floatโ Assume the floating-point coprocessor supports double-precision operations. This is the default ๐-modd-spreg,-mno-odd-spregโ Enable (or disable) the use of odd-numbered single-precision floating-point registers for the o32 ABI. Enabled by default for processors that are known to support these registers. When using the o32 FPXX ABI,-mno-odd-spregis set by default ๐-mabs=2008,-mabs=legacyโ These control how special not-a-number (NaN) IEEE 754 floating-point data gets treated by theabs.fmtandneg.fmtmachine instructions ๐ง
By default, or when -mabs=legacy is used, the legacy treatment is selected. In this mode, those instructions count as arithmetic, so they get avoided wherever correct operation matters and the input might be a NaN. A longer sequence that manually manipulates the sign bit of the floating-point datum is used instead, unless -ffinite-math-only has also been specified ๐
-mabs=2008 selects the IEEE 754-2008 treatment. Here those instructions count as non-arithmetic, so they work correctly in every case, including when the input operand is a NaN. That means they're always used for the respective operations ๐
-mnan=2008,-mnan=legacyโ These control the encoding of special not-a-number (NaN) IEEE 754 floating-point data ๐
-mnan=legacy selects the legacy encoding. Quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, and signaling NaNs (sNaNs) are marked by that first bit being 1.
-mnan=2008 selects the IEEE 754-2008 encoding. Now 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 has been configured with --with-nan=2008 ๐
-mllsc,-mno-llscโ Use (or don't use) thell,scandsyncinstructions to implement the atomic memory built-in functions. When neither option is specified, GCC uses those instructions if the target architecture supports them โก
-mllsc is handy if the runtime environment can emulate the instructions, and -mno-llsc can be useful when you're compiling for nonstandard ISAs. You can make either one the default by configuring GCC with --with-llsc or --without-llsc, respectively. --with-llsc is the default for some configurations, so check the installation documentation for the deets ๐
-mdsp,-mno-dspโ Use (or don't use) revision 1 of the MIPS DSP ASE. This defines the preprocessor macro__mips_dsp, and it also sets__mips_dsp_revto 1 ๐-mdspr2,-mno-dspr2โ Use (or don't use) revision 2 of the MIPS DSP ASE. This defines the preprocessor macros__mips_dspand__mips_dspr2, and it sets__mips_dsp_revto 2 ๐-msmartmips,-mno-smartmipsโ Use (or don't use) the MIPS SmartMIPS ASE ๐ง-mpaired-single,-mno-paired-singleโ Use (or don't use) paired-single floating-point instructions. This option requires hardware floating-point support to be enabled ๐ซถ-mdmx,-mno-mdmxโ Use (or don't use) MIPS Digital Media Extension instructions. This only works when generating 64-bit code, and it needs hardware floating-point support enabled ๐ฌ-mips3d,-mno-mips3dโ Use (or don't use) the MIPS-3D ASE. The option-mips3dimplies-mpaired-single๐-mmicromips,-mno-micromipsโ Generate (or don't generate) microMIPS code ๐ฆ
microMIPS code generation can also be controlled per function, using the "micromips" and "nomicromips" attributes ๐
-mmt,-mno-mtโ Use (or don't use) MT Multithreading instructions ๐งต-mmcu,-mno-mcuโ Use (or don't use) the MIPS MCU ASE instructions ๐ง-meva,-mno-evaโ Use (or don't use) the MIPS Enhanced Virtual Addressing instructions ๐-mvirt,-mno-virtโ Use (or don't use) the MIPS Virtualization (VZ) instructions ๐ฅ๏ธ-mxpa,-mno-xpaโ Use (or don't use) the MIPS eXtended Physical Address (XPA) instructions ๐-mcrc,-mno-crcโ Use (or don't use) the MIPS Cyclic Redundancy Check (CRC) instructions ๐-mginv,-mno-ginvโ Use (or don't use) the MIPS Global INValidate (GINV) instructions ๐งน-mloongson-mmi,-mno-loongson-mmiโ Use (or don't use) the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐ถ-mloongson-ext,-mno-loongson-extโ Use (or don't use) the MIPS Loongson EXTensions (EXT) instructions ๐งฉ-mloongson-ext2,-mno-loongson-ext2โ Use (or don't use) the MIPS Loongson EXTensions r2 (EXT2) instructions ๐งฉ-mlong64โ Forcelongtypes to be 64 bits wide. Check out-mlong32for the lowdown on the default and how the pointer size gets decided ๐-mlong32โ Forcelong,int, and pointer types to be 32 bits wide ๐
The default size of ints, longs and pointers depends on the ABI. Every supported ABI uses 32-bit ints. The n64 ABI uses 64-bit longs, and so does the 64-bit EABI, but the others use 32-bit longs. Pointers are the same size as longs, or the same size as integer registers, whichever is smaller ๐
-msym32,-mno-sym32โ okay so-msym32tells GCC to assume every symbol has a 32-bit value, no matter which ABI you picked.-mno-sym32says nah, don't assume that ๐ It's a total power combo with-mabi=64and-mno-abicallsbecause GCC can then write shorter, faster references to symbolic addresses โจ-G numโ puts externally-visible data into a small data section ๐ as long as that data is no bigger thannumbytes. GCC can then access the data more efficiently (see-mgpoptfor the deets). The default-Gvalue depends on your configuration ๐-mlocal-sdata,-mno-local-sdataโ extends the-Gbehaviour to local data too, like static variables in C.-mlocal-sdatais the default for all configurations. If the linker starts complaining that an app is using too much small data, try rebuilding the less performance-critical parts with-mno-local-sdata. You could also build big libraries with-mno-local-sdataso they leave more room for the main program ๐ซถ-mextern-sdata,-mno-extern-sdataโ assumes (or doesn't assume) that externally-defined data lives in a small data section if its size is within the-Glimit.-mextern-sdatais the default for all configurations. Heads up bestie ๐ญ if you compile a moduleModwith-mextern-sdata -G num -mgpopt, andModreferences a variableVarthat is no bigger thannumbytes, you must make sureVaris placed in a small data section. IfVaris defined by another module, you must either compile that module with a high-enough-Gsetting or attach a"section"attribute toVar's definition. IfVaris common, you must link the application with a high-enough-Gsetting. The easiest way to keep all of this happy is to compile and link every module with the same-Goption. However, if you're building a library that supports several different small data limits, compile it with the highest supported-Gsetting and add-mno-extern-sdataso the library stops making assumptions about externally-defined data ๐ง-mgpopt,-mno-gpoptโ uses (or doesn't use) GP-relative accesses for symbols that are known to be in a small data section; see-G,-mlocal-sdataand-mextern-sdata.-mgpoptis the default for all configurations.-mno-gpoptis useful when the$gpregister might not hold the value of"_gp". For example, if the code is part of a library that might be used in a boot monitor, programs that call boot monitor routines pass an unknown value in$gp. (In those situations, the boot monitor itself is usually compiled with-G0.)-mno-gpoptimplies-mno-local-sdataand-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, otherwise to data. It gives slightly slower code than the default, but it cuts down on the RAM needed while running, so it may be preferred for some embedded systems ๐-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ puts uninitialized"const"variables in the read-only data section. This only means something when paired with-membedded-data๐ธ-mcode-readable=settingโ controls whether GCC may generate code that reads from executable sections. There are three possible settings, bestie:-mcode-readable=yesโ instructions can freely access executable sections. This is the default setting โจ-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must not. This is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It's also useful on processors that can be configured with a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM ๐ฆ-mcode-readable=noโ instructions must not access executable sections. This can be useful on targets configured with a dual instruction/data SRAM interface that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM ๐
-msplit-addresses,-mno-split-addressesโ enables (disables) use of the%hi()and%lo()assembler relocation operators. This one has been superseded by-mexplicit-relocs, but it's kept around for backwards compatibility ๐ฐ๏ธ-mexplicit-relocs,-mno-explicit-relocsโ uses (doesn'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โ traps (or doesn't trap) on integer division by zero. The default is-mcheck-zero-division๐ฅ-mdivide-traps,-mdivide-breaksโ MIPS systems check for division by zero by generating either a conditional trap or 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 this can be overridden at configure time with--with-divide=breaks. Divide-by-zero checks can be completely disabled using-mno-check-zero-division๐-mload-store-pairs,-mno-load-store-pairsโ enables (disables) an optimization that pairs consecutive load or store instructions to enable load/store bonding. It's enabled by default, but it only takes effect when the selected architecture is known to support bonding ๐งโโ๏ธ-munaligned-access,-mno-unaligned-accessโ enables (disables) direct unaligned access for MIPS Release 6. MIPSr6 requires load/store unaligned-access support, either by hardware or bytrap&emulate. So-mno-unaligned-accessmay be needed by kernel ๐ซ-mmemcpy,-mno-memcpyโ forces (doesn't force) the use of"memcpy"for non-trivial block moves. The default is-mno-memcpy, which lets GCC inline most constant-sized copies ๐-mlong-calls,-mno-long-callsโ-mlong-callsdisables use of the"jal"instruction, while-mno-long-callsdoesn't disable it. 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โ enables (disables) use of the"mad","madu"and"mul"instructions, as provided by the R4650 ISA ๐ข-mimadd,-mno-imaddโ enables (disables) use of the"madd"and"msub"integer instructions. The default is-mimaddon architectures that support"madd"and"msub", except for the 74k architecture, where it was found to generate slower code ๐-mfused-madd,-mno-fused-maddโ enables (disables) use of the floating-point multiply-accumulate instructions, when they're available. The default is-mfused-maddโจ
On the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product is calculated to infinite precision and is not subject to the FCSR Flush to Zero bit. This may be undesirable in some circumstances. On other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions.
-nocppโ tells the MIPS assembler to not run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐ โโ๏ธ-mfix-24k,-mno-fix-24kโ works around the 24K E48 (lost data on stores during refill) errata. The workarounds are implemented by the assembler rather than by GCC ๐ ๏ธ-mfix-r4000,-mno-fix-r4000โ works around certain R4000 CPU errata:- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
- A double-word or a variable shift may give an incorrect result if executed while an integer multiplication is in progress.
- An integer division may give an incorrect result if started in a delay slot of a taken branch or a jump.
-mfix-r4400,-mno-fix-r4400โ works around certain R4400 CPU errata:- A double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
-mfix-r10000,-mno-fix-r10000โ works around certain R10000 errata:"ll"/"sc"sequences may not behave atomically on revisions prior to 3.0. They may deadlock on revisions 2.6 and earlier.
This option can only be used if the target architecture supports branch-likely instructions. -mfix-r10000 is the default when -march=r10000 is used; -mno-fix-r10000 is the default otherwise ๐ฏ
-mfix-r5900,-mno-fix-r5900โ do not attempt to schedule the preceding instruction into the delay slot of a branch instruction placed at the end of a short loop of six instructions or fewer. Instead, always schedule anopinstruction there. 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โ okay so this one is a workaround for the VR4130 "mflo"/"mfhi" errata ๐ The fixing happens in the assembler, not GCC, but GCC avoidsmfloandmfhialtogether when the VR4130 "macc", "macchi", "dmacc" and "dmacchi" instructions are available instead ๐ฆ-mfix-sb1,-mno-fix-sb1โ this works around certain SB-1 CPU core errata โจ Right now it only patches the SB-1 revision 2 "F1" and "F2" floating-point errata ๐ฅ-mr10k-cache-barrier=settingโ this decides whether GCC inserts cache barriers to dodge the side effects of speculation on R10K processors ๐
Okay, so, like a lot of processors, the R10K tries to guess which way a conditional branch will go and speculatively runs instructions from the "taken" branch ๐ฎ If the guess was wrong, it aborts them later. The catch? On the R10K, even aborted instructions can still have side effects ๐
This mostly affects kernel stores and, depending on your system, kernel loads ๐ธ For example, a speculatively-executed store might pull the target memory into cache and mark that cache line as dirty, even if the store gets aborted later. If a DMA operation writes to the same memory before that "dirty" line is flushed, the cached data overwrites the DMA-ed data ๐ญ For the full story (including other potential problems), check the R10K processor manual.
One workaround is to insert cache barrier instructions before every memory access that might be speculatively executed and might have side effects even if aborted โจ -mr10k-cache-barrier=setting controls how GCC does this. It assumes that aborted accesses to any byte in the following regions don't have side effects:
- the memory occupied by the current function's stack frame;
- the memory occupied by an incoming stack argument;
- the memory occupied by an object with a link-time-constant address.
It's the kernel's job to make sure speculative accesses to these regions are actually safe ๐ซถ
If 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" be executed speculatively ๐ GCC follows this rule for functions it compiles itself, and it expects non-GCC functions (like hand-written assembly) to do the same ๐
The option comes in three flavours:
-mr10k-cache-barrier=load-storeโ inserts a cache barrier before a load or store that might be speculatively executed and might have side effects even if aborted ๐ง-mr10k-cache-barrier=storeโ inserts a cache barrier only before a store that might be speculatively executed and might have side effects even if 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 GCC calls to flush the I and D caches, or tells it to call no such 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_func" or "__cpu_flush" โจmbranch-cost=numโ sets the cost of branches to roughly num "simple" instructions ๐ Heads up, this is only a heuristic, so it's not guaranteed to give consistent results across releases ๐ A cost of zero just lands you on the default, which is based on-mtune-mbranch-likely,-mno-branch-likelyโ enables or disables Branch Likely instructions, no matter what the selected architecture defaults to ๐ฅ By default they may be generated if the selected architecture supports them ๐ธ The exception is MIPS32 and MIPS64, plus processors implementing those architectures. For those, Branch Likely instructions aren't generated by default, because those architectures specifically deprecate their use ๐ โโ๏ธ-mcompact-branches=never,-mcompact-branches=optimal,-mcompact-branches=alwaysโ these control which form of branch gets generated ๐ฆ The default is-mcompact-branches=optimal-mcompact-branches=neverโ makes sure compact branch instructions are never generated ๐ซ-mcompact-branches=alwaysโ makes sure a compact branch instruction gets generated if one is available. If it isn't, a delay slot form of the branch is used instead ๐-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 is picked if one is available ๐ง
This option is supported from MIPS Release 6 onwards ๐
-mfp-exceptions,-mno-fp-exceptionsโ decides whether FP exceptions are enabled ๐ This affects how FP instructions get scheduled on some processors. The default is that FP exceptions are enabled โจ
For instance, on the SB-1, if FP exceptions are disabled and we're emitting 64-bit code, we can use both FP pipes ๐ฅ Otherwise, we can only use one FP pipe ๐ญ
-mvr4130-align,-mno-vr4130-alignโ the VR4130 pipeline is two-way superscalar, but it can only issue two instructions together if the first one is 8-byte aligned ๐ธ When this is enabled, GCC aligns pairs of instructions it thinks should run in parallel ๐ง
This only has an effect when you're optimizing for the VR4130 ๐ฆ It usually makes code faster, but the trade-off is that it makes the code bigger. It's enabled by default at optimization level -O3 ๐
-msynci,-mno-synciโ enables (or disables) generation of "synci" instructions on architectures that support them โจ If enabled, the "synci" instructions get generated when "__builtin___clear_cache" is compiled ๐ฎ
This option defaults to -mno-synci, but you can override the default by configuring GCC with --with-synci ๐
For single processor systems, it's generally safe to use "synci" ๐
Careful, bestie! On many multi-core (SMP) systems, synci doesn't invalidate the instruction caches on all cores, and it may lead to undefined behavior ๐
-mrelax-pic-calls,-mno-relax-pic-callsโ tries to turn PIC calls that normally get dispatched via register$25into direct calls ๐ This is only possible if the linker can resolve the destination at link time and the destination is within range for a direct call ๐
-mrelax-pic-calls is the default if GCC was configured to use an assembler and a linker that support the ".reloc" assembly directive, and -mexplicit-relocs is in effect ๐ซถ With -mno-explicit-relocs, this optimization can be done by the assembler and the linker alone, without any help from the compiler ๐ง
-mmcount-ra-address,-mno-mcount-ra-addressโ emits (or doesn't emit) code that lets "_mcount" modify the calling function's return address ๐ฆ When enabled, this extends the usual "_mcount" interface with a new ra-address parameter. It has type "intptr_t *" and gets passed in register$12๐ "_mcount" can then change the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in "
*ra-address", if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address ๐ฅ
-mframe-header-opt,-mno-frame-header-optโ enables (or disables) frame header optimization in the o32 ABI ๐ธ With the o32 ABI, calling functions allocate 16 bytes on the stack for the called function to write out register arguments ๐ When this is enabled, the optimization skips allocating the frame header if it can be determined that it's unused โจ
This optimization is off by default at all optimization levels ๐ญ
-mlxc1-sxc1,-mno-lxc1-sxc1โ when applicable, enables (or disables) the generation of "lwxc1", "swxc1", "ldxc1", "sdxc1" instructions ๐ง Enabled by default ๐-mmadd4,-mno-madd4โ when applicable, enables (or disables) the generation of 4-operand "madd.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 the "rE" epsilon register ๐ฎ-mabi=mmixware,-mabi=gnuโ generates code that passes function parameters and return values that (in the called function) are seen as registers$0and up ๐ฆ That's different from the GNU ABI, which uses global registers$231and up โจ-mzero-extend,-mno-zero-extendโ when reading data from memory in sizes shorter than 64 bits, uses (or doesn't use) zero-extending load instructions by default, instead of sign-extending ones ๐ธ-mknuthdiv,-mno-knuthdivโ makes the result of a division 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 the "PREFIX" assembly directive ๐ง-melfโ generates an executable in the ELF format, rather than the default mmo format used by the mmix simulator ๐-mbranch-predict,-mno-branch-predictโ uses (or doesn't use) the probable-branch instructions, when static branch prediction indicates a probable branch ๐ฅ-mbase-addresses,-mno-base-addressesโ okay so this one decides whether the compiler uses base addresses at all ๐ธ Turn it on and it generates code that does, turn it off and it doesn't. Using a base address automatically generates a request (the assembler and linker handle it ๐ซถ) for a constant to be set up in a global register. That register then gets used for one or more base address requests within the range0to255from the value it holds. This usually gives you short and fast code โจ, but the number of different data items you can address is limited, so a program with lots of static data may need-mno-base-addresses๐-msingle-exit,-mno-single-exitโ forces (or doesn't force) the 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 that avoids bugs in the multiply instructions for the MN10300 processors. This is the default ๐ฅ-mno-mult-bugโ does not generate code to avoid those multiply instruction bugs on the MN10300 processors ๐-mam33โ generates code using features specific to the AM33 processor ๐-mno-am33โ doesn't generate code using AM33-specific features. This is the default ๐-mam33-2โ generates code using features specific to the AM33/2.0 processor โจ-mam34โ generates code using features specific to the AM34 processor ๐ง-mtune=cpu-typeโ uses the timing characteristics of the CPU type you name when scheduling instructions ๐ This doesn't change the targeted processor type. The CPU type must be one ofmn10300,am33,am33-2oram34.-mreturn-pointer-on-d0โ when generating a function that returns a pointer, the pointer gets returned in both"a0"and"d0"๐ Otherwise it's only returned in"a0", and trying to call those functions without a prototype throws errors ๐ญ This option is on by default, so use-mno-return-pointer-on-d0to turn it off.-mno-crt0โ don't link in the C run-time initialization object file ๐ซถ-mrelaxโ tells the linker to run a relaxation optimization pass that shortens branches, calls and absolute memory addresses ๐ฆ This option only has an effect when used on the command line for the final link step.
Heads up: this option makes symbolic debugging impossible ๐ญ
-mliwโ lets the compiler generate Long Instruction Word instructions if the target is the AM33 or later. This is the default โจ It defines the preprocessor macro__LIW__.-mno-liwโ stops the compiler from generating Long Instruction Word instructions. It defines the preprocessor macro__NO_LIW__.-msetlbโ lets the compiler generate the SETLB and Lcc instructions if the target is the AM33 or later. This is the default ๐ธ It defines the preprocessor macro__SETLB__.-mno-setlbโ stops the compiler from generating SETLB or Lcc instructions. It defines the preprocessor macro__NO_SETLB__.
โจ Moxie Options โจ
-mebโ generates big-endian code ๐ This is the default formoxie-*-*configurations.-melโ generates little-endian code ๐-mmul.xโ generatesmul.xandumul.xinstructions ๐ This is the default formoxiebox-*-*configurations.-mno-crt0โ don't link in the C run-time initialization object file ๐ซถ
โจ MSP430 Options โจ
These options are defined for the MSP430 ๐
-masm-hexโ forces the assembly output to always use hex constants. Normally these are signed decimals, but this option is there for testsuite and/or aesthetic purposes ๐-mmcu=โ picks the MCU you're targeting ๐ It's used to create a C preprocessor symbol based on the MCU name, converted to upper case and pre- and post-fixed with__. That symbol is then used by themsp430.hheader file to select an MCU-specific supplementary header file โจ- It also sets the ISA to use. If the MCU name is one that's known to only support the 430 ISA, that's the one selected. Otherwise the 430X ISA is selected. The generic
msp430MCU name can also be used to select the 430 ISA, and the genericmsp430xMCU name selects the 430X ISA. - An MCU-specific linker script is added to the linker command line. The script's name is the MCU name with
.ldappended, 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. However, an external
devices.csvfile can be used to extend device support beyond those hard-coded ones ๐ - GCC searches for
devices.csvusing the following methods, in the given precedence order, where the first method takes precedence over the second, which takes precedence over the third:- Include path specified with
"-I"and"-L":devices.csvwill be searched for in each of the directories specified by include paths and linker library search paths. - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIR: define the value of the global environment variableMSP430_GCC_INCLUDE_DIRas the full path to the directory containingdevices.csv, and GCC will search that directory for it. Ifdevices.csvis found, this directory is also registered as an include path and linker library path. Header files and linker scripts in this directory can then be used without manually specifying"-I"and"-L"on the command line ๐ซถ - The
msp430-elf{,bare}/include/devicesdirectory: finally, GCC examinesmsp430-elf{,bare}/include/devicesfrom the toolchain root directory. This directory doesn't exist in a default installation, but if you've created it and copieddevices.csvthere, the MCU data will be read. Like above, this directory is also registered as an include path and linker library path.
- Include path specified with
- If none of the above search methods find
devices.csv, the hard-coded MCU data is used.
- It also sets the ISA to use. If the MCU name is one that's known to only support the 430 ISA, that's the one selected. Otherwise the 430X ISA is selected. The generic
-mwarn-mcu,-mno-warn-mcuโ enables or disables warnings about conflicts between the MCU name given by-mmcuand the ISA set by-mcpuand/or the hardware multiply support set by-mhwmult. It also toggles warnings about unrecognized MCU names. This option is on by default ๐-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 ๐ This overrides any scripts that would be selected by-mmcu=.-mlargeโ uses large-model addressing (20-bit pointers, 20-bit"size_t") ๐ธ-msmallโ uses small-model addressing (16-bit pointers, 16-bit"size_t") ๐ฆ-mrelaxโ gets passed to the assembler and linker, and lets the linker do certain optimizations that can't happen until the final link โญ-mhwmult=โ describes the type of hardware multiply the target supports ๐ฅ Accepted values:noneโ no hardware multiply16bitโ the original 16-bit-only multiply from early MCUs32bitโ the 16/32-bit multiply from later MCUsf5seriesโ the 16/32-bit multiply from F5-series MCUsautoโ tells GCC to deduce 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.autois the default setting โจ- Hardware multiplies are normally performed by calling a library routine, which saves space in the generated code ๐งธ When compiling at
-O3or 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, meaning no static initializers or constructors ๐งธ This is intended 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 sizeprintfandputslibrary functions ๐
Careful: these tiny implementations are not reentrant, so use them with caution in multi-threaded applications ๐ฌ
- Support for streams has been removed, and the string to be printed is always sent to stdout via the
writesyscall. The string isn't buffered before it's sent towrite. - This option requires Newlib Nano IO, so GCC must be configured with
--enable-newlib-nano-formatted-io.
-mmax-inline-shift=โ takes an integer between 0 and 64 inclusive, and sets the maximum number of inline shift instructions that should be emitted to perform a shift by a constant amount ๐ When this value needs to be exceeded, an mspabi helper function is used instead. The default value is 4.- This only affects cases where a shift by multiple positions can't be completed with a single instruction (e.g. all shifts
>1on the 430 ISA). - Shifts of a 32-bit value are at least twice as costly, so the value passed for this option is divided by 2 and the resulting value is used instead ๐งฎ
- This only affects cases where a shift by multiple positions can't be completed with a single instruction (e.g. all shifts
-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 corresponding attribute. The fourth,"any", is the default, and it leaves placement entirely up to the linker script and how it assigns the standard sections (.text,.data, etc.) to the memory regions ๐-msilicon-errata=โ passes a request to the assembler to enable the fixes for the named silicon errata ๐ฉน-msilicon-errata-warn=โ ๐ Okay so this one tells the assembler to turn on warning messages for when a silicon errata might need to be applied. Heads up, bestie ๐ซถ-mwarn-devices-csv,-mno-warn-devices-csvโ Warns you ifdevices.csvcan't be found or if there's trouble parsing it. It's on by default (default: on) ๐
๐ธ NDS32 Options ๐ธ
These ones are made for NDS32 implementations ๐ฆ
-mbig-endianโ Generates code in big-endian mode ๐-mlittle-endianโ Generates code in little-endian mode โจ-mreduced-regsโ Uses the reduced-set registers for register allocation ๐-mfull-regsโ Uses the full-set registers for register allocation ๐-mcmovโ Generates conditional move instructions ๐-mno-cmovโ Does not generate conditional move instructions ๐-mext-perfโ Generates performance extension instructions ๐ฅ-mno-ext-perfโ Does not generate performance extension instructions ๐-mext-perf2โ Generates performance extension 2 instructions ๐-mno-ext-perf2โ Does not generate performance extension 2 instructions ๐ซ-mext-stringโ Generates string extension instructions ๐งต-mno-ext-stringโ Does not generate string extension instructions ๐ซ-mv3pushโ Generates v3push25/pop25instructions ๐ฆ-mno-v3pushโ Does not generate v3push25/pop25instructions ๐ โโ๏ธ-m16-bitโ Generates 16-bit instructions ๐-mno-16-bitโ Does not generate 16-bit instructions ๐ซถ-misr-vector-size=numโ Sets the size of each interrupt vector. It has to be either4or16, no in-between ๐ง-mcache-block-size=numโ Sets the size of each cache block. It has to be a power of 2 between4and512๐-march=archโ Names the target architecture ๐ธ-mcmodel=code-modelโ Sets the code model to one of these:smallโ All the data and read-only data segments have to fit within 512KB of addressing space. The text segment has to fit within 16MB of addressing space โจmediumโ The data segment has to fit 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 live anywhere within 4GB of addressing space ๐
-mctor-dtorโ Enables the constructor/destructor feature ๐-mrelaxโ Guides the linker to relax instructions ๐
๐ฆ Nios II Options ๐ฆ
These are the options made for the Altera Nios II processor ๐
-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 are the option names it recognizes:noneโ No 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 put in a small data section with a"section"attribute ๐globalโ Same aslocal, but it also generates GP-relative accesses for small data objects that are external, weak, or common. If you go with this one, every part of your program (libraries included) has to be compiled with the same-Gsetting, so don't skip that ๐จdataโ Generates GP-relative accesses for all data objects in the program. If you use this, the entire data and BSS segments have to fit in 64K of memory, and you need an appropriate linker script to place 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, the entire text, data, and BSS segments have to fit in 64K of memory, and you need an appropriate linker script to place them within the addressable range of the global pointer ๐
-mgpopt is the same as -mgpopt=local, and -mno-gpopt is the same as -mgpopt=none โจ
The default is -mgpopt, except when -fpic or -fPIC is specified to generate position-independent code. Heads up that the Nios II ABI doesn't allow GP-relative accesses from shared libraries ๐ซถ
You might need to set -mno-gpopt explicitly when you're building programs with lots of small data, including big GOT data sections. In that case, the 16-bit offset for GP-relative addressing might not be large enough to reach the whole small data section ๐ง
-mgprel-sec=regexpโ Adds section names that can be reached through GP-relative addressing. It's most useful alongside"section"attributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression ๐ธ
This one doesn't change how -G behaves. The sections you list are added on top of the standard .sdata and .sbss small-data sections that -mgpopt already recognizes ๐
-mr0rel-sec=regexpโ Names the sections that can be accessed through a 16-bit offset fromr0, meaning the low 32K or high 32K of the 32-bit address space. It's most useful with"section"attributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression ๐
Unlike GP-relative addressing for small data, zero-based addressing is never generated by default, and standard linker scripts don't use any conventional section names for the low or high areas of memory. So this one is a bit of a special case ๐ฆ
-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 which kinds of instructions it's allowed to emit when generating assembly code. The permissible names arer1andr2๐
Programs can read the preprocessor macro "__nios2_arch__", which has the value 1 or 2, telling you the targeted ISA level ๐
-mbypass-cache,-mno-bypass-cacheโ-mbypass-cacheforces all load and store instructions to skip the cache by using the I/O variants of those instructions. The default is not to bypass the cache ๐-mno-cache-volatile,-mcache-volatileโ Volatile memory accesses bypass the cache using the I/O variants of the load and store instructions. The default is not to bypass the cache ๐งต-mno-fast-sw-div,-mfast-sw-divโ-mno-fast-sw-divstops the use of table-based fast divide for small numbers. The default is to use the fast divide at-O3and above โก-mno-hw-mul,-mhw-mul,-mno-hw-mulx,-mhw-mulx,-mno-hw-div,-mhw-divโ Enables or disables the compiler emitting themul,mulx, anddivfamilies of instructions. The default is to emitmul, and not emitdivormulx๐ฅ-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 they're optional extensions to the R2 architecture, the default is not to emit them ๐ธ-mcustom-insn=N,-mno-custom-insnโ Each-mcustom-insn=Nenables a custom instruction with encodingNwhen generating code that usesinsn. For example,-mcustom-fadds=253generates custom instruction 253 for single-precision floating-point add operations, instead of the default behavior of using a library call ๐ฆ
These are the supported values of insn. Unless noted otherwise, the floating-point operations are expected to use normal IEEE 754 semantics and map 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 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 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 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 are only generated if-funsafe-math-optimizationsis also specified ๐
๐ซถ Conversions ๐ซถ
fextsdโ Converts from single precision to double precision ๐ftruncdsโ Converts from double precision to single precision ๐fixsi,fixsu,fixdi,fixduโ Converts floating point to signed or unsigned integer types, truncating towards zero ๐ฐroundโ Converts single-precision floating point to a 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โ Converts signed or unsigned integer types to floating-point types ๐ฆ
Okay bestie, the double-precision stuff on Nios II is a whole vibe ๐
โจ You need all of these transfer instructions for internal registers X and Y before any double-precision floating-point instruction will work ๐ฅ 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) goes to the custom arithmetic instruction with the least significant half in source register src1 and the most significant half in src2 ๐ง A custom instruction that returns a double-precision result gives you back the most significant 32 bits in the destination register, and the other half lands in 32-bit register Y ๐ GCC automatically generates the necessary code sequences to write register X and/or read register Y whenever you use double-precision floating-point instructions, so you literally don't have to do it yourself ๐ซถ
fwrxโ Writessrc1into the least significant half of X andsrc2into the most significant half of X ๐ฆfwryโ Writessrc1into Y ๐ธfrdxhi,frdxloโ Reads the most or least (respectively) significant half of X and stores it indest๐frdyโ Reads the value of Y and stores it intodestโจ
Also, if you want more local control over when Nios II custom instructions get generated, you can use the target("custom-insn=N") and target("no-custom-insn") function attributes or pragmas ๐
โจ -mcustom-fpu-cfg=name โจ
This option turns on a predefined, named set of custom instruction encodings (see -mcustom-insn above). Right now these sets are defined:
-mcustom-fpu-cfg=60-1 is equivalent to:
-mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254
-fsingle-precision-constant
-mcustom-fpu-cfg=60-2 is equivalent to:
-mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254
-mcustom-fdivs=255 -fsingle-precision-constant
-mcustom-fpu-cfg=72-3 is equivalent to:
-mcustom-floatus=243 -mcustom-fixsi=244 -mcustom-floatis=245
-mcustom-fcmpgts=246 -mcustom-fcmples=249 -mcustom-fcmpeqs=250
-mcustom-fcmpnes=251 -mcustom-fmuls=252 -mcustom-fadds=253
-mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant
-mcustom-fpu-cfg=fph2 is equivalent to:
-mcustom-fabss=224 -mcustom-fnegs=225 -mcustom-fcmpnes=226
-mcustom-fcmpeqs=227 -mcustom-fcmpges=228 -mcustom-fcmpgts=229
-mcustom-fcmples=230 -mcustom-fcmplts=231 -mcustom-fmaxs=232
-mcustom-fmins=233 -mcustom-round=248 -mcustom-fixsi=249
-mcustom-floatis=250 -mcustom-fsqrts=251 -mcustom-fmuls=252
-mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255
Heads up: any custom instruction assignments you give through individual -mcustom-insn= options will override the ones from -mcustom-fpu-cfg=, no matter what order they appear in on the command line ๐
You can also get more local control over picking an FPU configuration with the target("custom-fpu-cfg=name") function attribute or pragma ๐
The name fph2 is short for Nios II Floating Point Hardware 2 Component ๐
๐ Okay, real talk: the custom instructions enabled by-mcustom-fmins=233and-mcustom-fmaxs=234only get generated if-ffinite-math-onlyis specified. The custom instruction enabled by-mcustom-round=248only gets generated if-fno-math-errnois specified. Unlike the other configurations,-fsingle-precision-constantis not set here ๐ญ
These extra -m options are available for the Altera Nios II ELF (bare-metal) target ๐ง
-mhalโ Links with the HAL BSP. This suppresses linking with the GCC-provided C runtime startup and termination code, and it's typically used together with-msys-crt0=to specify the location of the alternate startup code the HAL BSP provides ๐-msmallcโ Links with a limited version of the C library,-lsmallc, instead of Newlib ๐ธ-msys-crt0=startfileโstartfileis the file name of the startfile (crt0) to use when linking. This option is only useful together with-mhal๐-msys-lib=systemlibโsystemlibis the library name of the library that provides the low-level system calls the C library needs, like"read"and"write". This is typically used to link with a library provided by a HAL BSP ๐ฆ
๐ Nvidia PTX Options ๐
These options are defined for Nvidia PTX ๐ฅ
-m64โ Ignored, but kept around for backward compatibility. Only the 64-bit ABI is supported ๐ซถ-misa=ISA-stringโ Generates code for the specified PTX ISA (e.g.sm_35). ISA strings must be lower-case. Valid ISA strings includesm_30andsm_35. The default ISA issm_35โจ-mptx=version-stringโ Generates code for the specified PTX version (e.g.7.0). Valid version strings include3.1,6.0,6.3, and7.0. The default PTX version is6.0, unless a higher minimal version is required for the PTX ISA specified via-misa=๐-mmainkernelโ Links in code for a__mainkernel. This is for stand-alone execution instead of offloading execution ๐-moptimizeโ Applies partitioned execution optimizations. This is the default whenever any level of optimization is selected ๐-msoft-stackโ Generates code that doesn't use.localmemory directly for stack storage. Instead, a per-warp stack pointer is maintained explicitly. This enables variable-length stack allocation (with variable-length arrays oralloca), and when global memory is used for the underlying storage, it makes it possible to access automatic variables from other threads, or with atomic instructions. This code generation variant is used for OpenMP offloading, but the option is exposed on its own for the purpose of testing the compiler. To generate code suitable for linking into programs using OpenMP offloading, use-mgompinstead ๐ง-muniform-simtโ Switches to a code generation variant that lets all threads in each warp execute, while keeping memory state and side effects as if only one thread in each warp were active outside of OpenMP SIMD regions. All atomic operations and calls to the runtime (malloc,free,vprintf) are conditionally executed (iff the current lane index equals the master lane index), and the register being assigned is copied via a shuffle instruction from the master lane. Outside of SIMD regions, lane 0 is the master; inside, each thread sees itself as the master. The shared memory arrayint __nvptx_uni[]stores all-zeros or all-ones bitmasks for each warp, indicating the current mode (0 outside of SIMD regions). Each thread can bitwise-and the bitmask at positiontid.ywith the current lane index to compute the master lane index ๐ฆ-mgompโ Generates code for use in OpenMP offloading. This enables-msoft-stackand-muniform-simt, and selects the corresponding multilib variant ๐
๐ OpenRISC Options ๐
These options are defined for OpenRISC ๐
-mboard=nameโ Configures a board-specific runtime. This gets passed to the linker for newlib board library linking. The default is"or1ksim"๐-mnewlibโ This option is ignored; it's only here for compatibility purposes. It used to select linker and preprocessor options for use with newlib ๐ซถ-msoft-div,-mhard-divโ Selects software or hardware divide (l.div,l.divu) instructions. The default is hardware divide ๐ฅ-msoft-mul,-mhard-mulโ Selects software or hardware multiply (l.mul,l.muli) instructions. The default is hardware multiply โจ-msoft-float,-mhard-floatโ Selects software or hardware for floating point operations. The default is software ๐ธ-mdouble-floatโ When-mhard-floatis selected, this enables generation of double-precision floating point instructions. By default, functions from libgcc are used to perform double-precision floating point operations ๐-munordered-floatโ When-mhard-floatis selected, this enables generation of unordered floating point compare and set flag (lf.sfun*) instructions. By default, functions from libgcc are used to perform unordered floating point compare and set flag operations ๐ง-mcmovโ Enables generation of conditional move (l.cmov) instructions. By default, the equivalent gets generated using set and branch ๐ฆ-mrorโ Enables generation of rotate right (l.ror) instructions. By default, functions from libgcc are used to perform rotate right operations ๐-mroriโ Enables generation of rotate right with immediate (l.rori) instructions. By default, functions from libgcc are used to perform rotate right with immediate operations ๐-msextโ Enables generation of sign extension (l.ext*) instructions. By default, memory loads are used to perform sign extension ๐-msfimmโ Enables generation of compare and set flag with immediate (l.sf*i) instructions. By default, extra instructions get generated to store the immediate in a register first ๐-mshftimmโ Enables generation of shift with immediate (l.srai,l.srli,l.slli) instructions. By default, extra instructions get generated to store the immediate in a register first ๐-mcmodel=smallโ Generates OpenRISC code for the small model: the GOT is limited to 64k. This is the default model ๐-mcmodel=largeโ Generates OpenRISC code for the large model: the GOT may grow up to 4G in size ๐
๐ธ PDP-11 Options ๐ธ
These options are defined for the PDP-11 ๐ง
-mfpuโ Uses hardware FPP floating point. This is the default. (FIS floating point on the PDP-11/40 is not supported.) Implies-m45๐-msoft-floatโ Doesn't use hardware floating point ๐ซถ-mac0โ Returns floating-point results inac0(fr0in Unix assembler syntax) ๐ฆ-mno-ac0โ Returns floating-point results in memory. This is the default ๐ฅ-m40โ Generates code for a PDP-11/40. Implies-msoft-float -mno-split๐-m45โ Generates code for a PDP-11/45. This is the default โจ-m10โ Generates code for a PDP-11/10. Implies-msoft-float -mno-split๐-mint16,-mno-int32โ Uses 16-bit"int". This is the default ๐ธ-mint32,-mno-int16โ Uses 32-bit"int"๐-msplitโ The target has split instruction and data space. Implies-m45๐-munix-asmโ Uses Unix assembler syntax ๐-mdec-asmโ Uses DEC assembler syntax ๐-mgnu-asmโ Uses GNU assembler syntax. This is the default ๐ง-mlraโ Uses the new LRA register allocator. By default, the old"reload"allocator is used ๐
๐ picoChip Options ๐
These -m options are defined for picoChip implementations, so if you're on picoChip, these are your extra toys ๐ง
-mae=ae_typeโ sets the instruction set, register set, and instruction scheduling parameters for array element type ae_type. The supported values areANY,MUL, andMAC. โจ-mae=ANYโ a completely generic AE type ๐ซถ Code built this way runs on any of the other AE types, but it isn't as efficient as code built for a specific one, and some operations (like multiplication) don't work properly on every AE type.-mae=MULโ the MUL AE type ๐ It's the most useful one for compiled code and the default.-mae=MACโ a DSP-style MAC AE ๐ Code built with this can perform poorly on byte (char) manipulation, since the DSP AE has no hardware support for byte load/stores ๐ญ
-msymbol-as-addressโ lets the compiler use a symbol name directly as an address in a load/store instruction, skipping the step of loading it into a register first ๐ฆ This usually makes bigger programs that run faster, but the results vary from program to program, so it's a user option instead of being permanently enabled.-mno-inefficient-warningsโ turns off warnings about inefficient code ๐ Those can show up when you do byte-level memory operations on the MAC AE type, because MAC has no hardware support for them, so every byte load/store has to be synthesized from word load/stores. The warning is basically telling you to rewrite the code to avoid byte operations, or to target an AE type with the right hardware support. This option silences it.
โจ PowerPC Options โจ
These are listed under
โจ PRU Options โจ
These command-line options are defined for the PRU target ๐
-minrtโ links with a minimum runtime environment that has no support for static initializers and constructors ๐ Using this can significantly shrink the final ELF binary.
Beware! The compiler could still generate code with static initializers and constructors, so it's on you, the programmer, to make sure your source program doesn't use those features ๐
-mmcu=mcuโ picks the PRU MCU variant you want ๐ธ Check Newlib for the exact list of supported MCUs.-mno-relaxโ makes GCC pass--no-relaxto the linker instead of--relax๐-mloopโ lets GCC use the LOOP instruction, or not ๐ You decide whether it's allowed.-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 are the differences:- Function Pointer Size โ the TI ABI says function (code) pointers are 16-bit, whereas GNU only supports 32-bit data and code pointers ๐ง
- Optional Return Value Pointer โ function return values larger than 64 bits get passed using a hidden pointer as the first argument of the function. The TI ABI says that pointer can be NULL if the caller isn't using the returned value. GNU always passes and expects a valid return value pointer.
- The current
-mabi=tiimplementation just raises a compile error whenever any of the above code constructs shows up ๐ญ So the standard C library can't be built, and it gets omitted when linking with-mabi=ti. - Relaxation โ relaxation is a GNU feature, and for safety reasons it's disabled when using
-mabi=ti๐ซถ The TI toolchain doesn't emit relocations for QBBx instructions, so the GNU linker can't adjust them when shortening adjacent LDI32 pseudo instructions.
โจ RISC-V Options โจ
These command-line options are defined for RISC-V targets ๐ฆ
-mbranch-cost=nโ sets the cost of branches to roughlyninstructions ๐-mplt,-mno-pltโ when generating PIC code, these decide whether PLTs are allowed or not ๐ธ They're ignored for non-PIC code. The default is-mplt.-mabi=ABI-stringโ specifies 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=lp64dmeans long and pointers are 64-bit (which implicitly makes int 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 allows floating-point values up to 32 bits long to be passed in registers. Or-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers.- The default for this is system dependent, so if you want a specific calling convention, specify one explicitly ๐ซถ
- The valid calling conventions are:
ilp32,ilp32f,ilp32d,lp64,lp64f, andlp64d. - Some calling conventions are impossible on some ISAs ๐ For example,
-march=rv32if -mabi=ilp32dis invalid, because the ABI requires 64-bit values to be passed in F registers, but F registers are only 32 bits wide. - There's also the
ilp32eABI, which can only be used with therv32earchitecture. It isn't well specified at present and is subject to change โ ๏ธ
-mfdiv,-mno-fdivโ do or don't use hardware floating-point divide and square root instructions โจ This requires the F or D extensions for floating-point registers. The default is to use them if the specified architecture has these instructions.-mdiv,-mno-divโ do or don't use hardware instructions for integer division ๐ฅ This requires the M extension. The default is to use them if the specified architecture has these instructions.-misa-spec=ISA-spec-stringโ picks the version of the RISC-V Unprivileged (formerly User-Level) ISA specification your code should conform to ๐ The possibilities for ISA-spec-string are:2.2โ produce code conforming to version 2.2 ๐20190608โ produce code conforming to version 20190608 ๐20191213โ produce code conforming to version 20191213 ๐- The default is
-misa-spec=20191213, unless GCC has been configured with--with-isa-spec=specifying a different default version.
-march=ISA-stringโ generates code for the given RISC-V ISA (e.g.rv64im) ๐ ISA strings must be lower-case. Examples includerv64i,rv32g,rv32e, andrv32imaf.- When
-march=isn't specified, the setting from-mcpugets used ๐ง - If both
-marchand-mcpu=are left unspecified, the default is system dependent, so users who want specific architecture extensions should specify one explicitly ๐
- When
-mcpu=processor-stringโ uses the architecture of, and optimizes output for, the given processor, identified 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 output for the given processor, identified 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, the setting from-mcpugets used, and the default isrocketif neither is specified ๐ฆ - The
sizechoice isn't meant for end-users ๐ It's used when-Osis specified. It overrides the instruction cost info provided by-mtune=, but it doesn't override the pipeline info. This helps reduce code size while still giving good performance.
- When
-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐งฑ If-mpreferred-stack-boundaryisn't specified, the default is 4 (16 bytes or 128-bits).
Warning: If you use this switch, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐ญ
-msmall-data-limit=nโ puts global and static data smaller thannbytes into a special section (on some targets) ๐-msave-restore,-mno-save-restoreโ do or don't use smaller but slower prologue and epilogue code that uses library function calls ๐ข The default is to use fast inline prologues and epilogues โก-mshorten-memrefs,-mno-shorten-memrefsโ do or don't try to make more use of compressed load/store instructions ๐๏ธ This works by replacing a load/store ofbase register + large offsetwith a new load/store ofnew base + small offset. If the new base gets stored in a compressed register, then the new load/store can be compressed. Right now it only targets 32-bit integer load/stores.-mstrict-align,-mno-strict-alignโ-mstrict-alignmeans don't generate unaligned memory accesses, and-mno-strict-alignmeans go ahead and generate them ๐ซ The default depends on whether the processor you're optimizing for supports fast unaligned access or not.-mcmodel=medlowโ generates code for the medium-low code model ๐ The program and its statically defined symbols must lie within a single 2 GiB address range, and must lie between absolute addresses -2 GiB and +2 GiB. Programs can be statically or dynamically linked. This is the default code model ๐-mcmodel=medanyโ generates code for the medium-any code model ๐ The program and its statically defined symbols must be within any single 2 GiB address range. Programs can be statically or dynamically linked.- Code from the medium-any code model is position-independent, but it isn't guaranteed to function correctly when linked into position-independent executables or libraries ๐ฅบ
-mexplicit-relocs,-mno-exlicit-relocsโ use or don't use assembler relocation operators when dealing with symbolic addresses ๐งฉ The alternative is to use assembler macros instead, which may limit optimization.-mrelax,-mno-relaxโ take advantage of linker relaxations to reduce the number of instructions required to materialize symbol addresses โ๏ธ The default is to take advantage of linker relaxations.
๐ฆ RISC-V Options ๐ฆ
Okay so the next few are all about the RISC-V tea, bestie โโจ
-memit-attribute,-mno-emit-attributeโ-memit-attributetells GCC to emit a RISC-V attribute that records extra info inside your ELF objects ๐ฆ, and-mno-emit-attributetells it not to. โ ๏ธ This feature needs at least binutils 2.32, so check your toolchain first, bestie!-malign-data=typeโ this controls how GCC aligns variables and constants that are array, struct, or union types ๐. You get two choices:xlenuses the x register width as the alignment value (and it's the default ๐), whilenaturaluses natural alignment.-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-*-*one.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ these generate stack protection code using a canary at guard ๐ก๏ธ. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block.
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to pick the details ๐. The first says which register to use as the base register for reading the canary, and the second says what offset from that base register to read from. There is no default register or offset, because this is entirely for use within the Linux kernel ๐ง.
๐ธ RL78 Options ๐ธ
-msimโ links in extra target libraries so your code can run inside a simulator ๐ง.-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ this picks the flavour of hardware multiplication and division support you want ๐ . The simplest isnone, which uses software for both multiplication and division, and it's the default โจ. Theg13value is for the hardware multiply/divide peripheral found on RL78/G13 (S2 core) targets. Theg14value uses the multiplication and division instructions supported by RL78/G14 (S3 core) parts. The valuerl78is an alias forg14, and the valuemg10is an alias fornone.
In addition, a C preprocessor macro gets defined based on this option ๐. The possible values are __RL78_MUL_NONE__, __RL78_MUL_G13__, or __RL78_MUL_G14__.
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ this specifies which RL78 core you're targeting ๐. The default is the G14 core, also known as an S3 core or just RL78. The G13 (S2) core has no multiply or divide instructions and uses a hardware peripheral for those jobs instead ๐ง. The G10 (S1) core has no register banks, so it uses a different calling convention ๐คทโโ๏ธ.
If you set this option, it also picks which type of hardware multiply support to use ๐. The exception is if you override it with an explicit -mmul=none on the command line. So -mcpu=g13 enables the G13 hardware multiply peripheral, and -mcpu=g10 disables hardware multiplications altogether ๐ญ.
Heads up, bestie ๐: even though the RL78/G14 core is the default target, specifying-mcpu=g14or-mcpu=rl78on the command line does change how the toolchain behaves, because it also enables G14 hardware multiply support. If these options aren't on the command line, software multiplication routines get used even though the code targets the RL78 core. This is for backwards compatibility with older toolchains that didn't have hardware multiply and divide support.
In addition, a C preprocessor macro gets defined based on this setting too โจ. The possible values are __RL78_G10__, __RL78_G13__, or __RL78_G14__.
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the matching-mcpu=option ๐. They're only here for backwards compatibility, so you don't need them in new code, periodt ๐ .-mallregsโ lets the compiler use all of the available registers ๐. By default, registersr24..r31are reserved for interrupt handlers ๐. With this option turned on, those registers can be used in ordinary functions too.-m64bit-doubles,-m32bit-doublesโ this makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size ๐ฆ. The default is-m32bit-doubles.-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ this says whether interrupt handler functions should preserve the MDUC registers ๐ก๏ธ. You only need it if normal code might use the MDUC registers, for example because it does multiplication and division. The default is to ignore the MDUC registers, because that makes the interrupt handlers faster โก. The target option-mg13has to be passed for this to work, since this feature is only available on the G13 target (S2 core). The MDUC registers only get saved if the interrupt handler performs a multiplication or division operation, or if it calls another function.
โจ IBM RS/6000 and PowerPC Options โจ
These -m options are defined for the IBM RS/6000 and PowerPC ๐. 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 the specification of these options, and we recommend you use -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 ๐จ.-mmfcrf,-mno-mfcrfโ-mmfcrflets GCC generate the move from condition register field instruction. That's implemented on the POWER4 processor and other processors that support the PowerPC V2.01 architecture ๐ฅ.-mpopcntb,-mno-popcntbโ-mpopcntblets GCC generate the popcount and double-precision FP reciprocal estimate instruction. That's implemented on the POWER5 processor and other processors that support the PowerPC V2.02 architecture ๐ .-mpopcntd,-mno-popcntdโ-mpopcntdlets GCC generate the popcount instruction. That's implemented on the POWER7 processor and other processors that support the PowerPC V2.06 architecture ๐.-mfprnd,-mno-fprndโ-mfprndlets GCC generate the FP round to integer instructions. Those are implemented on the POWER5+ processor and other processors that support the PowerPC V2.03 architecture ๐ธ.-mcmpb,-mno-cmpbโ-mcmpblets GCC generate the compare bytes instruction. That's implemented on the POWER6 processor and other processors that support the PowerPC V2.05 architecture ๐ฆ.-mhard-dfp,-mno-hard-dfpโ-mhard-dfplets GCC generate the decimal floating-point instructions implemented on some POWER processors ๐ง.-mpowerpc64,-mno-powerpc64โ-mpowerpc64lets GCC generate the additional 64-bit instructions found in the full PowerPC64 architecture, and it treats GPRs as 64-bit doubleword quantities ๐. GCC defaults to-mno-powerpc64.-mcpu=cpu_typeโ this sets the architecture type, register usage, and instruction scheduling parameters for the machine type cpu_type ๐. The supported values for cpu_type are401,403,405,405fp,440,440fp,464,464fp,476,476fp,505,601,602,603,603e,604,604e,620,630,740,7400,7450,750,801,821,823,860,970,8540,a2,e300c2,e300c3,e500mc,e500mc64,e5500,e6500,ec603e,G3,G4,G5,titan,power3,power4,power5,power5+,power6,power6x,power7,power8,power9,power10,powerpc,powerpc64,powerpc64le,rs64, andnative๐.
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le specify pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC architecture machine types ๐ง. An appropriate, generic processor model is assumed for scheduling purposes.
Specifying native as the cpu type detects and selects the architecture option that matches the host processor of the system doing the compilation ๐.
The other options each specify a specific processor. Code generated under those options runs best on that processor, and may not run at all on others ๐.
Watch out ๐: -mcpu=native has no effect if GCC doesn't recognize the processor.
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 particular options set for any CPU vary 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 an individual option to a particular value, you can specify it after the -mcpu option, like -mcpu=970 -mno-altivec โจ.
On AIX, the -maltivec and -mpowerpc64 options are not enabled or disabled by the -mcpu option at present, because AIX doesn't have full support for these options ๐. 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 type cpu_type, but it doesn't set the architecture type or register usage the way-mcpu=cpu_typedoes ๐ถ. The same values for cpu_type are used for-mtuneas for-mcpu. If you specify both, the generated 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 may 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 may be up to 4G in size ๐. Other data and code is only limited by the 64-bit address space โจ.-maltivec,-mno-altivecโ okay so this one is the AltiVec switch ๐-maltivecmakes GCC generate AltiVec code and unlocks built-in functions for more direct access to the AltiVec instruction set โจ.-mno-altivecsays "nah, don't use them" ๐. You might also need-mabi=altivecto turn on the AltiVec ABI enhancements ๐
When -maltivec is on, the element order for AltiVec intrinsics like vec_splat, vec_extract, and vec_insert follows the endianness of your target ๐ Element zero is the leftmost element in a vector register on a big-endian platform, and the rightmost one on a little-endian platform. Main character energy for real ๐
-mvrsave,-mno-vrsaveโ generates VRSAVE instructions when you're making AltiVec code ๐ฆ-msecure-pltโ this one is lowkey iconic ๐ฅ It letsldandld.sobuild executables and shared libraries with non-executable.pltand.gotsections. It's a PowerPC 32-bit SYSV ABI option, so only for that crowd ๐ง-mbss-pltโ the opposite vibe ๐ธ It generates a BSS.pltsection thatld.sofills in, and it needs both the.pltand.gotsections to be writable and executable. Also a PowerPC 32-bit SYSV ABI option ๐-misel,-mno-iselโ turns ISEL instruction generation on or off โจ-mvsx,-mno-vsxโ generates code that uses (or skips) vector/scalar (VSX) instructions, and turns on the built-in functions for direct access to the VSX instruction set ๐-mcrypto,-mno-cryptoโ enables (or disables) the built-ins that give you direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐-mhtm,-mno-htmโ enables (or disables) the built-ins for the Hardware Transactional Memory (HTM) instructions, also added in version 2.07 of the PowerPC ISA ๐ซถ-mpower8-fusion,-mno-power8-fusionโ generates code that keeps some integer operations next to each other, so they can get fused together on POWER8 and later processors ๐ The-mno-version doesn't keep them together.-mpower8-vector,-mno-power8-vectorโ uses (or doesn't use) the vector and scalar instructions added in version 2.07 of the PowerPC ISA โญ The positive one also unlocks built-ins for more direct access to those vector instructions ๐-mquad-memory,-mno-quad-memoryโ uses (or avoids) the non-atomic quad word memory instructions ๐ฆ Heads up:-mquad-memoryneeds 64-bit mode โ ๏ธ-mquad-memory-atomic,-mno-quad-memory-atomicโ same energy, but for the atomic quad word memory instructions ๐ Also needs 64-bit mode.-mfloat128,-mno-float128โ enables or disables the__float128keyword for IEEE 128-bit floating point ๐ You get either software emulation or hardware instructions for it.
You need VSX (-mvsx) enabled to use IEEE 128-bit floating point support, and it's only supported on Linux ๐ง By default, -mfloat128 is on for PowerPC Linux systems using VSX, and off 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 also turns on generation of ISA 3.0 IEEE 128-bit floating point instructions โจ Otherwise, if you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets handled with software emulation ๐
-mfloat128-hardware,-mno-float128-hardwareโ enables or disables using ISA 3.0 hardware instructions to support the__float128data type ๐ฅ It's on by default on PowerPC Linux systems using the ISA 3.0 instruction set, and off on other systems.-m32,-m64โ generates code for 32-bit or 64-bit environments on Darwin and SVR4 targets (including GNU/Linux) ๐ธ The 32-bit environment setsint,long, and pointer to 32 bits, and the code runs on any PowerPC variant. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits, and generates code for PowerPC64, same as-mpowerpc64๐ง-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ these all tweak how the TOC (Table Of Contents) gets made, and every executable file has one ๐-mfull-tocis the default. With it, GCC gives at least one TOC entry to each unique non-automatic variable reference in your program, and also puts floating-point constants in the TOC. The catch is that only 16,384 entries fit in the TOC ๐ญ
If the linker yells that you've overflowed the TOC space, you can shrink its usage with -mno-fp-in-toc and/or -mno-sum-in-toc ๐ซถ -mno-fp-in-toc keeps floating-point constants out of the TOC, and -mno-sum-in-toc makes GCC calculate the sum of an address and a constant at run time instead of stashing that sum in 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're still out of TOC space even with both of those, try -mminimal-toc ๐ It makes only one TOC entry per file. Your code gets slower and larger, but it uses extremely little TOC space. Maybe only use it on files with less frequently-executed code.
-maix64,-maix32โ-maix64enables the 64-bit AIX ABI and calling convention, with 64-bit pointers, a 64-bitlongtype, and the infrastructure to support them ๐ It implies-mpowerpc64.-maix32turns the 64-bit ABI off and implies-mno-powerpc64. Just so you know, GCC defaults to-maix32๐-mxl-compat,-mno-xl-compatโ makes your code match IBM XL compiler semantics more closely when you're using the AIX-compatible ABI ๐ With it on, floating-point arguments passed to prototyped functions go on the stack past the register save area (RSA), in addition to the argument FPRs. It also stops assuming that the most significant double in a 128-bitlong doubleis properly rounded when comparing values and converting to double, and uses XL symbol names for thelong doublesupport routines.
The AIX calling convention got extended, but that wasn't documented at first, to handle an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than it declared ๐ IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine is compiled without optimization. Storing floating-point arguments on the stack is inefficient and rarely needed, so this option is not on by default. Only turn it on when calling subroutines compiled by IBM XL compilers without optimization.
-mpeโ supports the IBM RS/6000 SP Parallel Environment (PE) ๐ฐ๏ธ It links your message-passing app with special startup code so it can actually run. The system needs 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 โจ PE doesn't support threads, so-mpeand-pthreadare incompatible ๐ซ-malign-natural,-malign-powerโ on AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux,-malign-naturaloverrides the ABI-defined alignment of larger types (like floating-point doubles) and puts them on their natural size-based boundary ๐ธ-malign-powertells GCC to follow the ABI-specified alignment rules instead. GCC defaults to the standard alignment defined in the ABI.
On 64-bit Darwin, natural alignment is the default, and -malign-power isn't supported there ๐
-msoft-float,-mhard-floatโ generates code that doesn't use (or does use) the floating-point register set ๐ If you use-msoft-float, software floating-point emulation is provided, but you have to pass the option to GCC when linking too โ ๏ธ-mmultiple,-mno-multipleโ uses (or doesn't use) the load multiple word and store multiple word instructions ๐ง These are generated by default on POWER systems, but not on PowerPC systems. Don't use-mmultipleon little-endian PowerPC systems, because those instructions don't work when the processor is in little-endian mode ๐ญ The exceptions are PPC740 and PPC750, which do permit these instructions in little-endian mode.-mupdate,-mno-updateโ uses (or doesn't use) the load or store instructions that update the base register to the address of the calculated memory location ๐ These are generated by default. Heads up on-mno-update: there's a small window between when the stack pointer gets updated and when the address of the previous frame gets stored, so code that walks the stack frame across interrupts or signals might end up with corrupted data โ ๏ธ-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ generates code that tries to avoid (or doesn't avoid) indexed load or store instructions ๐ฆ These can cost performance on Power6 processors in certain situations, like stepping through large arrays that cross a 16M boundary. It's enabled by default when targeting Power6, and disabled otherwise.-mfused-madd,-mno-fused-maddโ uses (or doesn't use) the floating-point multiply and accumulate instructions โจ These are generated by default if hardware floating point is used. The machine-dependent-mfused-maddoption is now mapped to the machine-independent-ffp-contract=fastoption, and-mno-fused-maddis mapped to-ffp-contract=off๐ซถ-mmulhw,-mno-mulhwโ okay so these turn the half-word multiply and multiply-accumulate instructions on or off ๐ฅ. They're used on the IBM 405, 440, 464 and 476 processors, and they're on by default when you're targeting those chips ๐ .-mdlmzb,-mno-dlmzbโ this one switches the string-searchdlmzbinstruction on or off on the IBM 405, 440, 464 and 476 processors โจ. It's generated by default for those processors too, so you're already getting it ๐ง.-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems, these decide whether structures and unions with bit-fields get forced to line up with the base type of the bit-field ๐ฆ.-mno-bit-alignsays "nah, don't force it," and-mbit-alignsays "yes, force it" ๐.- Here's the vibe: by default, a structure with nothing but 8
unsignedbit-fields of length 1 gets aligned to a 4-byte boundary and ends up 4 bytes big ๐. Add-mno-bit-alignand that same structure lines up on a 1-byte boundary and is only 1 byte ๐ญ.
- Here's the vibe: by default, a structure with nothing but 8
-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems, these decide whether the compiler just trusts the system to handle unaligned memory references ๐ซถ.-mno-strict-alignis the "yeah, the system's got it" option, and-mstrict-alignis the "don't assume that" option ๐ธ.-mrelocatable,-mno-relocatableโ these control whether a static executable is allowed to get moved to a different address at run time ๐. With-mrelocatable, a simple embedded PowerPC loader has to relocate the whole.got2section and the 4-byte locations listed in the.fixupsection, which is a table of 32-bit addresses this option generates ๐. For it to actually work, every object you link together has to be compiled with-mrelocatableor-mrelocatable-lib๐ฅ. Heads up:-mrelocatablecode aligns the stack to an 8-byte boundary ๐.-mrelocatable-lib,-mno-relocatable-libโ this is basically-mrelocatablewith a twist โจ. It still makes a.fixupsection so static executables can be relocated at run time, but it doesn't use the smaller stack alignment that-mrelocatabledoes ๐ฆ. Objects built with-mrelocatable-libcan be linked with objects built with any combo of the-mrelocatableoptions, so it's super flexible ๐ง.-mno-toc,-mtocโ on System V.4 and embedded PowerPC systems, these decide whether the compiler assumes register 2 holds a pointer to a global area with the addresses the program uses ๐.-mno-tocsays don't assume it, and-mtocsays go ahead and assume it ๐ .-mlittle,-mlittle-endianโ on System V.4 and embedded PowerPC systems, this compiles your code for little-endian mode ๐ธ.-mlittle-endianand-mlittledo the exact same thing, so pick whichever you vibe with ๐ซถ.-mbig,-mbig-endianโ same energy as above but for big-endian mode on System V.4 and embedded PowerPC systems ๐.-mbig-endianis identical to-mbigโจ.-mdynamic-no-picโ on Darwin and Mac OS X systems, this compiles code so it isn't relocatable, but its external references still are ๐. The result works for applications but not for shared libraries ๐ญ.-msingle-pic-baseโ this treats the register used for PIC addressing as read-only, so it doesn't get loaded in the prologue for every function ๐. Instead, the runtime system is in charge of setting that register to the right value before execution starts ๐.-mprioritize-restricted-insns=priorityโ this controls the priority given to dispatch-slot restricted instructions during the second scheduling pass ๐ . Thepriorityargument takes0,1, or2, which means no priority, highest priority, or second-highest priority for those instructions ๐ฅ.-msched-costly-dep=dependence_typeโ this picks which dependences the target considers costly during instruction scheduling ๐ง. Thedependence_typeargument takes one of these values:noโ no dependence is costly ๐.allโ every dependence is costly ๐.true_store_to_loadโ a true dependence from store to load is costly ๐.store_to_loadโ any dependence from store to load is costly โจ.numberโ any dependence whose latency is greater than or equal tonumberis costly ๐ฆ.
-minsert-sched-nops=schemeโ this picks which NOP insertion scheme gets used during the second scheduling pass ๐ธ. Theschemeargument takes one of these:noโ don't insert NOPs at all ๐ซถ.padโ pad any dispatch group with vacant issue slots using NOPs, based on the scheduler's grouping ๐.regroup_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, based on the estimated processor grouping ๐ฅ.numberโ insert NOPs to force costly dependent insns into separate groups, usingnumberNOPs to push an insn into a new group ๐ .
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code using the calling conventions from the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement ๐. It's the default unless you configured GCC usingpowerpc-*-eabiaix๐.-mcall-sysv-eabi,-mcall-eabiโ these are shorthand for specifying both-mcall-sysvand-meabi๐.-mcall-sysv-noeabiโ shorthand for specifying both-mcall-sysvand-mno-eabi๐ง.-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐ฆ.-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง.-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐.-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐ธ.-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐ซถ.-mtraceback=traceback_typeโ this selects the type of traceback table ๐. Valid values fortraceback_typearefull,part, andno๐ .-maix-struct-returnโ returns all structures in memory, as the AIX ABI specifies ๐ฅ.-msvr4-struct-returnโ returns structures smaller than 8 bytes in registers, as the SVR4 ABI specifies ๐.-mabi=abi-typeโ this extends the current ABI with a particular extension, or removes one ๐. Valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1,elfv2, and, for AIX,vec-extabiandvec-default๐.-mabi=ibmlongdoubleโ switches the current ABI to IBM extended-precision long double โจ. This probably won't work if your system defaults to IEEE extended-precision long double ๐. If you change the long double type away from IEEE extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption ๐. This one needs-mlong-double-128enabled ๐ฅ.-mabi=ieeelongdoubleโ switches the current ABI to IEEE extended-precision long double ๐ฆ. This probably won't work if your system defaults to IBM extended-precision long double ๐. If you change the long double type away from IBM extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption ๐. This one needs-mlong-double-128enabled ๐ฅ.-mabi=elfv1โ switches the current ABI to ELFv1 ๐ง. This is the default ABI for big-endian PowerPC 64-bit Linux ๐ง. Overriding the default ABI needs special system support and is likely to fail in spectacular ways ๐.-mabi=elfv2โ switches the current ABI to ELFv2 โจ. This is the default ABI for little-endian PowerPC 64-bit Linux ๐ธ. Overriding the default ABI needs special system support and is likely to fail in spectacular ways ๐.-mgnu-attribute,-mno-gnu-attributeโ these emit.gnu_attributeassembly directives that set tag/value pairs in a.gnu.attributessection ๐. Those pairs describe ABI variations in function parameters or return values ๐.-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems,-mprototypeassumes every call to a variable argument function is properly prototyped ๐ซถ. Without that, 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 says whether floating-point values are passed in the floating-point registers, in case the function takes variable arguments ๐ง. With-mprototype, only calls to prototyped variable argument functions set or clear that bit ๐ .-msimโ on embedded PowerPC systems, this assumes the startup module is calledsim-crt0.oand the standard C libraries arelibsim.aandlibc.a๐. It's the default forpowerpc-*-eabisimconfigurations ๐.-mmvmeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibmvme.aandlibc.a๐ฆ.-madsโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibads.aandlibc.a๐.-myellowknifeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibyk.aandlibc.a๐.-mvxworksโ on System V.4 and embedded PowerPC systems, this tells the compiler you're building for a VxWorks system ๐ธ.-membโ on embedded PowerPC systems, this sets thePPC_EMBbit in the ELF flags header, which indicates that eabi extended relocations are used ๐.-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems, these decide whether you adhere to the Embedded Applications Binary Interface (EABI), a set of modifications to the System V.4 specifications โจ. Here's the breakdown ๐ซถ:-meabimeans the stack is aligned to an 8-byte boundary ๐, a function__eabigets called frommainto set up the EABI environment ๐, and the-msdataoption can use bothr2andr13to point to two separate small data areas ๐ .-mno-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 -meabi option is on by default if you configured GCC using one of the powerpc*-*-eabi* options ๐.
--msdata=eabi โ โจ On System V.4 and embedded PowerPC, small initialized const globals and statics go into the .sdata2 section, which is pointed to by register r2. Small initialized non-const globals and statics go into .sdata, pointed to by register r13. Small uninitialized globals and statics go into .sbss, which sits right next to .sdata. Heads up: -msdata=eabi is incompatible with -mrelocatable, and it also turns on -memb ๐
-msdata=sysvโ ๐ธ On System V.4 and embedded PowerPC, small global and static data goes into.sdata, pointed to by registerr13. Small uninitialized globals and statics go into.sbss, which is adjacent to.sdata. Also,-msdata=sysvis incompatible with-mrelocatable๐-msdata=default,-msdataโ ๐ฆ On System V.4 and embedded PowerPC, if-meabiis used, the code gets compiled the same as-msdata=eabi. Otherwise, it gets compiled the same as-msdata=sysv.-msdata=dataโ ๐ง On System V.4 and embedded PowerPC, small global data goes into.sdata, and small uninitialized global data goes into.sbss. The twist is that registerr13is not used to address small data. This is the default unless some other-msdataoption is used.-msdata=none,-mno-sdataโ ๐ On embedded PowerPC, all initialized global and static data goes into.data, and all uninitialized data goes into.bss.-mreadonly-in-sdataโ ๐ Read-only objects get put into.sdatatoo. This is the default.-mblock-move-inline-limit=numโ ๐ฅ Inline all block moves (like calls tomemcpyor structure copies) that are less than or equal tonumbytes. The minimum value fornumis 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default value is target-specific.-mblock-compare-inline-limit=numโ ๐ Generate non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal tonumbytes. Ifnumis0, all inline expansion (both non-loop and loop) of block compare is disabled. The default value is target-specific.-mblock-compare-inline-loop-limit=numโ ๐ Generate an inline expansion using loop code for all block compares that are less than or equal tonumbytes, but greater than the limit for non-loop inline block compare expansion. If the block length isn't constant, at mostnumbytes will be compared beforememcmpis called to compare the rest of the block. The default value is target-specific.-mstring-compare-inline-limit=numโ โญ Compare at mostnumstring 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, global and static items less than or equal tonumbytes go into the small data or BSS sections instead of the normal data or BSS section. By default,numis 8. The-G numswitch is also passed to the linker. All modules should be compiled with the same-G numvalue.-mregnames,-mno-regnamesโ ๐ซถ On System V.4 and embedded PowerPC, GCC does (or does not) emit register names in the assembly output using symbolic forms.-mlongcall,-mno-longcallโ ๐ญ By default, GCC assumes that all calls are far away, so a longer and more expensive calling sequence is required. This is needed for calls farther than 32 megabytes (33,554,432 bytes) from the current location. A short call is generated if the compiler knows the call can't be that far away. This setting can be overridden by theshortcallfunction attribute, or by#pragma longcall(0).
Some linkers can detect out-of-range calls and generate glue code on the fly. On these systems, long calls are unnecessary and generate slower code. As of this writing, the AIX linker can do this, and so can the GNU linker for PowerPC/64. The plan is to add this feature to the GNU linker for 32-bit PowerPC systems too.
On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see -mpltseq). PowerPC with -mbss-plt and PowerPC64 ELFv1 (big-endian) do not support inline PLT calls.
On Darwin/PPC systems, #pragma longcall generates jbsr callee, L42, plus a branch island (glue code). The two target addresses represent the callee and the branch island. The Darwin/PPC linker prefers the first address and generates bl callee if the PPC bl instruction reaches the callee directly. Otherwise, the linker generates bl L42 to call the branch island. The branch island is appended to the body of the calling function, and it computes the full 32-bit address of the callee and jumps to it.
On Mach-O (Darwin) systems, this option tells the compiler to emit the glue for every direct call, and then the Darwin linker decides whether to use it or discard it.
In the future, GCC may ignore all longcall specifications when the linker is known to generate glue. ๐ฆ
-mpltseq,-mno-pltseqโ ๐ Implement (or do not implement)-fno-pltand long calls using an inline PLT call sequence. That sequence supports lazy linking and long calls to functions indlopen'd shared libraries. Inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers. They're enabled by default if the support is detected when configuring GCC, and, in the case of 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โ ๐ง Mark (or do not mark) calls to__tls_get_addrwith a relocation that specifies the function argument. The relocation lets the linker reliably connect the function call with the argument setup instructions for TLS optimization. That in turn lets GCC schedule the sequence better ๐-mrecip,-mno-recipโ โจ This option enables the use of the reciprocal estimate and reciprocal square root estimate instructions, with extra Newton-Raphson steps to boost precision, instead of doing a divide or a square root and divide for floating-point arguments. You should use the-ffast-mathoption when 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 can drop by up to 2 ulp (i.e. the inverse of 1.0 equals0.99999994) for reciprocal square roots.
โ ๏ธ Precision bestie alert: with -mrecip, reciprocal square roots can lose up to 2 ulp of precision.
-mrecip=optโ ๐ This controls which reciprocal estimate instructions may be used.optis a comma-separated list of options, and any of them can be preceded by a!to invert it:allโ enable all estimate instructions.defaultโ enable the default instructions, which is equivalent to-mrecip.noneโ disable all estimate instructions, which is 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 do not 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 give an estimate that converges after three steps.-mveclibabi=typeโ ๐ Specifies the ABI type to use for vectorizing intrinsics using an external library. The only type supported right now ismass, which tells GCC to use IBM's Mathematical Acceleration Subsystem (MASS) libraries for vectorizing intrinsics with external libraries. When generating code for power7, GCC currently emits calls to the following functions:
"acosd2", "acosf4", "acoshd2", "acoshf4", "asind2", "asinf4", "asinhd2", "asinhf4",
"atan2d2", "atan2f4", "atand2", "atanf4", "atanhd2", "atanhf4", "cbrtd2", "cbrtf4",
"cosd2", "cosf4", "coshd2", "coshf4", "erfcd2", "erfcf4", "erfd2", "erff4",
"exp2d2", "exp2f4", "expd2", "expf4", "expm1d2", "expm1f4", "hypotd2", "hypotf4",
"lgammad2", "lgammaf4", "log10d2", "log10f4", "log1pd2", "log1pf4", "log2d2", "log2f4",
"logd2", "logf4", "powd2", "powf4", "sind2", "sinf4", "sinhd2", "sinhf4",
"sqrtd2", "sqrtf4", "tand2", "tanf4", "tanhd2", and "tanhf4"
Both -ftree-vectorize and -funsafe-math-optimizations must also be enabled. The MASS libraries must be specified at link time.
-mfriz,-mno-frizโ ๐ฆ Generate (or do not generate) thefrizinstruction when-funsafe-math-optimizationsis used to optimize rounding of floating-point values to 64-bit integers and back to floating point. Thefrizinstruction doesn't return the same value if the floating-point number is too large to fit in an integer.
-mpointers-to-nested-functions -mno-pointers-to-nested-functions
Okay so these two are a PACKAGE deal ๐ง Generate (or don't generate) code that loads up the static chain register ("r11") when you call through a pointer, on AIX and 64-bit Linux systems, where a function pointer points to a 3-word descriptor. That descriptor holds the function address, the TOC value that gets loaded into register "r2", and the static chain value that gets loaded into register "r11". ๐
-mpointers-to-nested-functions is on by default, so you're already set!
โ ๏ธ If you use -mno-pointers-to-nested-functions, you can't call through pointers to nested functions, and you also can't call through pointers to functions compiled in other languages that use the static chain. Bestie, that's a whole no-go zone ๐
-msave-toc-indirect -mno-save-toc-indirect
Lowkey a bit of a technical one ๐ธ On AIX and 64-bit Linux systems, these decide whether the TOC value gets saved in the reserved stack location during the function prologue, but only if the function calls through a pointer. If the TOC value doesn't get saved in the prologue, it gets saved right before the call through the pointer instead. -mno-save-toc-indirect is the default, so that's the one you get unless you ask for something else โจ
-mcompat-align-parm -mno-compat-align-parm
Okay this one is giving throwback ๐ฐ๏ธ These make the compiler generate (or not generate) code that passes structure parameters with a maximum alignment of 64 bits, so it stays compatible with older versions of GCC.
Older versions of GCC (prior to 4.9.0) incorrectly didn't align a structure parameter on a 128-bit boundary when that structure had a member that needed 128-bit alignment. Newer versions of GCC fixed that bug ๐ You can use this option if you need your code to play nicely with functions compiled by those older versions.
-mno-compat-align-parm is the default, so you don't have to think about it unless you're dealing with the old stuff ๐ซถ
-mstack-protector-guard=guard -mstack-protector-guard-reg=reg -mstack-protector-guard-offset=offset -mstack-protector-guard-symbol=symbol
Main character energy, these are about stack protection! ๐ก๏ธ They generate stack protection code that uses a canary at the guard location. The supported locations are global for a global canary, or tls for a per-thread canary in the TLS block. tls is the default with GNU libc version 2.4 or later.
If you pick tls, then -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset tell the compiler which register to use as the base register for reading the canary, and what offset from that base to use. The defaults for those come from the relevant ABI, so you don't have to set them yourself ๐ฆ
-mstack-protector-guard-symbol=symbol overrides the offset with a symbol reference to a canary in the TLS block. Iykyk ๐
-mpcrel -mno-pcrel
Generate (or don't generate) pc-relative addressing. ๐งญ Just a heads up, -mpcrel only works if you also have the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) turned on. No cap, it needs both of those as its besties ๐ฏ
-mprefixed -mno-prefixed
Generate (or don't generate) addressing modes that use prefixed load and store instructions. โจ -mprefixed needs -mcpu=power10 (or later) to be enabled, so make sure your CPU target is on board first ๐
-mmma -mno-mma
Generate (or don't generate) the MMA instructions. ๐ฅ The -mma option needs -mcpu=power10 (or later) to be enabled too, same energy as -mprefixed ๐
-mrop-protect -mno-rop-protect
Generate (or don't generate) ROP protection instructions, but only when the target processor actually supports them ๐ Heads up, though: right now this option disables the shrink-wrap optimization (-fshrink-wrap). So it's a trade-off, bestie ๐
-mprivileged -mno-privileged
Generate (or don't generate) code that runs in privileged state. ๐ Very powerful, very serious, so use it with intention โจ
-mblock-ops-unaligned-vsx -mno-block-ops-unaligned-vsx
Generate (or don't generate) unaligned VSX loads and stores for inline expansion of memcpy and memmove. ๐ฆ Think of it as the compiler deciding whether to use unaligned VSX moves when it inlines those two.
โจ RX Options โจ
These command-line options are defined for RX targets, so they only matter if you're building for an RX chip ๐ธ
-m64bit-doubles -m32bit-doubles
Make the double data type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size. The default is -m32bit-doubles, and that's because RX floating-point hardware only works on 32-bit values. Makes sense, right? ๐
-fpu -nofpu
Enables (-fpu) or disables (-nofpu) the use of RX floating-point hardware. ๐ฅ The default is enabled for the RX600 series and disabled for the RX200 series.
Floating-point instructions are only generated for 32-bit floating-point values, though, so the FPU hardware isn't used for doubles if -m64bit-doubles is used. Plot twist ๐ญ
Note: if -fpu is enabled, then -funsafe-math-optimizations is also enabled automatically. The reason is that the RX FPU instructions are themselves unsafe ๐
-mcpu=name
Selects the type of RX CPU to target. Three types are supported right now: the generic RX600 and RX200 series hardware, and the specific RX610 CPU. The default is RX600 ๐ง
The only difference between RX600 and RX610 is that the RX610 doesn't support the MVTIPL instruction. That's it, that's the tea โ
The RX200 series doesn't have a hardware floating-point unit, so -nofpu is enabled by default when this type is selected ๐ซถ
-mbig-endian-data -mlittle-endian-data
Store data (but not code) in big-endian format. The default is -mlittle-endian-data, which stores data in little-endian format. ๐
-msmall-data-limit=N
Specifies the maximum size in bytes of global and static variables that can be placed into the small data area. Using the small data area can lead to smaller and faster code, BUT the area is limited and it's up to you to make sure it doesn't overflow ๐ฌ
When the small data area is used, one of the RX's registers (usually "r13") is reserved to point to this area, so the compiler can't use it anymore. That could make your code slower and/or bigger if variables get pushed onto the stack instead of being held in that register ๐
Note: common variables (uninitialized variables) 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 is NOT enabled by default at higher optimization levels (-O2 etc.) because of the potentially detrimental effects of reserving a register. You'll have to experiment and figure out whether it helps your program ๐ฌ See the description of the -mpid option for how the actual register that holds the small data area pointer gets chosen.
-msim -mno-sim
Use the simulator runtime. The default is to use the libgloss board-specific runtime. ๐งช
-mas100-syntax -mno-as100-syntax
When generating assembler output, use a syntax that's compatible with Renesas's AS100 assembler. This syntax can also be handled by the GAS assembler, but it has some restrictions, so it isn't generated by default ๐
-mmax-constant-size=N
Specifies the maximum size, in bytes, of a constant that can be used as an operand in an RX instruction. The RX instruction set does allow constants up to 4 bytes long, but a longer value means a longer instruction. So sometimes it's actually beneficial to restrict the size of constants used in instructions. Constants that are too big get placed into a constant pool and referenced via register indirection ๐ง
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. Linker relaxation is when the linker tries to shrink your program by finding shorter versions of various instructions. โ๏ธ Disabled by default.
-mint-register=N
Specifies the number of registers to reserve for fast interrupt handler functions. The value N can be between 0 and 4. A value of 1 means register "r13" is reserved for the exclusive use of fast interrupt handlers. A value of 2 reserves "r13" and "r12". A value of 3 reserves "r13", "r12" and "r11", and a value of 4 reserves "r13" through "r10". A value of 0, the default, doesn't reserve any registers ๐ฆ
-msave-acc-in-interrupts
Specifies that interrupt handler functions should preserve the accumulator register. This is only necessary if normal code might use the accumulator, for example because it does 64-bit multiplications. The default is to ignore the accumulator, because that makes the interrupt handlers faster โก
-mpid -mno-pid
Enables the generation of position independent data. When enabled, any access to constant data is done via an offset from a base address held in a register. This lets the location of constant data be figured out at run time without the executable needing to be relocated, which is a huge win for embedded apps with tight memory constraints ๐ Data that can be modified isn't affected by this option.
Note: using this feature reserves a register (usually "r13") for the constant data base address. That can make your code slower and/or bigger, especially in complicated functions ๐ญ
Which register ends up holding the constant data base address depends on whether -msmall-data-limit and/or -mint-register are enabled. Starting with "r13" and working downwards, registers get allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. So it's possible for the small data area register to be "r8" if both -mint-register=4 and -mpid are specified on the command line ๐งฉ
By default this feature is not enabled. You can restore the default with the -mno-pid command-line option ๐
-mno-warn-multiple-fast-interrupts -mwarn-multiple-fast-interrupts
Prevents GCC from issuing a warning if it finds more than one fast interrupt handler while compiling a file. The default is to issue a warning for each extra fast interrupt handler found, because the RX only supports one such interrupt ๐จ
-mallow-string-insns -mno-allow-string-insns
Enables or disables the use of the string manipulation instructions "SMOVF", "SCMPU", "SMOVB", "SMOVU", "SUNTIL" "SWHILE" and also the "RMPA" instruction. These instructions may prefetch data, which isn't safe to do when accessing an I/O register. (See section 12.2.7 of the RX62N Group User's Manual for more information.) โ ๏ธ
Okay so the RX string instructions are ON by default ๐, but here's the tea: GCC can't reliably spot every time a string instruction pokes an I/O register ๐, so it can't switch them off automatically. That means it's on you, bestie, to pass -mno-allow-string-insns if your program touches I/O space ๐ซถ.
When they're enabled, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. When they're not, it defines __RX_DISALLOW_STRING_INSNS__ instead โจ.
-mjsr,-mno-jsrโ Use only (or not only)JSRinstructions to call functions ๐. This is the move when your code size goes past the reach ofBSRinstructions ๐ฆ. Heads up:-mno-jsrdoesn't mean "never useJSR" ๐ โโ๏ธ. It just means any type of branch is fair game ๐ .
Note: The generic GCC command-line option-ffixed-reghas special significance to the RX port when it's used with theinterruptfunction attribute ๐ฅ. That attribute marks a function meant to handle fast interrupts โก. GCC makes sure it only usesr10,r11,r12and/orr13, and only when the normal use of those registers has been restricted with-ffixed-regor-mint-register๐ซถ.
โจ S/390 and zSeries Options โจ
These are the -m options for the S/390 and zSeries architecture ๐ง.
-mhard-float,-msoft-floatโ Use (or don't use) the hardware floating-point instructions and registers for floating-point math ๐ข. With-msoft-float, the functions inlibgcc.ado the floating-point work instead ๐ ๏ธ. With-mhard-float, GCC generates IEEE floating-point instructions ๐. This is the default ๐.-mhard-dfp,-mno-hard-dfpโ Use (or don't use) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐. With-mno-hard-dfp, the functions inlibgcc.ahandle decimal-floating-point operations instead. With-mhard-dfp, GCC 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 thelong doubletype ๐. A size of 64 bits makeslong doublethe same asdouble๐. This is the default โจ.-mbackchain,-mno-backchainโ Store (or don't store) the address of the caller's frame as a backchain pointer in the callee's stack frame ๐. A backchain may be needed for debugging with tools that don't understand DWARF call frame information ๐ต๏ธโโ๏ธ. With-mno-packed-stackin effect, the backchain pointer lives at the bottom of the stack frame ๐ . With-mpacked-stackin effect, the backchain goes 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 ๐ค. But using the backchain for debugging usually means the whole binary needs to be built with -mbackchain ๐ญ. Also, the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported ๐. If you want to build a Linux kernel, use -msoft-float ๐ซถ.
The default is to not maintain the backchain ๐ โโ๏ธ.
-mpacked-stack,-mno-packed-stackโ Use (or don't use) the packed stack layout ๐ฆ. With-mno-packed-stack, the compiler uses all the fields of the 96/160 byte register save area only for their default purpose, so unused fields still eat stack space ๐ค. With-mpacked-stack, register save slots are densely packed at the top of the save area, and unused space gets reused for other stuff ๐ง . Way more efficient with the stack space ๐ . However, 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 generated with -mpacked-stack is call-compatible with code generated with -mno-packed-stack โ
. Now, some non-FSF releases of GCC 2.95 for S/390 or zSeries generated code that uses the stack frame backchain at run time, not just for debugging ๐ฌ. That code is NOT call-compatible with code compiled with -mpacked-stack ๐ซ. Also, the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported ๐. To build a Linux kernel, use -msoft-float ๐ซถ.
The default is to not use the packed stack layout ๐ โโ๏ธ.
-msmall-exec,-mno-small-execโ Generate (or don't generate) code that uses thebrasinstruction for subroutine calls ๐. This only works reliably if the total executable size doesn't go over 64k ๐, so be careful ๐ฌ. The default is thebasrinstruction instead, which doesn't have that limit ๐.-m64,-m31โ With-m31, GCC generates code compliant with the GNU/Linux for S/390 ABI ๐งฉ. With-m64, it generates code compliant with the GNU/Linux for zSeries ABI ๐. This lets GCC generate 64-bit instructions, which is the big win ๐ฅ. For the s390 targets the default is-m31, while the s390x targets default to-m64๐.-mzarch,-mesaโ With-mzarch, GCC generates code using the instructions available on z/Architecture ๐ฆ. With-mesa, it uses the instructions available on ESA/390 ๐ฐ๏ธ. Note that-mesais not possible with-m64๐ โโ๏ธ. When generating code compliant with the GNU/Linux for S/390 ABI, the default is-mesa. When generating code compliant with the GNU/Linux for zSeries ABI, the default is-mzarch๐.-mhtm,-mno-htmโ The-mhtmoption turns on a set of builtins that use instructions from the transactional execution facility, introduced with the IBM zEnterprise EC12 machine generation ๐ง. These are part of the S/390 System z Built-in Functions ๐ง.-mhtmis enabled by default when you use-march=zEC12โจ.-mvx,-mno-vxโ With-mvx, GCC generates code using the instructions from the vector extension facility, introduced with the IBM z13 machine generation ๐. This option changes the ABI for some vector type values when it comes to alignment and calling conventions โ ๏ธ. If vector type values are used in an ABI-relevant context, a GAS.gnu_attributecommand gets added to mark the resulting binary with the ABI it used ๐ท๏ธ.-mvxis enabled by default when you use-march=z13๐.-mzvector,-mno-zvectorโ The-mzvectoroption turns on vector language extensions and builtins, using instructions from the vector extension facility introduced with the IBM z13 machine generation ๐ . It adds support forvectoras a keyword to define vector type variables and arguments ๐. Heads up:vectoris only available when GNU extensions are enabled ๐. It won't be expanded when you request strict standard compliance, e.g. with-std=c99๐ซ. On top of the GCC low-level builtins,-mzvectoralso enables a set of builtins added for compatibility with AltiVec-style implementations like Power and Cell ๐ง. To use these builtins, you need to include the header filevecintrin.h๐.-mzvectoris disabled by default ๐ โโ๏ธ.-mmvcle,-mno-mvcleโ Generate (or don't generate) code using themvcleinstruction for block moves ๐. With-mno-mvcle, it uses anmvcloop instead. This is the default unless you're optimizing for size ๐.-mdebug,-mno-debugโ Print (or don't print) extra debug information while compiling ๐. The default is to not print debug information ๐ โโ๏ธ.-march=cpu-typeโ Generate code that runs on cpu-type, which is the name of a system representing a certain processor type ๐ฅ๏ธ. Possible values for cpu-type arez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12,z15/arch13, andnative๐. The default is-march=z900๐.
Choosing native as the cpu type picks the best architecture option for the host processor ๐ง . -march=native has no effect if GCC doesn't recognize the processor ๐คทโโ๏ธ.
-mtune=cpu-typeโ Tune everything applicable in the generated code to cpu-type, except for the ABI and the set of available instructions ๐๏ธ. The list of cpu-type values is the same as for-march๐. The default is whatever value 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 specifying-mtpf-trace๐.-mfused-madd,-mno-fused-maddโ Generate code that uses (or doesn't use) the floating-point multiply and accumulate instructions โ๏ธโ. These are generated by default if hardware floating point is used ๐.-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 have to be a real problem when the program runs ๐ซถ. It's meant to catch functions that most probably cause a stack overflow ๐ฑ. It's super useful in environments with a limited stack size, e.g. 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 ๐.-mstack-guard=stack-guard,-mstack-size=stack-sizeโ okay so these two are a package deal ๐ง With them on, the S/390 back end slips extra instructions into the function prologue that set off a trap when the stack reachesstack-guardbytes above thestack-sizemark. Heads up, the stack on S/390 grows downward ๐, so that's the direction it's watching. If you leave outstack-guard, GCC picks the smallest power of 2 that's bigger than the compiled function's frame size ๐ข These are built for debugging stack overflow problems ๐ต๏ธโโ๏ธ The extra code adds only a little overhead, so you can use it on production-like systems without a big performance hit ๐ The values have to be exact powers of 2, andstack-sizehas to be bigger thanstack-guardwithout going over 64k. To be efficient, the extra code assumes the stack starts at an address aligned to thestack-sizevalue. And-mstack-guardonly works together with-mstack-size, bestie ๐ซถ-mhotpatch=pre-halfwords,post-halfwordsโ if hotpatch is turned on, every function in the compilation unit gets a "hot-patching" prologue โจ The function label gets prepended withpre-halfwordsworth of two-byte NOP instructions (max1000000). After the label,2 * post-halfwordsbytes get tacked on, using the largest NOP-like instructions the architecture allows (max1000000).- If both arguments are zero, hotpatching is disabled ๐ โโ๏ธ
- You can override this for individual functions with the
"hotpatch"attribute ๐ฅ
๐ Score Options ๐
These options are defined for Score implementations:
-mebโ compile for big-endian mode. This is the default ๐-melโ compile for little-endian mode ๐-mnhwloopโ disable generation of"bcnz"instructions ๐-mulsโ enable generation of unaligned load and store instructions ๐ง-mmacโ enable the use of multiply-accumulate instructions. These are disabled by default ๐-mscore5โ specify SCORE5 as the target architecture โญ-mscore5uโ specify SCORE5U as the target architecture โญ-mscore7โ specify SCORE7 as the target architecture. This is the default ๐-mscore7dโ specify 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 an FPU, or for a SH2a-FPU in a way that the floating-point unit isn't 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โ generate code for SH4-200 in such a way that the floating-point unit is not used ๐-m4-200-singleโ generate code for SH4-200, assuming the floating-point unit is in single-precision mode by default ๐-m4-200-single-onlyโ generate code for SH4-200 in such a way that no double-precision floating-point operations are used ๐-m4-300โ generate code for SH4-300 ๐-m4-300-nofpuโ generate code for SH4-300 in such a way that the floating-point unit is not used ๐-m4-300-singleโ generate code for SH4-300 in such a way that no double-precision floating-point operations are used ๐-m4-300-single-onlyโ generate code for SH4-300 in such a way that no double-precision floating-point operations are used ๐-m4-340โ generate code for SH4-340 (no MMU, no FPU) ๐ง-m4-500โ generate code for SH4-500 (no FPU). It passes-isa=sh4-nofputo the assembler ๐ง-m4a-nofpuโ generate code for the SH4al-dsp, or for a SH4a in such a way that the floating-point unit is not used ๐-m4a-single-onlyโ generate code for the SH4a in such a way that no double-precision floating-point operations are used ๐-m4a-singleโ generate code for the SH4a, assuming the floating-point unit is in single-precision mode by default ๐-m4aโ generate code for the SH4a ๐-m4alโ same as-m4a-nofpu, except that it implicitly passes-dspto the assembler. GCC doesn't generate any DSP instructions at the moment ๐-mbโ compile code for the processor in big-endian mode ๐-mlโ compile code for the processor in little-endian mode ๐-mdalignโ align doubles at 64-bit boundaries. Heads up, this changes the calling conventions, so some functions from the standard C library won't work unless you recompile them first with-mdalign๐จ
Standard C library functions break with -mdalign unless you recompile the library first, so don't skip that step, bestie ๐
-mrelaxโ shorten some address references at link time, when possible. This uses the linker option-relaxโก-mbigtableโ use 32-bit offsets in"switch"tables. The default is 16-bit offsets ๐-mbitopsโ enable the use of bit manipulation instructions on SH2A ๐-mfmovdโ enable the use of the instruction"fmovd". Check-mdalignfor alignment constraints ๐-mrenesasโ comply with the calling conventions defined by Renesas ๐-mno-renesasโ comply with the calling conventions GCC used before the Renesas conventions were available. This is the default for all targets of the SH toolchain ๐-mnomacsaveโ mark the"MAC"register as call-clobbered, even if-mrenesasis given ๐ซถ-mieee,-mno-ieeeโ control the IEEE compliance of floating-point comparisons, which affects how cases where the result of a comparison is unordered get handled ๐ง- By default
-mieeeis implicitly enabled. - If
-ffinite-math-onlyis enabled,-mno-ieeeis implicitly set, which gives you faster floating-point greater-equal and less-equal comparisons โก - The implicit settings can be overridden by specifying either
-mieeeor-mno-ieee๐
- By default
-minline-ic_invalidateโ inline code that invalidates instruction cache entries after setting up nested function trampolines. This option 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 the
"icbi"instruction, and-musermodeis not in effect, the inlined code manipulates the instruction cache address array directly with an associative write.
- If the selected code generation option doesn't allow the
This needs privileged mode at run time, and it also fails if the cache line had been mapped via the TLB and has become unmapped ๐ญ
-misizeโ dump instruction size and location in the assembly code ๐-mpadstructโ this option is deprecated ๐ชฆ It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI.
Deprecated and incompatible with the SH ABI, so please don't reach for this one, bestie ๐ โโ๏ธ
-matomic-model=modelโ sets the model of atomic operations and additional parameters as a comma-separated list. For details on the atomic built-in functions, see__atomic Builtins. These models and parameters are supported:noneโ disable compiler-generated atomic sequences and emit library calls for atomic operations. This is the default if the target is not"sh*-*-linux*"๐ซsoft-gusaโ generate 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 SH3* or SH4*. When the target is SH4A, this option also partially uses the hardware atomic instructions"movli.l"and"movco.l"to create more efficient code, unlessstrictis specified ๐ธsoft-tcbโ generate software atomic sequences that use a variable in the thread control block. This is a variation of the gUSA sequences that can also be used on SH1* and SH2* targets. The generated sequences need extra support from the interrupt/exception handling code and are only suitable for single-core systems. When using this model, thegbr-offset=parameter has to be specified as well ๐งsoft-imaskโ generate software atomic sequences that temporarily disable interrupts by setting"SR.IMASK = 1111". This model only works when the program runs in privileged mode, and it's only suitable for single-core systems. Extra support from the interrupt/exception handling code is not required. This model is enabled by default when the target is"sh*-*-linux*"and SH1* or SH2* ๐hard-llcsโ generate 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- or 16-bit variable access is 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. Extra support from the interrupt/exception handling code of the system is not required for this model ๐
gbr-offset=โ okay so this one sets the byte offset of the variable inside the thread control block structure, and the generated atomic sequences use that spot ๐ It only matters when the soft-tcb model is selected. For every other model it gets ignored ๐ฆ The value has to be an integer multiple of four and fall somewhere in the range0-1020โจstrictโ this one stops you from mixing multiple atomic models, even when they'd normally be compatible ๐ โโ๏ธ The compiler only makes atomic sequences for the model you specified, and nothing else ๐
-mtasโ this makes the compiler generate thetas.bopcode for__atomic_test_and_set๐ฅ Heads up, though: depending on your hardware and software setup, this can tank overall performance because of the operand cache line flushes thattas.bbrings along ๐ญ On multi-core SH4A processors,tas.bhas to be used with caution, since it can cause data corruption with certain cache configurations ๐-mprefergotโ when you're generating position-independent code, this emits function calls through the Global Offset Table instead of the Procedure Linkage Table ๐ธ-musermode,-mno-usermodeโ these decide whether the compiler is allowed to generate privileged mode code ๐-mno-usermodesays no, and-musermodesays yes ๐ Specifying-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode ๐ซถ-musermodeis the default when the target issh*-*-linux*๐ If the target is SH1* or SH2*,-musermodedoes nothing at all, because those chips have no user mode ๐ฅ-multcost=numberโ sets the cost the compiler assumes for a multiply insn โจ-mdiv=strategyโ picks the division strategy used for integer division operations ๐งฎ Thestrategycan be one of these:call-div1โ calls a library function that uses the single-step division instructiondiv1to do the math ๐ Dividing by zero gives an unspecified result and doesn't trap ๐ This is the default except for SH4, SH2A, and SHcompact.call-fpโ calls a library function that does the operation in double precision floating point ๐ฆ Dividing by zero causes a floating-point exception โ ๏ธ This is the default for SHcompact with an FPU. If you specify this for targets without a double precision FPU, it falls back tocall-div1๐call-tableโ calls a library function that uses a lookup table for small divisors and thediv1instruction with case distinction for larger divisors ๐ง Dividing by zero gives an unspecified result and doesn't trap ๐ This is the default for SH4. If you specify this for targets without dynamic shift instructions, it defaults tocall-div1instead ๐
If you don't specify a division strategy, the compiler picks the default based on the current target ๐ฏ For SH2A, the default is to use the divs and divu instructions instead of library function calls ๐ฅ
-maccumulate-outgoing-argsโ reserves space once for outgoing arguments in the function prologue, instead of around each call ๐ท This is generally great for performance and size ๐ It's also needed for unwinding, so the stack frame doesn't get changed around conditional code ๐ซถ-mdivsi3_libfunc=nameโ sets the name of the library function used for 32-bit signed division toname๐ This only changes the name used in the call division strategies. The compiler still expects the same sets of input, output, and clobbered registers as if this option weren't there ๐ง-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers ๐ A fixed register is one the register allocator isn't allowed to use, which is super useful when you're compiling kernel code ๐ฅ๏ธ A register range is written as two registers separated by a dash, and you can list multiple ranges separated by commas โจ-mbranch-cost=numโ tells the compiler to assumenumis the cost of a branch instruction ๐ Higher numbers make the compiler try harder to generate branch-free code when it's possible ๐ If you don't specify it, the value is picked based on the processor type you're compiling for ๐-mzdcbranch,-mno-zdcbranchโ these tell the compiler whether zero displacement conditional branch instructionsbtandbfare fast ๐โโ๏ธ With-mzdcbranch, the compiler prefers zero displacement branch code sequences โจ It's enabled by default for SH4 and SH4A ๐ฆ You can explicitly turn it off with-mno-zdcbranch๐ โโ๏ธ-mcbranch-force-delay-slotโ forces the use of delay slots for conditional branches, which stuffs the delay slot with anopif a suitable instruction can't be found ๐ซ This option is disabled by default ๐ You can turn it on to work around hardware bugs found in the original SH7055 ๐ง-mfused-madd,-mno-fused-maddโ these decide whether the code uses the floating-point multiply and accumulate instructions โ๏ธโ They're generated by default when hardware floating point is used ๐ฅ The machine-dependent-mfused-maddoption is now mapped to the machine-independent-ffp-contract=fastoption, and-mno-fused-maddis mapped to-ffp-contract=off๐ค-mfsca,-mno-fscaโ allow or disallow the compiler from emitting thefscainstruction for sine and cosine approximations ๐ The option-mfscahas to be used together with-funsafe-math-optimizations๐ง It's enabled by default for SH4A ๐ธ Using-mno-fscadisables sine and cosine approximations even if-funsafe-math-optimizationsis in effect ๐ โโ๏ธ-mfsrra,-mno-fsrraโ allow or disallow the compiler from emitting thefsrrainstruction for reciprocal square root approximations ๐งฎ The option-mfsrrahas to be used together with-funsafe-math-optimizationsand-ffinite-math-only๐ It's enabled by default for SH4A ๐ Using-mno-fsrradisables reciprocal square root approximations even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect ๐ซ-mpretend-cmoveโ prefers zero-displacement conditional branches for conditional move instruction patterns ๐ This can make the code run faster on the SH4 processor ๐๏ธ-mfdpicโ generates code using the FDPIC ABI ๐ง
โจ Solaris 2 Options โจ
These -m options are supported on Solaris 2 ๐
-mclear-hwcapโ tells the compiler to remove the hardware capabilities generated by the Solaris assembler ๐งน You only need this when object files use ISA extensions the current machine doesn't support, but they check at runtime whether or not to use them ๐คทโโ๏ธ-mimpure-textโ used alongside-shared, this tells the compiler not to pass-z textto the linker when linking a shared object ๐ With it, you can link position-dependent code into a shared object ๐ณ
Okay, real talk bestie:-mimpure-textsuppresses the "relocations remain against allocatable but non-writable sections" linker error message ๐ But the necessary relocations trigger copy-on-write, so the shared object isn't actually shared across processes ๐ญ Instead of using-mimpure-text, you should compile all your source code with-fpicor-fPIC๐
These switches are supported in addition to the above on Solaris 2 ๐
-pthreadsโ this is just a synonym for-pthread๐ซถ
โจ SPARC Options โจ
These -m options are supported on the SPARC ๐ป
-mno-app-regs,-mapp-regsโ specify-mapp-regsto generate output using global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐ Like global register 1, each of global registers 2 through 4 is then treated as an allocable register that gets clobbered by function calls ๐ฅน This is the default ๐
To be fully SVR4 ABI-compliant (with some performance loss), specify -mno-app-regs ๐ซ You should compile libraries and system software with this option ๐ฆ
-mflat,-mno-flatโ with-mflat, the compiler doesn't generate save/restore instructions and uses a "flat" or single register window model ๐ช This model is compatible with the regular register window model ๐ค The local registers and the input registers (0--5) are still treated as "call-saved" registers and get saved on the stack as needed ๐ฅ With-mno-flat(the default), the compiler generates save/restore instructions, except for leaf functions ๐ This is the normal operating mode โจ-mfpu,-mhard-floatโ generate output containing floating-point instructions ๐ฅ This is the default ๐-mno-fpu,-msoft-floatโ generate output containing library calls for floating point ๐
Warning, bestie: the requisite libraries aren't 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 all of a program with this option ๐งต In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work ๐
-mhard-quad-floatโ generate output containing quad-word (long double) floating-point instructions ๐-msoft-quad-floatโ generate output containing library calls for quad-word (long double) floating-point instructions โ๏ธ The functions called are the ones specified in the SPARC ABI, and this is the default ๐
As of this writing, there are no SPARC implementations with hardware support for 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 the trap handler overhead, this is much slower than calling the ABI library routines, so -msoft-quad-float is the default ๐ท
-mno-unaligned-doubles,-munaligned-doublesโ assume that doubles have 8-byte alignment ๐ This is the default โจ
Okay so the end of the -munaligned-doubles bit is lowkey important ๐ With it on, GCC only assumes doubles have 8-byte alignment if they're tucked inside another type or have an absolute address. Otherwise it goes with 4-byte alignment. This helps avoid some rare compatibility drama with code from other compilers ๐ซถ but it's not the default, because it costs performance, especially for floating-point code ๐
-muser-mode,-mno-user-modeโ no code that can only run in supervisor mode ๐ This only matters for thecasainstruction that gets emitted for the LEON3 processor. And yep, this is the default ๐-mfaster-structs,-mno-faster-structsโ with-mfaster-structs, the compiler assumes structures have 8-byte alignment ๐โโ๏ธ That lets it use pairs oflddandstdinstructions for copies in structure assignment, instead of twice as manyldandstpairs.
๐จ The catch: this changed alignment directly violates the SPARC ABI. So it's only meant for targets where the developer knows and accepts that their code isn't fully in line with the ABI rules. Use with care, bestie ๐ญ
-mstd-struct-return,-mno-std-struct-returnโ with the first one, the compiler adds checking code to functions that return structures or unions, so it can catch size mismatches between the two sides of a function call, as per the 32-bit ABI ๐ The default is-mno-std-struct-return. This option does nothing in 64-bit mode ๐ โโ๏ธ-mlra,-mno-lraโ turns on Local Register Allocation โจ This has been the default for SPARC since GCC 7, so if you want the old Reload behaviour, you have to pass-mno-lra๐ฐ๏ธ-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for the machine typecpu_type๐ง The supported values arev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,leon5,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8.
Native Solaris and GNU/Linux toolchains also accept native, which picks the best architecture option for the host processor ๐ฅ๏ธ If GCC doesn't recognize the processor, -mcpu=native just does nothing ๐คทโโ๏ธ
Default instruction scheduling parameters get used for the values that pick an architecture rather than an implementation. Those are v7, v8, sparclite, sparclet and v9.
Here's the full lineup of each architecture and its implementations ๐
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3,leon5sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless it's been configured otherwise), GCC makes code for the V7 variant of SPARC ๐ธ With -mcpu=cypress, it also optimizes for the Cypress CY7C602 chip, which was used in the SPARCStation/SPARCServer 3xx series. This is also a good fit for the older SPARCStation 1, 2, IPX and so on ๐ฆ
With -mcpu=v8, GCC makes code for the V8 variant. The only difference from V7 code is that the compiler emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not SPARC-V7 โจ With -mcpu=supersparc, it also optimizes for the SuperSPARC chip, found in the SPARCStation 10, 1000 and 2000 series ๐ค
With -mcpu=sparclite, GCC makes code for the SPARClite variant ๐ This adds the integer multiply, integer divide step and scan ("ffs") instructions that exist in SPARClite but not SPARC-V7. With -mcpu=f930, it also optimizes for the Fujitsu MB86930, which is the original SPARClite and has no FPU. With -mcpu=f934, it optimizes for the Fujitsu MB86934, the more recent SPARClite that does have an FPU ๐ฅ
With -mcpu=sparclet, GCC makes code for the SPARClet variant ๐ง This adds the integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions that exist in SPARClet but not SPARC-V7. With -mcpu=tsc701, it also optimizes for the TEMIC SPARClet chip.
With -mcpu=v9, GCC makes code for the V9 variant ๐ This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers, and conditional move instructions. With -mcpu=ultrasparc, it optimizes for the Sun UltraSPARC I/II/IIi chips. With -mcpu=ultrasparc3, it optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips. With -mcpu=niagara, it optimizes for Sun UltraSPARC T1 chips. With -mcpu=niagara2, it optimizes for Sun UltraSPARC T2 chips. With -mcpu=niagara3, it optimizes for Sun UltraSPARC T3 chips. With -mcpu=niagara4, it optimizes for Sun UltraSPARC T4 chips. With -mcpu=niagara7, it optimizes for Oracle SPARC M7 chips. And with -mcpu=m8, it optimizes for Oracle M8 chips ๐
-mtune=cpu_typeโ sets the instruction scheduling parameters for the machine typecpu_type, but doesn't touch the instruction set or register set the way-mcpu=cpu_typedoes ๐ฏ
You can use the same values as -mcpu=cpu_type, but only the ones that pick out a particular CPU implementation are actually useful here. Those are cypress, supersparc, hypersparc, leon, leon3, leon3v7, leon5, f930, f934, sparclite86x, tsc701, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7 and m8. On native Solaris and GNU/Linux toolchains, native works here too ๐
-mv8plus,-mno-v8plusโ generates code for the SPARC-V8+ ABI ๐งฉ The difference from the V8 ABI is that the global and out registers are treated as 64 bits wide. This is turned on by default on Solaris in 32-bit mode for all SPARC-V9 processors โจ-mvis,-mno-visโ makes GCC take advantage of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mno-vis.-mvis2,-mno-vis2โ takes advantage of version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐ผ The default is-mvis2when you're targeting a CPU that supports these instructions, like UltraSPARC-III and later. Setting-mvis2also sets-mvis.-mvis3,-mno-vis3โ takes advantage of version 3.0 of the VIS extensions ๐ The default is-mvis3when targeting a CPU that supports these, like niagara-3 and later. Setting-mvis3also sets-mvis2and-mvis.-mvis4,-mno-vis4โ takes advantage of version 4.0 of the VIS extensions ๐ฆ The default is-mvis4when targeting a CPU that supports these, like niagara-7 and later. Setting-mvis4also sets-mvis3,-mvis2and-mvis.-mvis4b,-mno-vis4bโ takes advantage of version 4.0 of the VIS extensions, plus the extra VIS instructions introduced in the Oracle SPARC Architecture 2017 ๐ช The default is-mvis4bwhen targeting a CPU that supports them, like m8 and later. Setting-mvis4balso sets-mvis4,-mvis3,-mvis2and-mvis.-mcbcond,-mno-cbcondโ takes advantage of the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ The default is-mcbcondwhen targeting a CPU that supports them, like Niagara-4 and later.-mfmaf,-mno-fmafโ takes advantage of the UltraSPARC Fused Multiply-Add Floating-point instructions ๐งฎ The default is-mfmafwhen targeting a CPU that supports them, like Niagara-3 and later.-mfsmuld,-mno-fsmuldโ takes advantage of the Floating-point Multiply Single to Double (FsMULd) instruction ๐ซ The default is-mfsmuldwhen targeting a CPU that supports the architecture versions V8 or V9 with an FPU, except-mcpu=leon.-mpopc,-mno-popcโ takes advantage of the UltraSPARC Population Count instruction ๐ข The default is-mpopcwhen targeting a CPU that supports it, like Niagara-2 and later.-msubxc,-mno-subxcโ takes advantage of the UltraSPARC Subtract-Extended-with-Carry instruction ๐ The default is-msubxcwhen targeting 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 matches 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 on top of everything above, and they work on SPARC-V9 processors in 64-bit environments ๐ธ
-m32,-m64โ generates code for a 32-bit or 64-bit environment ๐ The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits.-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 has to sit within 2GB of the text segment.
medany: okay, the Medium/Anywhere code model ๐ gives you 64-bit addresses and lets programs be linked anywhere in memory ๐บ๏ธ. The catch is that the text and data segments each have to be less than 2GB, and the data segment must sit within 2GB of the text segment ๐ (strict, but it's giving organized).embmedany: the Medium/Anywhere code model for embedded systems ๐ง has 64-bit addresses, and the text and data segments must each be less than 2GB. Both can start anywhere in memory, which gets decided at link time ๐. The global register%g4points to the base of the data segment ๐. Programs are statically linked, and PIC is not supported ๐ โโ๏ธ, so no cap, that's a hard no.-mmemory-model=mem-model: sets the memory model that's in force on the processor to one of these ๐ :default: the default memory model for the processor and operating system.rmo: Relaxed Memory Orderpso: Partial Store Ordertso: Total Store Ordersc: Sequential Consistency
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, and they 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. That offset has to be added back whenever stack frame references get made ๐ง . This is the default in 64-bit mode. Otherwise, GCC assumes no such offset is present ๐ฆ.
โจ Options for System V โจ
These extra options are available on System V Release 4 so they can play nicely with 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: refrains from adding".ident"directives to the output file. This is the default ๐.-YP,dirs: searches the directories dirs, and no others, for libraries specified with-l๐.-Ym,dir: looks in the directory dir to 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 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 (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: does not optimize (or does optimize) basic blocks that use the same index pointer 4 or more times to copy the pointer into the"ep"register, and use the shorter"sld"and"sst"instructions โจ. The-mepoption is on by default if you optimize.-mno-prolog-function,-mprolog-function: does not use (or does use) external functions to save and restore registers at the prologue and epilogue of a function ๐ซง. The external functions are slower, but they use less code space if more than one function saves the same number of registers. The-mprolog-functionoption is on by default if you optimize.-mspace: tries to make the code as small as possible ๐ค. At present, this just turns on the-mepand-mprolog-functionoptions.-mtda=n: puts static or global variables whose size is n bytes or less into the tiny data area that register"ep"points to ๐ธ. The tiny data area can hold up to 256 bytes in total, with 128 bytes for byte references.-msda=n: puts static or global variables whose size is n bytes or less into the small data area that register"gp"points to ๐. The small data area can hold up to 64 kilobytes.-mzda=n: puts static or global variables whose size is n bytes or less into the first 32 kilobytes of memory ๐งธ.-mv850: specifies that the target processor is the V850 ๐ฏ.-mv850e3v5: specifies that the target processor is the V850E3V5. The preprocessor constant"__v850e3v5__"is defined if this option is used ๐.-mv850e2v4: specifies that the target processor is the V850E3V5. This is an alias for the-mv850e3v5option ๐ฆ.-mv850e2v3: specifies that the target processor is the V850E2V3. The preprocessor constant"__v850e2v3__"is defined if this option is used ๐.-mv850e2: specifies that the target processor is the V850E2. The preprocessor constant"__v850e2__"is defined if this option is used ๐.-mv850e1: specifies that the target processor is the V850E1. The preprocessor constants"__v850e1__"and"__v850e__"are defined if this option is used ๐ฅ.-mv850es: specifies that the target processor is the V850ES. This is an alias for the-mv850e1option ๐ซถ.-mv850e: specifies that the target processor is the V850E. The preprocessor constant"__v850e__"is defined if this option is used ๐.
If none of -mv850, -mv850e, -mv850e1, -mv850e2, -mv850e2v3, or -mv850e3v5 are defined, then a default target processor is chosen and the relevant __v850*__ preprocessor constant is defined ๐คทโโ๏ธ.
The preprocessor constants "__v850" and "__v851__" are always defined, no matter which processor variant is the target ๐.
-mdisable-callt,-mno-disable-callt: this option suppresses generation of the"CALLT"instruction for the v850e, v850e1, v850e2, v850e2v3, and v850e3v5 flavors of the v850 architecture ๐ โโ๏ธ.
This option is enabled by default when the RH850 ABI is in use (see -mrh850-abi), and disabled by default when the GCC ABI is in use. If "CALLT" instructions are being generated, then the C preprocessor symbol "__V850_CALLT__" is defined ๐
.
-mrelax,-mno-relax: passes on (or does not pass on) the-mrelaxcommand-line option to the assembler ๐งต.-mlong-jumps,-mno-long-jumps: disables (or re-enables) the generation of PC-relative jump instructions ๐ฆ.-msoft-float,-mhard-float: disables (or re-enables) the generation of hardware floating point instructions ๐ข. This option only matters when the target architecture is V850E2V3 or higher. If hardware floating point instructions are being generated, then the C preprocessor symbol"__FPU_OK__"is defined. Otherwise, the symbol"__NO_FPU__"is defined.-mloop: enables the use of the e3v5LOOPinstruction ๐. The use of this instruction is not enabled by default when the e3v5 architecture is selected, because its use is still experimental ๐งช.-mrh850-abi,-mghs: enables support for the RH850 version of the V850 ABI. This is the default ๐. With this version of the ABI, the following rules apply:- Integer sized structures and unions are returned via a memory pointer rather than a register.
- Large structures and unions (more than 8 bytes in size) are passed by value.
- Functions are aligned to 16-bit boundaries.
- The
-m8byte-aligncommand-line option is supported. - The
-mdisable-calltcommand-line option is enabled by default. The-mno-disable-calltcommand-line option is not supported.
When this version of the ABI is enabled, the C preprocessor symbol "__V850_RH850_ABI__" is 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__" is defined ๐.
-m8byte-align,-mno-8byte-align: enables support for"double"and"long long"types to be aligned on 8-byte boundaries ๐. The default is to restrict the alignment of all objects to at most 4 bytes. When-m8byte-alignis in effect, the C preprocessor symbol"__V850_8BYTE_ALIGN__"is defined.-mbig-switch: generates code suitable for big switch tables ๐ท. Only use this option if the assembler or linker complains about out-of-range branches within a switch table ๐ญ.-mapp-regs: makesr2andr5get used in the code the compiler generates. This setting 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 (likeaobleqand so on) that the Unix assembler for the VAX can't handle across long ranges ๐.-mgnu: does output those jump instructions, on the assumption that the GNU assembler is being used ๐ง.-mg: outputs code for G-format floating-point numbers instead of D-format ๐ข.-mlra,-mno-lra: enables Local Register Allocation. This is still experimental for the VAX, so by default the compiler uses standard reload ๐งช.
โจ Visium Options โจ
-mdebug: a program that performs 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โ okay so, a program that does file I/O and is meant to run on the simulator needs to be linked with option. ๐ That makes the linker pull inlibc.aandlibsim.aโจ-mfpu,-mhard-floatโ generates code with floating-point instructions. This is the default, so you're already getting it ๐-mno-fpu,-msoft-floatโ generates code that uses library calls for floating-point instead ๐ซถ
โ ๏ธ-msoft-floatchanges the calling convention in the output file, so it only slaps if you compile your whole program with it. You also need to compilelibgcc.a(the library that comes with GCC) with-msoft-floatfor this to work ๐ญ
-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for the machine type cpu_type. The supported values aremcm,gr5andgr6๐ธmcmis just a synonym forgr5, kept around for backward compatibility ๐- By default (unless it was 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 cpu_type, but it does not touch 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 from"main". The default is to return POSIX-style condition (e.g. error) codes โจ-mdebug-main=prefixโ flags the first routine whose name starts with prefix as the main routine for the debugger ๐-mmalloc64โ defaults to 64-bit memory allocation routines ๐-mpointer-size=sizeโ sets the default size of pointers. The possible options for size are32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers ๐ซง- The
nooption disables"pragma pointer_size", so heads up ๐
- The
๐ฆ VxWorks Options
The options in this section are defined for all VxWorks targets. Options specific to the target hardware are listed with the other options for that target ๐ธ
-mrtpโ GCC can generate code for both VxWorks kernels and real time processes (RTPs). This option switches from the former to the latter. It also defines the preprocessor macro"__RTP__"๐-non-staticโ links an RTP executable against shared libraries instead of static libraries. The options-staticand-sharedcan also be used for RTPs, and-staticis the default ๐ง-Bstatic,-Bdynamicโ these get passed down to the linker. They're defined for compatibility with Diab ๐-Xbind-lazyโ enables lazy binding of function calls. This option is equivalent to-Wl,-z,nowand is defined for compatibility with Diab ๐ฆ-Xbind-nowโ disables lazy binding of function calls. This option is the default and is defined for compatibility with Diab ๐
๐ x86 Options
These -m options are defined for the x86 family of computers ๐ป
-march=cpu-typeโ generates instructions for the machine type cpu-type. Unlike-mtune=cpu-type, which only tunes the generated code for the specified cpu-type,-march=cpu-typelets GCC generate code that may not run at all on processors other than the one you pointed at ๐. Specifying-march=cpu-typeimplies-mtune=cpu-type, except where noted otherwise ๐ซถ
The choices for cpu-type are:
nativeโ selects the CPU to generate code for at compilation time by figuring out the processor type of the compiling machine. Using-march=nativeenables all instruction subsets supported by the local machine, so the result might not run on different machines ๐. Using-mtune=nativeproduces code optimized for the local machine under the constraints of the selected instruction set ๐ฅx86-64โ a generic CPU with 64-bit extensions ๐x86-64-v2,x86-64-v3,x86-64-v4โ these select the corresponding micro-architecture level from the x86-64 psABI. On ABIs other than the x86-64 psABI, they select the same CPU features that the x86-64 psABI documents for that particular micro-architecture level ๐. Since thesecpu-typevalues don't have a corresponding-mtunesetting, using-marchwith them enables generic tuning. If you want specific tuning, use the-mtune=other-cpu-typeoption with an appropriate other-cpu-type value ๐i386โ the original Intel i386 CPU ๐ฆi486โ the Intel i486 CPU. (No scheduling is implemented for this chip.) ๐i586,pentiumโ 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, the Pentium Pro instruction set is used, so the code runs on all i686 family chips. When used with-mtune, it has the same meaning asgeneric๐ฆpentium2โ Intel Pentium II CPU, based on the Pentium Pro core with MMX and FXSR instruction set support ๐pentium3,pentium3mโ Intel Pentium III CPU, based on the Pentium Pro core with MMX, FXSR and SSE instruction set support ๐pentium-mโ Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE, SSE2 and FXSR instruction set support. Used by Centrino notebooks ๐ปpentium4,pentium4mโ Intel Pentium 4 CPU with MMX, SSE, SSE2 and FXSR instruction set support ๐ฅprescottโ an improved version of the Intel Pentium 4 CPU with MMX, SSE, SSE2, SSE3 and FXSR instruction set support ๐ธnoconaโ an improved version of the Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and FXSR instruction set support ๐ซถcore2โ Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, CX16, SAHF and FXSR instruction set support โnehalemโ Intel Nehalem CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF and FXSR instruction set support โญwestmereโ Intel Westmere CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR and PCLMUL instruction set support ๐sandybridgeโ Intel Sandy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE and PCLMUL instruction set support ๐ivybridgeโ Intel Ivy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND and F16C instruction set support ๐งhaswellโ Intel Haswell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE, RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE and HLE instruction set support ๐ฆbroadwellโ Intel Broadwell CPU 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 and PREFETCHW instruction set support ๐skylakeโ Intel Skylake 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 and SGX 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, CX16, SAHF, FXSR, PCLMUL, PREFETCHW and RDRND instruction set support ๐goldmontโ Intel Goldmont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW, RDRND, AES, SHA, RDSEED, XSAVE, XSAVEC, XSAVES, XSAVEOPT, CLFLUSHOPT and FSGSBASE instruction set support โจgoldmont-plusโ Intel Goldmont Plus CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW, RDRND, AES, SHA, RDSEED, XSAVE, XSAVEC, XSAVES, XSAVEOPT, CLFLUSHOPT, FSGSBASE, PTWRITE, RDPID and SGX instruction set support ๐tremontโ Intel Tremont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, PCLMUL, PREFETCHW, RDRND, AES, SHA, RDSEED, XSAVE, XSAVEC, XSAVES, XSAVEOPT, CLFLUSHOPT, FSGSBASE, PTWRITE, RDPID, SGX, CLWB, GFNI-SSE, MOVDIRI, MOVDIR64B, CLDEMOTE and WAITPKG instruction set support ๐ซงknlโ Intel Knight's Landing 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, AVX512PF, AVX512ER, AVX512F, AVX512CD and PREFETCHWT1 instruction set support ๐
knm๐ธ Okay bestie, this is Intel Knights Mill! It has 64-bit extensions plusMOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,CX16,SAHF,FXSR,AVX,XSAVE,PCLMUL,FSGSBASE,RDRND,F16C,AVX2,BMI,BMI2,LZCNT,FMA,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AVX512PF,AVX512ER,AVX512F,AVX512CDandPREFETCHWT1,AVX5124VNNIW,AVX5124FMAPSandAVX512VPOPCNTDQinstruction set support ๐ โจskylake-avx512๐ฆ This is the Intel Skylake Server CPU, and it's giving 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,CLWB,AVX512VL,AVX512BW,AVX512DQandAVX512CDinstruction set support ๐ฅcannonlake๐ง Next up is the Intel Cannonlake Server CPU, which brings 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,AVX512IFMAandSHAinstruction set support ๐icelake-client๐ This is the Intel Icelake Client CPU! Lowkey so complete: 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,RDPIDandAVX512VPOPCNTDQinstruction set support ๐icelake-server๐ The Intel Icelake Server CPU is the server sibling, and it has 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,WBNOINVDandCLWBinstruction set support ๐ซถcascadelake๐ Meet the Intel Cascadelake CPU! It comes 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,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CDandAVX512VNNIinstruction set support ๐ธcooperlake๐ This is the Intel cooperlake CPU (lowercase in the original, and I'm keeping it that way for the vibe check), 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,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VNNIandAVX512BF16instruction set support โจtigerlake๐ฆ The Intel Tigerlake CPU is giving 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,MOVDIRI,MOVDIR64B,CLWB,AVX512VP2INTERSECTandKEYLOCKERinstruction set support ๐ฅsapphirerapids๐ The Intel sapphirerapids CPU (also lowercase, slay anyway) comes 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,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VNNI,AVX512BF16,MOVDIRI,MOVDIR64B,AVX512VP2INTERSECT,ENQCMD,CLDEMOTE,PTWRITE,WAITPKG,SERIALIZE,TSXLDTRK,UINTR,AMX-BF16,AMX-TILE,AMX-INT8,AVX-VNNIandAVX512FP16instruction set support ๐alderlake๐ง The Intel Alderlake CPU is the one with a shorter, cute list: 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPT,FSGSBASE,PTWRITE,RDPID,SGX,GFNI-SSE,CLWB,MOVDIRI,MOVDIR64B,CLDEMOTE,WAITPKG,ADCX,AVX,AVX2,BMI,BMI2,F16C,FMA,LZCNT,PCONFIG,PKU,VAES,VPCLMULQDQ,SERIALIZE,HRESET,KL,WIDEKLandAVX-VNNIinstruction set support ๐rocketlake๐ธ Last Intel one, the Intel Rocketlake CPU! It has 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,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,PKU,AVX512VBMI,AVX512IFMA,SHA,AVX512VNNI,GFNI,VAES,AVX512VBMI2,VPCLMULQDQ,AVX512BITALG,RDPIDandAVX512VPOPCNTDQinstruction set support ๐k6๐ This is the AMD K6 CPU, withMMXinstruction set support. Simple and iconic ๐k6-2,k6-3๐ฆ These are the improved versions of the AMD K6 CPU, and they come withMMXand3DNow!instruction set support โจathlon,athlon-tbird๐ The AMD Athlon CPU, which hasMMX,3dNOW!, enhanced3DNow!and SSE prefetch instructions support ๐ฅathlon-4,athlon-xp,athlon-mp๐ These are the improved AMD Athlon CPUs. They haveMMX,3DNow!, enhanced3DNow!and full SSE instruction set support, so they're a whole mood ๐k8,opteron,athlon64,athlon-fx๐ธ These are processors based on the AMD K8 core withx86-64instruction set support, including the AMD Opteron, Athlon 64, and Athlon 64 FX processors. Okay, and this supersetsMMX,SSE,SSE2,3DNow!, enhanced3DNow!and 64-bit instruction set extensions, so it's a full package ๐ซถk8-sse3,opteron-sse3,athlon64-sse3๐ These are the improved versions of the AMD K8 cores, and the big upgrade here isSSE3instruction set support โจamdfam10,barcelona๐ง These are CPUs based on AMD Family 10h cores withx86-64instruction set support. Lowkey iconic: this supersetsMMX,SSE,SSE2,SSE3,SSE4A,3DNow!, enhanced3DNow!,ABMand 64-bit instruction set extensions ๐bdver1๐ These are CPUs based on AMD Family 15h cores withx86-64instruction 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๐ฆ This is an AMD Family 15h core based CPU withx86-64instruction 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๐ Another AMD Family 15h core based CPU withx86-64instruction 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๐ Still AMD Family 15h core based, withx86-64instruction 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๐ซถ These are AMD Family 17h core based CPUs withx86-64instruction set support. They supersede... well, they supersetsBMI,BMI2,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT, and 64-bit instruction set extensions ๐ฅznver2๐ธ AMD Family 17h core based CPUs withx86-64instruction set support, and this one supersetsBMI,BMI2,CLWB,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCLMUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT,RDPID,WBNOINVD, and 64-bit instruction set extensions ๐znver3๐ AMD Family 19h core based CPUs withx86-64instruction set support, and yep, it's a whole upgrade. 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 โจbtver1๐ง These are CPUs based on AMD Family 14h cores withx86-64instruction set support. They supersetsMMX,SSE,SSE2,SSE3,SSSE3,SSE4A,CX16,ABMand 64-bit instruction set extensions ๐btver2๐ฆ CPUs based on AMD Family 16h cores withx86-64instruction set support! This includesMOVBE,F16C,BMI,AVX,PCLMUL,AES,SSE4.2,SSE4.1,CX16,ABM,SSE4A,SSSE3,SSE3,SSE2,SSE,MMXand 64-bit instruction set extensions ๐winchip-c6๐ซถ This is the IDT WinChip C6 CPU, which gets dealt with in the same way asi486with additionalMMXinstruction set support ๐ธwinchip2๐ This is the IDT WinChip 2 CPU, which is handled the same way asi486, with additionalMMXand3DNow!instruction set support โจc3๐ The VIA C3 CPU hasMMXand3DNow!instruction set support. Quick heads-up, bestie: no scheduling is implemented for this chip ๐c3-2๐ The VIA C3-2 (Nehemiah/C5XL) CPU hasMMXandSSEinstruction set support. No scheduling is implemented for this chip either ๐งc7๐ The VIA C7 (Esther) CPU comes withMMX,SSE,SSE2andSSE3instruction set support. Again, no scheduling is implemented for this chip ๐ฆsamuel-2๐ The VIA Eden Samuel 2 CPU hasMMXand3DNow!instruction set support. No scheduling is implemented for this chip, so keep that in mind ๐nehemiah๐ The VIA Eden Nehemiah CPU hasMMXandSSEinstruction set support. And yup, no scheduling is implemented for this chip ๐estherโ ๐ VIA Eden Esther CPU with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x2โ โจ VIA Eden X2 CPU with x86-64, MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x4โ ๐ฅ VIA Eden X4 CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 instruction set support. (No scheduling is implemented for this chip.)nanoโ ๐ฆ Generic VIA Nano CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-1000โ ๐ธ VIA Nano 1xxx CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-2000โ ๐ VIA Nano 2xxx CPU with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-3000โ ๐ง VIA Nano 3xxx CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x2โ ๐ VIA Nano Dual Core CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x4โ ๐ VIA Nano Quad Core CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)geodeโ ๐ AMD Geode embedded processor with MMX and 3DNow! instruction set support.
-mtune=cpu-typeโ ๐ฏ Okay so this one tunes everything that can be tuned in the generated code tocpu-type, except for the ABI and the set of available instructions. Picking a specific cpu-type schedules things nicely for that particular chip, but GCC will never generate code that can't run on the default machine type unless you also use a-march=cpu-typeoption. For example, if GCC is configured fori686-pc-linux-gnu, then-mtune=pentium4makes code tuned for Pentium 4 that still runs on i686 machines. ๐- The choices for cpu-type are the same as for
-march. In addition,-mtunesupports 2 extra choices for cpu-type: genericโ โจ Produces code optimized for the most common IA32/AMD64/EM64T processors. If you know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=generic. But if you don't know exactly what CPU your users will have, this is the one you want. ๐ซถ- As new processors hit the marketplace, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generation controlled by this option will shift to match whatever processors are most common when that version of GCC is released. ๐
- There is no
-march=genericoption, because-marchindicates the instruction set the compiler can use, and there's no generic instruction set that applies to all processors.-mtune, on the other hand, indicates the processor (or, in this case, collection of processors) the code is optimized for. ๐ง intelโ ๐ Produces 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-mtuneor-marchoption instead of-mtune=intel. But if you want your application to perform better on both Haswell and Silvermont, this is the one. ๐ฅ- 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 generation controlled by this option will reflect the most current Intel processors at the time that version of GCC is released. โญ
- There is no
-march=inteloption, because-marchindicates the instruction set the compiler can use, and there's no common instruction set that applies to all processors.-mtuneindicates the processor (or, in this case, collection of processors) the code is optimized for. ๐
- The choices for cpu-type are the same as for
-mcpu=cpu-typeโ ๐ A deprecated synonym for-mtune. Use-mtuneinstead, bestie.-mfpmath=unitโ ๐งฎ Generates floating-point arithmetic for the selectedunit. The choices forunitare:387โ ๐ธ Uses the standard 387 floating-point coprocessor that's on the majority of chips, and emulates it otherwise. Code compiled with this option runs almost everywhere. The temporary results are computed in 80-bit precision instead of the precision specified by the type, so you can get slightly different results compared to most other chips. See-ffloat-storefor a more detailed description. This is the default choice for non-Darwin x86-32 targets.sseโ ๐ Uses scalar floating-point instructions from the SSE instruction set. This is supported by Pentium III and newer chips, and in the AMD line by Athlon-4, Athlon XP and Athlon MP chips. The earlier version of SSE only supports single-precision arithmetic, so double and extended-precision arithmetic still get done using 387. A later version, present only in Pentium 4 and AMD x86-64 chips, supports double-precision arithmetic too.- For the x86-32 compiler, you must use
-march=cpu-type,-msseor-msse2switches to enable SSE extensions and make this option effective. For the x86-64 compiler, these extensions are enabled by default. - The resulting code should be considerably faster in most cases and avoid the numerical instability problems of 387 code, but it may break some existing code that expects temporaries to be 80 bits. ๐
- This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and the default choice for x86-32 targets with the SSE2 instruction set when
-ffast-mathis enabled.
- For the x86-32 compiler, you must use
sse,387,sse+387,bothโ ๐งช Attempts to use both instruction sets at once. This effectively doubles the amount of available registers, and on chips with separate execution units for 387 and SSE, the execution resources too. Use this option with care! It's still experimental, because the GCC register allocator doesn't model separate functional units well, which can lead to unstable performance. ๐
-masm=dialectโ ๐ Outputs assembly instructions using the selected dialect. This also affects which dialect is used for basic"asm"and extended"asm". Supported choices (in dialect order) areattorintel. The default isatt. Darwin does not supportintel.-mieee-fp,-mno-ieee-fpโ ๐ข Controls whether or not the compiler uses IEEE floating-point comparisons. These correctly handle the case where the result of a comparison is unordered.-m80387,-mhard-floatโ ๐ Generates output containing 80387 instructions for floating point.-mno-80387,-msoft-floatโ ๐ซง Generates output containing library calls for floating point.
Warning: the requisite libraries are not part of GCC. Normally the facilities of the machine's usual C compiler are used, but this cannot be done directly in cross-compilation. You must 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 be emitted even if -msoft-float is used.
-mno-fp-ret-in-387โ ๐ Do not use the FPU registers for return values of functions. The usual calling convention has functions return values of types"float"and"double"in an FPU register, even if there is no FPU. The idea is that the operating system should emulate an FPU. The option-mno-fp-ret-in-387causes such values to be returned in ordinary CPU registers instead.-mno-fancy-math-387โ ๐งฎ Some 387 emulators don't support the"sin","cos"and"sqrt"instructions for the 387. Specify this option to avoid generating those instructions. This option is overridden when-marchindicates that the target CPU always has an FPU, so the instruction doesn't need emulation. These instructions are not generated unless you also use the-funsafe-math-optimizationsswitch.-malign-double,-mno-align-doubleโ ๐ Controls whether GCC aligns"double","long double", and"long long"variables on a two-word boundary or a one-word boundary. Aligning"double"variables on a two-word boundary produces code that runs somewhat faster on a Pentium, at the expense of more memory. On x86-64,-malign-doubleis enabled by default.
Warning: if you use the -malign-double switch, structures containing the above types are aligned differently than the published application binary interface specifications for the x86-32, and they are not binary compatible with structures in code compiled without that switch. ๐
-m96bit-long-double,-m128bit-long-doubleโ ๐ These switches control the size of the"long double"type. The x86-32 application binary interface specifies the size to be 96 bits, so-m96bit-long-doubleis the default in 32-bit mode. Modern architectures (Pentium and newer) prefer"long double"to be aligned to an 8- or 16-byte boundary. In arrays or structures conforming to the ABI, that isn't possible. So specifying-m128bit-long-doublealigns"long double"to a 16-byte boundary by padding it with an additional 32-bit zero.- In the x86-64 compiler,
-m128bit-long-doubleis the default choice, since its ABI specifies that"long double"is aligned on a 16-byte boundary. ๐ - Notice that neither of these options enables any extra precision over the x87 standard of 80 bits for a
"long double".
- In the x86-64 compiler,
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containing"long double"variables, as well as modifying the function calling convention for functions taking"long double". Hence they are not binary-compatible with code compiled without that switch. ๐ฅบ
-mlong-double-64,-mlong-double-80,-mlong-double-128โ okay so these three decide how big thelong doubletype is ๐โจ.-mlong-double-64makeslong doubleexactly the same asdouble๐ธ (that's the default for the 32-bit Bionic C library ๐ค).-mlong-double-128makes it equivalent to__float128๐, which is the default for the 64-bit Bionic C library ๐ .-mlong-double-80is the third one in the lineup.
Warning: if you override the default for your target ABI, the size of structures and arrays holdinglong doublevariables changes ๐, and so does the calling convention for functions that takelong double. So your code won't be binary-compatible with stuff compiled without that switch ๐.
-malign-data=typeโ this one is all about how GCC lines up your variables in memory ๐๐. The type can becompat, which uses the increased alignment that GCC 4.8 and earlier used ๐ฐ๏ธ;abi, which uses the alignment the psABI specifies ๐; orcacheline, which bumps the alignment to match the cache line size ๐ง.compatis the default, so you're already set unless you say otherwise ๐.-mlarge-data-threshold=thresholdโ when you've got-mcmodel=mediumturned on, any data object bigger than threshold gets tossed into the large data section ๐. The value has to be the same for every object linked into the binary โ ๏ธ, and it defaults to65535โจ.-mrtdโ a whole different function-calling convention, babe ๐ฆ. Functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments on the way out. That saves one instruction in the caller, since the caller doesn't have to pop anything ๐งน.
You can make just one function use this sequence with the stdcall function attribute ๐ฏ, and you can override -mrtd for a specific function with the cdecl attribute ๐.
Warning: this calling convention is NOT the one normally used on Unix ๐ซ, so don't use it if you need to call libraries compiled with the Unix compiler ๐ญ.
Also, you MUST provide function prototypes for every function that takes a variable number of arguments (printf included) ๐ซถ, or GCC generates incorrect code for those calls. And if you call a function with too many arguments, you get seriously incorrect code ๐. (Normally, extra arguments are harmlessly ignored, so this one is a plot twist ๐.)
-mregparm=numโ controls how many registers get used to pass integer arguments ๐ง . By default, no registers are used for arguments, and at most 3 registers can be used. You can control this for one specific function with theregparmfunction attribute ๐.
Warning: if you use this switch and num is nonzero, every module must be built with the same value ๐จ, including any libraries, the system libraries, and the startup modules. No exceptions, bestie ๐ค.
-msseregparmโ uses SSE register passing conventions forfloatanddoublearguments and return values ๐ฅ. You can control this for a specific function with thesseregparmfunction attribute ๐ฆ.
Warning: same deal here ๐ฌ. If you use this switch, you must build all modules with the same value, including any libraries, the system libraries, and the 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 if you need to stay compatible with existing code made by those older compiler versions or older versions of GCC ๐.-mpc32,-mpc64,-mpc80โ set the 80387 floating-point precision to 32, 64, or 80 bits ๐ฏ. With-mpc32, the significands of floating-point results get rounded to 24 bits (single precision) ๐ฑ.-mpc64rounds them to 53 bits (double precision) ๐.-mpc80rounds them to 64 bits (extended double precision), and that's the default ๐. Once you use this option, higher-precision floating-point operations aren't available to the programmer unless you set the FPU control word explicitly ๐ ๏ธ.
Rounding to less than the default 80 bits can speed some programs up by 2% or more โก. BUT, some math libraries assume extended-precision (80-bit) floating-point operations are on by default ๐ฑ. Routines in those libraries could lose a ton of accuracy, usually through so-called "catastrophic cancellation", if you use this option to drop below extended precision ๐.
-mstackrealignโ realigns the stack at entry ๐ชโจ. On x86, this option generates an alternate prologue and epilogue that realigns the run-time stack if it's needed ๐ง. It lets legacy code that keeps 4-byte stack alignment play nicely with modern code that keeps 16-byte stack alignment for SSE compatibility ๐ซถ. You can also check out theforce_align_arg_pointerattribute, 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 it, the default is 4 (16 bytes or 128 bits) ๐.
Warning: when you're generating code for the x86-64 architecture with SSE extensions disabled, you can use -mpreferred-stack-boundary=3 to 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 limited resource ๐ฅฒ.
This option leads to wrong code when functions compiled with 16 byte stack alignment (like functions from a standard library) get called with a misaligned stack ๐. In that case, SSE instructions can cause misaligned memory access traps ๐ต. Variable arguments also get handled incorrectly for 16 byte aligned objects (including x87 long double and __int128), which gives wrong results ๐. So you MUST build all modules with -mpreferred-stack-boundary=3, including any libraries, the system libraries, and the startup modules ๐.
-mincoming-stack-boundary=numโ assumes the incoming stack is aligned to a 2 raised to num byte boundary ๐งญ. If you don't specify it, the one set by-mpreferred-stack-boundaryis used ๐.
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double), or you'll take some serious run-time performance hits ๐. On Pentium III, the Streaming SIMD Extension (SSE) data type __m128 may not work properly if it isn't 16-byte aligned ๐ฌ.
To make sure these values are aligned properly on the stack, the stack boundary has to be as aligned as the most demanding value stored on it ๐๏ธ. Every function also has to be generated so it keeps the stack aligned ๐ซก. That means calling a function compiled with a higher preferred stack boundary from a function compiled with a lower one will most likely misalign the stack ๐ฅ. For libraries that use callbacks, it's recommended to always use the default setting ๐.
This extra alignment eats up extra stack space and usually increases code size ๐. If your code is sensitive to stack usage, like embedded systems and operating system kernels, you might want to lower the preferred alignment to -mpreferred-stack-boundary=2 ๐ธ.
- The big ISA squad โ these switches turn on the instruction sets listed below, so GCC can use them in your generated code ๐. Each one has a matching
-mno-option to turn it off ๐ซ. Here's the whole lineup, no skipping ๐ :
-mmmx
-msse
-msse2
-msse3
-mssse3
-msse4
-msse4a
-msse4.1
-msse4.2
-mavx
-mavx2
-mavx512f
-mavx512pf
-mavx512er
-mavx512cd
-mavx512vl
-mavx512bw
-mavx512dq
-mavx512ifma
-mavx512vbmi
-msha
-maes
-mpclmul
-mclflushopt
-mclwb
-mfsgsbase
-mptwrite
-mrdrnd
-mf16c
-mfma
-mpconfig
-mwbnoinvd
-mfma4
-mprfchw
-mrdpid
-mprefetchwt1
-mrdseed
-msgx
-mxop
-mlwp
-m3dnow
-m3dnowa
-mpopcnt
-mabm
-madx
-mbmi
-mbmi2
-mlzcnt
-mfxsr
-mxsave
-mxsaveopt
-mxsavec
-mxsaves
-mrtm
-mhle
-mtbm
-mmwaitx
-mclzero
-mpku
-mavx512vbmi2
-mavx512bf16
-mavx512fp16
-mgfni
-mvaes
-mwaitpkg
-mvpclmulqdq
-mavx512bitalg
-mmovdiri
-mmovdir64b
-menqcmd
-muintr
-mtsxldtrk
-mavx512vpopcntdq
-mavx512vp2intersect
-mavx5124fmaps
-mavx512vnni
-mavxvnni
-mavx5124vnniw
-mcldemote
-mserialize
-mamx-tile
-mamx-int8
-mamx-bf16
-mhreset
-mkl
-mwidekl
These turn on the MMX, SSE, SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA, AES, PCLMUL, CLFLUSHOPT, CLWB, FSGSBASE, PTWRITE, RDRND, F16C, FMA, PCONFIG, WBNOINVD, FMA4, PREFETCHW, RDPID, PREFETCHWT1, RDSEED, SGX, XOP, LWP, 3DNow!, enhanced 3DNow!, POPCNT, ABM, ADX, BMI, BMI2, LZCNT, FXSR, XSAVE, XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2, GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16, ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE, UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI, AVX512FP16, or CLDEMOTE extended instruction sets ๐.
The same extensions also show up as built-in functions ๐งฉ. Check out x86 Built-in Functions for the details on 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), look at -mfpmath=sse ๐ฅ.
Heads up: GCC depresses SSEx instructions when -mavx is used ๐ง. Instead, it generates new AVX instructions, or AVX equivalents for all the SSEx instructions, when it needs them ๐ฆ.
These options let GCC use these extended instructions in the 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 right flags ๐ซถ. In particular, the file with the CPU detection code should be compiled WITHOUT these options ๐.
-mdump-tune-featuresโ okay bestie, this one makes GCC dump the names of the x86 performance tuning features and their default settings ๐ง You can use those names with-mtune-ctrl=feature-list.-mtune-ctrl=feature-listโ the fine-grain control knob for x86 code generation features โจfeature-listis a comma-separated list of feature names, and you can look them up with-mdump-tune-features. A feature turns on if it has no^in front of it, and turns off if it does.
๐ This one is really meant for GCC developers. Using it may lead to code paths that testing never covers, and that can potentially result in compiler ICEs or runtime errors. Proceed with caution, bestie.
-mno-defaultโ turns off all the 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 autoincrement or autodecrement mode. The ABI says DF gets cleared on function entry, but some operating systems don't clear it in their exception dispatchers. So the handler can run with DF set, and string instructions end up going the wrong direction ๐ญ This option can be enabled by default on 32-bit x86 targets if you configure GCC with the--enable-cldconfigure option. In that case, you can suppresscldgeneration with the-mno-cldcompiler option.-mvzeroupperโ emits avzeroupperinstruction before control flow leaves the function, which minimises the AVX to SSE transition penalty and removes unnecessaryzeroupperintrinsics ๐ฆ-mprefer-avx128โ the auto-vectorizer uses 128-bit AVX instructions instead of 256-bit AVX instructions ๐-mprefer-vector-width=optโ uses opt-bit vector width in instructions instead of the default on the selected platform ๐-mmove-max=bitsโ sets the maximum number of bits that can be moved from memory to memory efficiently to bits. The valid values are128,256and512.-mstore-max=bitsโ sets the maximum number of bits that can be stored to memory efficiently to bits. The valid values are128,256and512.noneโ no extra limitations on GCC beyond what the selected platform already 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 for compare-and-exchange on 16-byte aligned 128-bit objects ๐ This is iconic for atomic updates of data structures bigger than one machine word. The compiler uses it to implement__syncbuiltins. However,__atomicbuiltins operating on 128-bit integers always go through a library call.-msahfโ enablesSAHFinstructions in 64-bit code ๐ Early Intel Pentium 4 CPUs with Intel 64 support, before the Pentium 4 G1 step in December 2005, didn't have theLAHFandSAHFinstructions that AMD64 supports. They're load and store instructions, respectively, for certain status flags. In 64-bit mode,SAHFgets used to optimise thefmod,drem, andremainderbuilt-in functions; see Other Builtins for details.-mmovbeโ uses themovbeinstruction to implement__builtin_bswap32and__builtin_bswap64โจ-mshstkโ enables the shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ก๏ธ-mcrc32โ makes the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32siand__builtin_ia32_crc32digenerate thecrc32machine instruction ๐-mmwaitโ makes the built-in functions__builtin_ia32_monitorand__builtin_ia32_mwaitgenerate themonitorandmwaitmachine instructions ๐ง-mrecipโ usesRCPSSandRSQRTSS(plus their vectorized versionsRCPPSandRSQRTPS) with an extra Newton-Raphson step for precision, instead ofDIVSSandSQRTSS(and their vectorized versions) for single-precision floating-point arguments ๐ฅ These instructions only get generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math. The throughput of the sequence beats the non-reciprocal instruction, but its precision can drop by up to 2 ulp (i.e. the inverse of 1.0 equals0.99999994).- GCC already implements
1.0f/sqrtf(x)in terms ofRSQRTSS(orRSQRTPS) with-ffast-math(or the option combination above), so it doesn't need-mrecipfor that. - GCC also emits the sequence 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 it doesn't need-mrecipthere either.
- GCC already implements
-mrecip=optโ controls which reciprocal estimate instructions may be used ๐ opt is a comma-separated list, and any option can be preceded by a!to invert it.allโ enables all estimate instructions.defaultโ enables the default instructions, equivalent to-mrecip.noneโ disables all estimate instructions, equivalent to-mno-recip.divโ enables the approximation for scalar division.vec-divโ enables the approximation for vectorized division.sqrtโ enables the approximation for scalar square root.vec-sqrtโ enables the approximation for vectorized square root.- So, for example,
-mrecip=all,!sqrtenables all of the reciprocal approximations except for square root ๐ซถ
-mveclibabi=typeโ specifies the ABI type to use when vectorizing intrinsics with an external library ๐ธ The supportedtypevalues aresvmlfor the Intel short vector math library andacmlfor the AMD math core library. To use this option, both-ftree-vectorizeand-funsafe-math-optimizationshave to be enabled, and an SVML or ACML ABI-compatible library must be specified at link time.- With
-mveclibabi=svml, GCC currently emits calls tovmldExp2,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,vmlsAcosh4andvmlsAcos4for the corresponding function type. - With
-mveclibabi=acml, GCC currently emits calls to__vrd2_sin,__vrd2_cos,__vrd2_exp,__vrd2_log,__vrd2_log2,__vrd2_log10,__vrs4_sinf,__vrs4_cosf,__vrs4_expf,__vrs4_logf,__vrs4_log2f,__vrs4_log10fand__vrs4_powffor the corresponding function type.
- With
-mabi=nameโ generates code for the specified calling convention ๐ The permissible values aresysvfor the ABI used on GNU/Linux and other systems, andmsfor the Microsoft ABI. The default is the Microsoft ABI when targeting Microsoft Windows, and the SysV ABI on all other systems. You can control this for specific functions with the function attributesms_abiandsysv_abi.
-mforce-indirect-callโ forces all calls to functions to be indirect ๐ This is useful with Intel Processor Trace, since it gives more precise timing information for function calls.-mmanual-endbrโ inserts an ENDBR instruction at function entry only via thecf_checkfunction attribute ๐ฏ This is useful with-fcf-protection=branchto control ENDBR insertion at function entry.-mcall-ms2sysv-xloguesโ because of differences between the 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function must consider RSI, RDI and XMM6-15 as clobbered ๐ฎโ๐จ By default, the code that saves and restores these registers is emitted inline, which makes the prologues and epilogues pretty lengthy. With this option, the prologues and epilogues use stubs in the static portion of libgcc to do those saves and restores. That shrinks function size at the cost of a few extra instructions ๐ฆ-mtls-dialect=typeโ generates code to access thread-local storage using thegnuorgnu2conventions ๐งตgnuis the conservative default.gnu2is more efficient, but it may add compile- and run-time requirements that can't be satisfied on all systems.-mpush-args,-mno-push-argsโ use 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 better scheduling and fewer 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 thanks to 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 thread-safe exception handling must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT. When linking, it links in a special thread helper library,-lmingwthrd, which cleans up per-thread exception-handling data.-mms-bitfields,-mno-ms-bitfieldsโ enable or disable bit-field layout that's compatible with the native Microsoft Windows compiler ๐ช
Okay so, if "packed" gets slapped on a structure, or you use bit-fields, the Microsoft ABI might lay that struct out totally differently from how GCC normally does ๐ This matters a lot when you're passing packed data between GCC-compiled functions and the native Microsoft compiler, whether that's through a function call or as data in a file, because you might need to access either format ๐ซถ
This one is on by default for Microsoft Windows targets ๐ช You can also control it locally with variable or type attributes. Check out x86 Variable Attributes and x86 Type Attributes for the deets ๐
The Microsoft structure layout algorithm is pretty simple, except for bit-field packing. The padding and alignment of structure members, plus whether a bit-field can straddle a storage-unit boundary, are determined by these rules:
- Structure members are stored in the order they're declared. The first member sits at the lowest memory address and the last one sits at the highest ๐
- Every data object has an alignment requirement. For everything except structures, unions, and arrays, it's the smaller of the object's size and the current packing size (set with the "aligned" attribute or the "pack" pragma). For structures, unions, and arrays, it's the largest alignment requirement among their members. Every object gets an offset so that
offset % alignment_requirement == 0๐ - Adjacent bit-fields get packed into the same 1-, 2-, or 4-byte allocation unit if their integral types are the same size, and the next bit-field fits in the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit-fields ๐งฉ
๐ MSVC zero-length bit-fields ๐
Now for the zero-length bit-field drama ๐ MSVC interprets them in these ways:
1. If a zero-length bit-field is inserted between two bit-fields that would normally be coalesced, the bit-fields are not coalesced. Like this:
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 ๐
2. If a zero-length bit-field is inserted after a bit-field, "foo", and the alignment of the zero-length bit-field is greater than that of the member that follows it, "bar", then "bar" is aligned as the type of the zero-length bit-field. Check these out:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For t2, "bar" is placed at offset 2 instead of offset 1, so the size of t2 is 4. For t3, the zero-length bit-field doesn't affect the alignment of "bar" or, as a result, the size of the structure ๐ธ
Taking that into account, it's important to note the following:
- If a zero-length bit-field follows a normal bit-field, its type may affect the alignment of the whole structure. 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 can still affect the alignment of the structure:
struct
{
char foo : 6;
long : 0;
} t4;
Here, t4 takes up 4 bytes ๐
3. Zero-length bit-fields that follow non-bit-field members are ignored:
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes ๐ง
-mno-align-stringopsโ Don't align the destination of inlined string operations. This reduces code size and improves performance when the destination is already aligned but GCC doesn't know it ๐ซถ-minline-all-stringopsโ By default, GCC only inlines string operations when the destination is known to be aligned to at least a 4-byte boundary. This one enables more inlining and bigger code, and may speed up code that relies on fastmemcpyandmemsetfor short lengths. It also enables inline expansion ofstrlenfor all pointer alignments ๐ฅ-minline-stringops-dynamicallyโ For string operations of unknown size, use run-time checks with inline code for small blocks and a library call for large blocks โจ-mstringop-strategy=algโ Overrides the internal heuristic for picking the algorithm used to inline string operations. The allowed values foralgare:rep_byte,rep_4byte,rep_8byteโ expand using the i386repprefix of the specified sizebyte_loop,loop,unrolled_loopโ expand into an inline looplibcallโ always use a library call
-mmemcpy-strategy=strategyโ Overrides the internal heuristic that decides whether__builtin_memcpyshould be inlined and which inline algorithm to use when the expected copy size is known.strategyis a comma-separated list ofalg:max_size:dest_aligntriplets.algis one of the values from-mstringop-strategy, andmax_sizeis the biggest byte size thatalgis allowed to handle. The last triplet must havemax_sizeset to-1. Themax_sizevalues in the list must be in increasing order. The minimal byte size foralgis 0 for the first triplet, andmax_size + 1of the preceding range for every triplet after that ๐-mmemset-strategy=strategyโ Works like-mmemcpy-strategy=, except it controls__builtin_memsetexpansion ๐งฝ-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions. This skips the instructions that save, set up, and restore frame pointers, and frees up an extra register in leaf functions.-fomit-leaf-frame-pointerremoves the frame pointer for leaf functions too, but it might make debugging harder ๐-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ Controls whether TLS variables can be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer has to be added. Whether or not this is valid depends on the operating system, and on whether it maps the segment to cover the entire TLS area. For systems that use the GNU C Library, the default is on ๐ฆ-msse2avx,-mno-sse2avxโ Specifies that the assembler should encode SSE instructions with a VEX prefix. The option-mavxturns this on by default ๐-mfentry,-mno-fentryโ If profiling is active (-pg), put the profiling counter call before the prologue. Note: on x86 architectures, the attributems_hook_prologueisn't possible at the moment for-mfentryand-pg๐-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), generate a__mcount_locsection that contains pointers to each profiling call. This is useful for automatically patching and out calls ๐-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), generate the calls to the profiling functions as NOPs. This is useful when they should be patched in later, dynamically. This is likely only useful together with-mrecord-mcount๐-minstrument-return=typeโ Instruments function exit in-pg -mfentryinstrumented functions with a call to the specified function. This only instruments true returns ending withret, not sibling calls ending with a jump. Valid types arenone(don't instrument),call(generate a call to__return__), ornop5(generate a 5 byte nop) โญ-mrecord-return,-mno-record-returnโ Generates a__return_locsection pointing to all return instrumentation code ๐-mfentry-name=nameโ Sets the name of the__fentry__symbol called at function entry for-pg -mfentryfunctions ๐ง-mfentry-section=nameโ Sets the name of the section where-mrecord-mcountcalls get recorded (default__mcount_loc) ๐ฆ-mskip-rax-setup,-mno-skip-rax-setupโ When generating code for the x86-64 architecture with SSE extensions disabled,-mskip-rax-setupcan be used to skip setting up the RAX register when no variable arguments are passed in vector registers ๐ธ
Warning: The RAX register is used to avoid unnecessarily saving vector registers on the stack when passing variable arguments, so the impacts of this option are: callees may waste some stack space, misbehave, or jump to a random location. GCC 4.4 or newer don't have those issues, regardless of the RAX register value ๐
-m8bit-idiv,-mno-8bit-idivโ On some processors, like Intel Atom, 8-bit unsigned integer divide is way faster than 32-bit/64-bit integer divide. This option generates a run-time check. If both dividend and divisor are within the range of 0 to 255, 8-bit unsigned integer divide is used instead of 32-bit/64-bit integer divide ๐-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Split 32-byte AVX unaligned load and store ๐-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generates stack protection code using a canary atguard. Supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default). This option only has an effect when-fstack-protectoror-fstack-protector-allis specified ๐ก๏ธ
With that second choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset get to decide which segment register (%fs or %gs) acts as the base for reading the canary ๐, plus how far from that base to look. If you don't set them, you get whatever the relevant ABI says โจ.
-mgeneral-regs-onlyโ bestie, this one keeps the compiler on a short leash ๐ . It only uses general-purpose registers, so floating-point, vector, mask, and bound registers are all off the table.-mrelax-cmpxchg-loopโ this is lowkey genius ๐ง . It adds an early load and compare beforecmpxchg, and runspauseif the loaded value isn't the one you expected. That cuts down on excessive cache line bouncing, and it works for every atomic logic fetch builtin that builds a compare and swap loop ๐ฆ.-mindirect-branch=choiceโ this one changes how indirect calls and jumps get handled ๐. The default iskeep, which leaves them completely alone ๐ธ.thunkturns them into call and return thunks,thunk-inlineturns them into inlined call and return thunks, andthunk-externturns them into external call and return thunks that live in a separate object file. You can override this for one specific function with the function attribute"indirect_branch"๐.
โ ๏ธ-mcmodel=largedoesn't get along with-mindirect-branch=thunkor-mindirect-branch=thunk-extern, because the thunk function might not be reachable in the large code model. Be careful with that combo ๐.
Good news though: -mindirect-branch=thunk-extern plays nicely with -fcf-protection=branch, since the external thunk can be made to turn on control-flow checking ๐ซถ.
-mfunction-return=choiceโ same energy, but for function returns ๐ฆ. The default iskeep, which leaves returns unmodified ๐.thunkconverts function returns to call and return thunks,thunk-inlineconverts them to inlined call and return thunks, andthunk-externconverts them to external call and return thunks in a separate object file. Per function, you can control this with the function attribute"function_return"โจ.
โ ๏ธ The-mcmodel=largeflag clashes with-mfunction-return=thunkand-mfunction-return=thunk-externfor the same reason as before: the thunk might not be reachable in the large code model ๐.
Also, -mindirect-return=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐.
-mindirect-branch-registerโ this forces indirect calls and jumps to go through a register ๐ง.-mharden-sls=choiceโ this is your anti-speculation shield ๐ก๏ธ. It generates code to mitigate straight line speculation (SLS). The default isnone, which turns off all SLS hardening ๐ โโ๏ธ.returnturns it on for function returns,indirect-jmpturns it on for indirect jumps, andallturns on every bit of it ๐.-mindirect-branch-cs-prefixโ this one is kinda wild ๐คฏ. It adds a CS prefix tocallandjmpgoing to an indirect thunk, with the branch target inr8-r15registers. That makes the call and jmp instructions 6 bytes long, so they can be swapped at run-time forlfence; call *%r8-r15orlfence; jmp *%r8-r15๐.
These -m switches are supported on top of everything above for x86-64 processors in 64-bit environments ๐.
-m32โ targets a 32-bit environment ๐. It setsint,long, and pointer types to 32 bits, and generates code that runs on any i386 system ๐.-m64โ targets a 64-bit environment ๐. It setsintto 32 bits, whilelongand pointer types become 64 bits, and generates code for the x86-64 architecture. On Darwin, only-m64also turns off the-fno-picand-mdynamic-no-picoptions ๐.-mx32โ setsint,long, and pointer types to 32 bits, and still generates code for the x86-64 architecture ๐ฆ.-m16โ basically-m32, with one twist ๐งโโ๏ธ. It outputs the.code16gccassembly directive at the very start of the assembly output, so the binary can run in 16-bit mode ๐ฐ๏ธ.-miamcuโ generates code that conforms to the Intel MCU psABI ๐ง. It needs-m32turned on too, so don't forget that one ๐ญ.-mno-red-zoneโ this turns off the so-called "red zone" for x86-64 code ๐ โโ๏ธ. The red zone is mandated by the x86-64 ABI, and it's a 128-byte area beyond the stack pointer that signal or interrupt handlers don't touch ๐ธ. That means it can hold temporary data without adjusting the stack pointer. This flag disables that whole setup ๐ .-mcmodel=smallโ the small code model ๐ท. The program and its symbols have to be linked in the lower 2 GB of the address space, and pointers are 64 bits. Programs can be statically or dynamically linked. This is the default code model ๐.-mcmodel=kernelโ the kernel code model ๐ง. The kernel runs in the negative 2 GB of the address space. This model has to be used for Linux kernel code ๐.-mcmodel=mediumโ the medium model ๐. The program is linked in the lower 2 GB of the address space, and small symbols are placed there too. Symbols bigger than-mlarge-data-thresholdgo into large data or BSS sections, and they can live above 2GB. Programs can be statically or dynamically linked ๐ง.-mcmodel=largeโ the large model ๐. It makes no assumptions about addresses and sizes of sections, so it's the most chill about where things end up ๐.-maddress-mode=longโ generates code for long address mode ๐. This is only supported for 64-bit and x32 environments, and it's the default address mode for 64-bit environments โจ.-maddress-mode=shortโ generates code for short address mode ๐. This is only supported for 32-bit and x32 environments, and it's the default address mode for 32-bit and x32 environments ๐ซถ.-mneeded,-mno-neededโ these control whether theGNU_PROPERTY_X86_ISA_1_NEEDEDGNU property gets emitted for Linux targets ๐. That property tells you which micro-architecture ISA level the binary needs to run ๐.-mno-direct-extern-accessโ okay, this one's a bit technical but it matters ๐ง. Without-fpicor-fPIC, it always uses the GOT pointer to access external symbols. With-fpicor-fPIC, it treats access to protected symbols like local symbols. The default is-mdirect-extern-access๐.
โ ๏ธ Warning, bestie: shared libraries compiled with-mno-direct-extern-accessand executables compiled with-mdirect-extern-accessmight not be binary compatible if protected symbols are used in both the shared libraries and the executable ๐.
๐ธ x86 Windows Options ๐ธ
These extra options are available for Microsoft Windows targets ๐ช:
-mconsoleโ generates a console application by telling the linker to set the PE header subsystem type for console apps ๐ฅ๏ธ. It's available for Cygwin and MinGW targets, and it's on by default there ๐.-mdllโ available for Cygwin and MinGW ๐ฆ. It generates a DLL (a dynamic link library), which lets the compiler pick the right runtime startup object and entry point ๐ง.-mnop-fun-dllimportโ available for Cygwin and MinGW ๐. It makes the compiler ignore the"dllimport"attribute ๐ซ .-mthreadsโ available for MinGW targets ๐งต. It uses MinGW-specific thread support ๐ .-municodeโ available for MinGW-w64 targets ๐. It predefines theUNICODEpreprocessor macro and chooses Unicode-capable runtime startup code ๐.-mwin32โ available for Cygwin and MinGW ๐ช. It sets the typical Microsoft Windows predefined macros in the preprocessor, but it doesn't change which runtime library or startup code gets picked โจ.-mwindowsโ available for Cygwin and MinGW ๐ฎ. It generates a GUI application by having the linker set the PE header subsystem type appropriately ๐ช.-fno-set-stack-executableโ available for MinGW targets ๐. It stops the executable flag from being set for the stack used by nested functions. This is necessary for binaries running in kernel mode of Microsoft Windows, since the User32 API (used to set executable privileges) isn't available there ๐.-fwritable-relocated-rdataโ available for MinGW and Cygwin ๐ฆ. It puts relocated data from a read-only section into the".data"section. This is needed for older runtimes that don't support modifying".rdata"sections for pseudo-relocation ๐งธ.-mpe-aligned-commonsโ available for Cygwin and MinGW ๐ท. It 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 work with the simulator ๐ฎ.
๐ Xtensa Options ๐
These options are supported for Xtensa targets ๐:
-mconst16,-mno-const16โ enables or disables the use ofCONST16instructions for loading constant values ๐ข.CONST16isn't a standard option from Tensilica right now ๐. When it's enabled,CONST16gets used every time instead of the standardL32Rinstructions. It's only enabled by default ifL32Risn't available ๐.-mfused-madd,-mno-fused-maddโ enables or disables fused multiply/add and multiply/subtract instructions in the floating-point option ๐งฎ. This does nothing if the floating-point option isn't also turned on ๐ โโ๏ธ. Disabling them makes the compiler use separate instructions for the multiply and the add/subtract ๐งฉ. That's useful when you need strict IEEE 754-compliant results ๐ฏ, because fused instructions don't round the intermediate result, so they carry more bits of precision than the IEEE standard specifies ๐ค. Disabling them also means your program's output won't depend on whether the compiler can combine multiply and add/subtract operations ๐.-mserialize-volatile,-mno-serialize-volatileโ okay so this one is aboutvolatilememory references. When it's on, GCC slidesMEMWinstructions in front of them to guarantee sequential consistency ๐โจ. The default is-mserialize-volatile, and if you want theMEMWinstructions gone, use-mno-serialize-volatile๐-mforce-no-picโ for targets like GNU/Linux where all user-mode Xtensa code has to be position-independent code (PIC), this one turns PIC off just for compiling kernel code ๐ง-mtext-section-literals,-mno-text-section-literalsโ these two control how literal pools get treated ๐ธ The default is-mno-text-section-literals, which puts literals in their own section in the output file. This lets the literal pool live in data RAM/ROM, and it lets the linker merge literal pools from separate object files to kill redundant literals and improve code size, which is so iconic ๐ With-mtext-section-literals, the literals get interspersed in the text section so they stay as close as possible to their references. That might be necessary for large assembly files. Literals for each function get placed right before that function ๐ฆ-mauto-litpools,-mno-auto-litpoolsโ also about literal pools ๐ The default is-mno-auto-litpools, which puts literals in a separate section in the output file unless-mtext-section-literalsis used. With-mauto-litpools, the assembler does the interspersing in the text section. GCC doesn't emit explicit.literaldirectives, and it loads literals into registers withMOVIinstructions instead ofL32R, so the assembler can do relaxation and place literals wherever they need to go ๐ซถ This option lets the assembler make several literal pools per function and assemble very big functions, which might not be possible with-mtext-section-literals๐ญ-mtarget-align,-mno-target-alignโ when this is enabled, GCC tells the assembler to auto-align instructions to cut down on branch penalties, at the cost of some code density ๐ The assembler tries to widen density instructions to align branch targets and the instructions right after 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 touch auto-aligned instructions likeLOOP, which the assembler always aligns, either by widening density instructions or by inserting NOP instructions ๐-mlongcalls,-mno-longcallsโ when enabled, GCC tells the assembler to turn direct calls into indirect calls unless it can tell the target of the direct call is in range for the call instruction ๐ This usually happens for calls to functions in other source files. Specifically, the assembler turns a directCALLinto anL32Rfollowed by aCALLX. The default is-mno-longcalls. Use this in programs where the call target could be out of range โญ This option is implemented in the assembler, not the compiler, so the assembly GCC generates still shows direct call instructions---look at the disassembled object code to see the actual instructions ๐ 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โ when this is on, function parameters get passed in registersa2througha7, registersa12througha15are caller-saved, and registera15may be used as a frame pointer ๐ When this ABI version is enabled, the C preprocessor symbol__XTENSA_CALL0_ABI__is defined ๐ฆ-mabi=windowedโ when this is on, function parameters get 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, and the register window gets rotated 8 registers back on return. When this ABI version is enabled, the C preprocessor symbol__XTENSA_WINDOWED_ABI__is defined ๐ซถ
โจ zSeries Options โจ
These are listed under
โจ ENVIRONMENT โจ
okay bestie, this section is all about the environment variables that change how GCC behaves ๐ธ Some of them tell GCC where to hunt for files (directories and prefixes), and some just tweak other parts of the compilation setup ๐
ngl, you can also tell GCC where to look with options like -B, -I and -L. Those beat environment variables, and environment variables beat the defaults baked into how GCC was configured. Main character hierarchy ๐
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL ๐
These four handle localization, which is how GCC copes with different national conventions. GCC checks LC_CTYPE and LC_MESSAGES 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 means English from the United Kingdom encoded in UTF-8 ๐ฌ๐ง
LC_CTYPEis all about character classification. GCC uses it to figure out where characters start and end in a string. This matters for some multibyte encodings that have quote and escape characters that would otherwise be read as the end of a string or as an escape ๐ซถLC_MESSAGESpicks the language for diagnostic messages (aka the errors and warnings you get back) ๐ฌLC_ALLis the boss. If it's set, it overridesLC_CTYPEandLC_MESSAGES. If it isn't, thenLC_CTYPEandLC_MESSAGESjust default to whateverLANGsays. And if none of these are set at all, GCC goes with traditional C English behavior ๐
TMPDIR ๐ฆ
If TMPDIR is set, that's the directory GCC uses for its temporary files. GCC stashes the output of one stage so the next stage can use it as input. For example, the preprocessor's output becomes the input for 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's a prefix that gets used in the names of the subprograms GCC runs. No slash gets added when it's combined with a subprogram name, so if you want one, end your prefix with a slash yourself ๐
- If it's not set, GCC tries to work out a sensible prefix from the pathname it was invoked with ๐
- If GCC can't find a subprogram using your prefix, it falls back to the usual places ๐
- The default is
prefix/lib/gcc/, whereprefixis the prefix of the installed compiler. Most of the time that's whatever you passed as "prefix" when you ran the configure script โ๏ธ - Prefixes given with
-Bbeat this one ๐ - This prefix also helps GCC find files like
crt0.othat get used for linking ๐
It's also used in a sneaky way for header files ๐ซฃ For each standard directory that normally starts with /usr/local/lib/gcc (or more precisely, with the value of GCC_INCLUDE_DIR), GCC swaps that beginning for your prefix to make an alternate directory name. So with -Bfoo/, GCC searches foo/bar just before it checks the standard /usr/local/lib/bar. And if a standard directory starts with the configured prefix, GCC swaps in the value of GCC_EXEC_PREFIX when looking for headers ๐
COMPILER_PATH ๐ค๏ธ
The value of COMPILER_PATH is a colon-separated list of directories, very much like PATH. GCC checks these when searching for subprograms, but only if it can't find them using GCC_EXEC_PREFIX first ๐
LIBRARY_PATH ๐
The value of LIBRARY_PATH is also a colon-separated list of directories, just like PATH. On a native compiler, GCC checks these when hunting for special linker files, but only if GCC_EXEC_PREFIX didn't find them first. Linking also searches these directories for ordinary libraries used with the -l option, although any directories given with -L come first ๐ฆ
LANG (round two) ๐ธ
This LANG is about passing locale info to the compiler. One thing it affects is which character set gets used when character literals, string literals and comments are parsed in C and C++ ๐ง When the compiler is set up to allow multibyte characters, these LANG values are recognized:
C-JISโ recognizes JIS characters ๐ฏ๐ตC-SJISโ recognizes SJIS characters ๐ฏ๐ตC-EUCJPโ recognizes EUCJP characters ๐ฏ๐ต
If LANG isn't defined, or it's set to something else, the compiler uses "mblen" and "mbtowc" from 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, GCC prints extra text to stderr whenever it emits fix-it hints. Heads up: -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 first column ๐ขfixits-v2โ same asfixits-v1, except columns are counted as display columns, like with-fdiagnostics-column-unit=display๐
Some more environment variables affect the preprocessor too ๐งโโ๏ธ
CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH ๐
Each of these holds a list of directories to search for header files, separated by a special character, like PATH. That special character, "PATH_SEPARATOR", depends on the target and gets decided when GCC is built. On Microsoft Windows-based targets it's a semicolon, and on almost every other target it's a colon ๐ช
CPATHdirectories get searched as if you'd used-I, but after any paths from-Ioptions on the command line. This one is used no matter which language is being preprocessed ๐- The rest only apply when preprocessing their particular language. Each one's directories get searched as if you'd used
-isystem, but after any paths from-isystemoptions 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 start or end of a path. For example, if CPATH is ":/special/include", that has the exact same effect as -I. -I/special/include ๐
DEPENDENCIES_OUTPUT ๐งฉ
If this variable 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 is guessed from the source file name. Or the value can look like file target, in which case the rules get written to file and use target as the target name ๐ฏ
Put simply, this environment variable works like combining the options -MM and -MF, with an optional -MT switch too ๐
SUNPRO_DEPENDENCIES ๐
This one is the same as DEPENDENCIES_OUTPUT (see above), with one big difference: system header files are not ignored. That means it implies -M rather than -MM ๐ณ The dependence on the main input file is left out, though ๐
SOURCE_DATE_EPOCH โฐ
If this variable is set, its value is a UNIX timestamp that replaces the current date and time in the "__DATE__" and "__TIME__" macros. That way the embedded timestamps stay reproducible โจ
The value has to be a UNIX timestamp, which is the number of seconds (leap seconds excluded) since 01 Jan 1970 00:00:00, written in ASCII. It's the same as what date +%s prints on GNU/Linux and other systems that support the %s extension in the date command ๐งฎ
Pick a known timestamp, like the last modification time of the source or package, and let your build process set it ๐ ๏ธ
๐ BUGS ๐
For instructions on reporting bugs, see <file:///usr/share/doc/gcc-12/README.Bugs> ๐
๐ FOOTNOTES ๐
- On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work. On multi-libbed systems,gcc -sharedmust select the correct support libraries to link against. Failing to supply the correct flags may lead to subtle defects. Supplying them in cases where they are not necessary is innocuous. ๐
๐ SEE ALSO ๐
gpl(7), gfdl(7), fsf-funding(7), cpp(1), gcov(1), as(1), ld(1), gdb(1), dbx(1) and the Info entries for gcc, cpp, as, ld, binutils and gdb ๐
๐ฉโ๐ป AUTHOR ๐ฉโ๐ป
See the Info entry for gcc, or <https://gcc.gnu.org/onlinedocs/gcc/Contributors.html>, for contributors to GCC ๐ซถ
โ๏ธ COPYRIGHT โ๏ธ
Copyright (c) 1988-2022 Free Software Foundation, Inc. ๐ธ
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation. The Invariant Sections are "GNU General Public License" and "Funding Free Software", the Front-Cover texts are (a) (see below), and the Back-Cover Texts are (b) (see below). A copy of the license is included in the gfdl(7) man page ๐
(a) The FSF's Front-Cover Text is:
A GNU Manual
(b) The FSF's Back-Cover Text is:
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development. ๐
That's the whole page, bestie! ๐ Thanks for hanging with me through all 116 parts ๐ฅน This one was gcc-12, last updated 2022-03-02, and we are SO done ๐ โจ
๐ฆ where this page comes from
- ubuntu jammy: gcc-12-hppa-linux-gnu 12-20220302-1ubuntu1cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms