GCC(1)
๐ GCC(1) ยท GNU manual ๐
๐ NAME ๐
gcc - GNU project C and C++ compiler ๐
๐ธ SYNOPSIS ๐ธ
Here's the vibe check for how you call it โจ
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
Only the MVP options made the cut here, so the rest are down below ๐. g++ takes pretty much the same options as gcc ๐ง.
๐ DESCRIPTION ๐
Okay so when you invoke GCC, it normally runs through preprocessing, compilation, assembly, and linking all in one go ๐ฅ. The "overall options" let you stop the process at an intermediate stage. Like, -c says don't bother running the linker, so what you get back is the object files the assembler spat out ๐ฆ.
Other options get passed along to one or more stages of processing ๐ . Some control the preprocessor, some control the compiler itself, and yet more control the assembler and linker. Most of those linker and assembler ones aren't documented here, since you hardly ever 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 explicitly ๐. If an option's description doesn't mention a source language, you can use it with all supported languages โจ.
The usual way to run it is the executable called gcc, or machine-gcc when you're cross-compiling, or machine-gcc-version if you want a specific version of GCC ๐ง. When you compile C++ programs, though, invoke GCC as g++ instead ๐.
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so you can't bundle single-letter options together. -dv is very different from -d -v ๐.
You can mix options and other arguments ๐. For the most part the order doesn't matter, but it does when you use several options of the same kind. For example, if you specify -L more than once, the directories get searched in the order you gave them. Also, where you place the -l option is significant ๐.
Tons of options have long names starting with -f or with -W---for, for example -fmove-loop-invariants, -Wformat, and so on ๐
. Most of them come in positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one isn't the default ๐ฆ.
Some options take one or more arguments, usually separated from the option name by either a space or an equals sign (=) ๐ซถ. Unless it says otherwise, an argument can be numeric or a string ๐ฅ. Numeric arguments are typically small unsigned decimal or hexadecimal integers, and hex ones must begin with the 0x prefix ๐.
Arguments to options that set a size threshold can be arbitrarily large decimal or hexadecimal integers, followed by a byte size suffix ๐. Those suffixes stand for multiples of bytes: "kB" and "KiB" for kilobyte and kibibyte, "MB" and "MiB" for megabyte and mebibyte, "GB" and "GiB" for gigabyte and gigibyte, and so on. In the following text these are called byte-size arguments. For the full listing and explanation of the binary and decimal byte size prefixes, refer to the NIST, IEC, and other relevant national and international standards ๐ง.
โจ OPTIONS โจ
๐ฆ Option Summary ๐ฆ
Here's the whole squad of options, sorted by type ๐. The explanations come later on in the page โจ.
Overall Options
-c -S -E -o file -dumpbase dumpbase -dumpbase-ext auxdropsuf
-dumpdir dumppfx -x language -v -### --help[=class[,...]]
--target-help --version -pass-exit-codes -pipe -specs=file
-wrapper @file -ffile-prefix-map=old=new -fplugin=file
-fplugin-arg-name=arg -fdump-ada-spec[-slim] -fada-spec-parent=unit
-fdump-go-spec=file
C Language Options
-ansi -std=standard -fgnu89-inline
-fpermitted-flt-eval-methods=standard -aux-info filename
-fallow-parameterless-variadic-functions -fno-asm -fno-builtin
-fno-builtin-function -fgimple -fhosted -ffreestanding -fopenacc
-fopenacc-dim=geom -fopenmp -fopenmp-simd -fms-extensions
-fplan9-extensions -fsso-struct=endianness -fallow-single-precision
-fcond-mismatch -flax-vector-conversions -fsigned-bitfields
-fsigned-char -funsigned-bitfields -funsigned-char
C++ Language Options
-fabi-version=n -fno-access-control -faligned-new=n
-fargs-in-order=n -fchar8_t -fcheck-new -fconstexpr-depth=n
-fconstexpr-cache-depth=n -fconstexpr-loop-limit=n
-fconstexpr-ops-limit=n -fno-elide-constructors
-fno-enforce-eh-specs -fno-gnu-keywords -fno-implicit-templates
-fno-implicit-inline-templates -fno-implement-inlines
-fmodule-header[=kind] -fmodule-only -fmodules-ts
-fmodule-implicit-inline -fno-module-lazy
-fmodule-mapper=specification -fmodule-version-ignore
-fms-extensions -fnew-inheriting-ctors -fnew-ttp-matching
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names
-fno-optional-diags -fpermissive -fno-pretty-templates -fno-rtti
-fsized-deallocation -ftemplate-backtrace-limit=n -ftemplate-depth=n
-fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++
-fvisibility-inlines-hidden -fvisibility-ms-compat
-fext-numeric-literals -flang-info-include-translate[=header]
-flang-info-include-translate-not -flang-info-module-cmi[=module]
-stdlib=libstdc++,libc++ -Wabi-tag -Wcatch-value -Wcatch-value=n
-Wno-class-conversion -Wclass-memaccess -Wcomma-subscript
-Wconditionally-supported -Wno-conversion-null
-Wctad-maybe-unsupported -Wctor-dtor-privacy -Wno-delete-incomplete
-Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor
-Wno-deprecated-enum-enum-conversion
-Wno-deprecated-enum-float-conversion -Weffc++ -Wno-exceptions
-Wextra-semi -Wno-inaccessible-base -Wno-inherited-variadic-ctor
-Wno-init-list-lifetime -Winvalid-imported-macros
-Wno-invalid-offsetof -Wno-literal-suffix
-Wno-mismatched-new-delete -Wmismatched-tags -Wmultiple-inheritance
-Wnamespaces -Wnarrowing -Wnoexcept -Wnoexcept-type
-Wnon-virtual-dtor -Wpessimizing-move -Wno-placement-new
-Wplacement-new=n -Wrange-loop-construct -Wredundant-move
-Wredundant-tags -Wreorder -Wregister -Wstrict-null-sentinel
-Wno-subobject-linkage -Wtemplates -Wno-non-template-friend
-Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions
-Wsign-promo -Wsized-deallocation -Wsuggest-final-methods
-Wsuggest-final-types -Wsuggest-override -Wno-terminate
-Wuseless-cast -Wno-vexing-parse -Wvirtual-inheritance
-Wno-virtual-move-assign -Wvolatile
-Wzero-as-null-pointer-constant
Objective-C and Objective-C++ Language Options
-fconstant-string-class=class-name -fgnu-runtime -fnext-runtime
-fno-nil-receivers -fobjc-abi-version=n -fobjc-call-cxx-cdtors
-fobjc-direct-dispatch -fobjc-exceptions -fobjc-gc -fobjc-nilcheck
-fobjc-std=objc1 -fno-local-ivars
-fivar-visibility=[public|protected|private|package]
-freplace-objc-classes -fzero-link -gen-decls -Wassign-intercept
-Wno-property-assign-default -Wno-protocol -Wobjc-root-class
-Wselector -Wstrict-selector-match -Wundeclared-selector
Diagnostic Message Formatting Options
-fmessage-length=n -fdiagnostics-plain-output
-fdiagnostics-show-location=[once|every-line]
-fdiagnostics-color=[auto|never|always]
-fdiagnostics-urls=[auto|never|always]
-fdiagnostics-format=[text|json] -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-labels
-fno-diagnostics-show-line-numbers -fno-diagnostics-show-cwe
-fdiagnostics-minimum-margin-width=width
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type
-fdiagnostics-path-format=[none|separate-events|inline-events]
-fdiagnostics-show-path-depths -fno-show-column
-fdiagnostics-column-unit=[display|byte]
-fdiagnostics-column-origin=origin
โจ Warning Options โจ
okay bestie, this is the whole warning squad ๐จ๐ these are just the names, no descriptions in this part, so grab the ones you need and go ๐ซถ
-fsyntax-only -fmax-errors=n -Wpedantic -pedantic-errors -w
-Wextra -Wall -Wabi=n -Waddress -Wno-address-of-packed-member
-Waggregate-return -Walloc-size-larger-than=byte-size -Walloc-zero
-Walloca -Walloca-larger-than=byte-size
-Wno-aggressive-loop-optimizations -Warith-conversion -Warray-bounds
-Warray-bounds=n -Wno-attributes -Wattribute-alias=n
-Wno-attribute-alias -Wno-attribute-warning -Wbool-compare
-Wbool-operation -Wno-builtin-declaration-mismatch
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat
-Wc11-c2x-compat -Wc++-compat -Wc++11-compat -Wc++14-compat
-Wc++17-compat -Wc++20-compat -Wcast-align -Wcast-align=strict
-Wcast-function-type -Wcast-qual -Wchar-subscripts -Wclobbered
-Wcomment -Wconversion -Wno-coverage-mismatch -Wno-cpp
-Wdangling-else -Wdate-time -Wno-deprecated
-Wno-deprecated-declarations -Wno-designated-init
-Wdisabled-optimization -Wno-discarded-array-qualifiers
-Wno-discarded-qualifiers -Wno-div-by-zero -Wdouble-promotion
-Wduplicated-branches -Wduplicated-cond -Wempty-body
-Wno-endif-labels -Wenum-compare -Wenum-conversion -Werror
-Werror=* -Wexpansion-to-defined -Wfatal-errors -Wfloat-conversion
-Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul
-Wno-format-extra-args -Wformat-nonliteral -Wformat-overflow=n
-Wformat-security -Wformat-signedness -Wformat-truncation=n
-Wformat-y2k -Wframe-address -Wframe-larger-than=byte-size
-Wno-free-nonheap-object -Wno-if-not-aligned
-Wno-ignored-attributes -Wignored-qualifiers
-Wno-incompatible-pointer-types -Wimplicit -Wimplicit-fallthrough
-Wimplicit-fallthrough=n -Wno-implicit-function-declaration
-Wno-implicit-int -Winit-self -Winline -Wno-int-conversion
-Wint-in-bool-context -Wno-int-to-pointer-cast
-Wno-invalid-memory-model -Winvalid-pch -Wjump-misses-init
-Wlarger-than=byte-size -Wlogical-not-parentheses -Wlogical-op
-Wlong-long -Wno-lto-type-mismatch -Wmain -Wmaybe-uninitialized
-Wmemset-elt-size -Wmemset-transposed-args -Wmisleading-indentation
-Wmissing-attributes -Wmissing-braces -Wmissing-field-initializers
-Wmissing-format-attribute -Wmissing-include-dirs
-Wmissing-noreturn -Wno-missing-profile -Wno-multichar
-Wmultistatement-macros -Wnonnull -Wnonnull-compare
-Wnormalized=[none|id|nfc|nfkc] -Wnull-dereference -Wno-odr
-Wopenmp-simd -Wno-overflow -Woverlength-strings
-Wno-override-init-side-effects -Wpacked
-Wno-packed-bitfield-compat -Wpacked-not-aligned -Wpadded
-Wparentheses -Wno-pedantic-ms-format -Wpointer-arith
-Wno-pointer-compare -Wno-pointer-to-int-cast -Wno-pragmas
-Wno-prio-ctor-dtor -Wredundant-decls -Wrestrict
-Wno-return-local-addr -Wreturn-type -Wno-scalar-storage-order
-Wsequence-point -Wshadow -Wshadow=global -Wshadow=local
-Wshadow=compatible-local -Wno-shadow-ivar -Wno-shift-count-negative
-Wno-shift-count-overflow -Wshift-negative-value
-Wno-shift-overflow -Wshift-overflow=n -Wsign-compare
-Wsign-conversion -Wno-sizeof-array-argument -Wsizeof-array-div
-Wsizeof-pointer-div -Wsizeof-pointer-memaccess -Wstack-protector
-Wstack-usage=byte-size -Wstrict-aliasing -Wstrict-aliasing=n
-Wstrict-overflow -Wstrict-overflow=n -Wstring-compare
-Wno-stringop-overflow -Wno-stringop-overread
-Wno-stringop-truncation
-Wsuggest-attribute=[pure|const|noreturn|format|malloc] -Wswitch
-Wno-switch-bool -Wswitch-default -Wswitch-enum
-Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand
-Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs
-Wtsan -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas
-Wunsuffixed-float-constants -Wunused -Wunused-but-set-parameter
-Wunused-but-set-variable -Wunused-const-variable
-Wunused-const-variable=n -Wunused-function -Wunused-label
-Wunused-local-typedefs -Wunused-macros -Wunused-parameter
-Wno-unused-result -Wunused-value -Wunused-variable -Wno-varargs
-Wvariadic-macros -Wvector-operation-performance -Wvla
-Wvla-larger-than=byte-size -Wno-vla-larger-than
-Wvolatile-register-var -Wwrite-strings -Wzero-length-bounds
โจ Static Analyzer Options โจ
the analyzer era ๐๐ฆ these are the static analyzer flags, all lined up and ready to be used, no cap
-fanalyzer -fanalyzer-call-summaries -fanalyzer-checker=name
-fno-analyzer-feasibility -fanalyzer-fine-grained
-fanalyzer-state-merge -fanalyzer-state-purge
-fanalyzer-transitivity -fanalyzer-verbose-edges
-fanalyzer-verbose-state-changes -fanalyzer-verbosity=level
-fdump-analyzer -fdump-analyzer-stderr -fdump-analyzer-callgraph
-fdump-analyzer-exploded-graph -fdump-analyzer-exploded-nodes
-fdump-analyzer-exploded-nodes-2 -fdump-analyzer-exploded-nodes-3
-fdump-analyzer-feasibility -fdump-analyzer-json
-fdump-analyzer-state-purge -fdump-analyzer-supergraph
-Wno-analyzer-double-fclose -Wno-analyzer-double-free
-Wno-analyzer-exposure-through-output-file -Wno-analyzer-file-leak
-Wno-analyzer-free-of-non-heap -Wno-analyzer-malloc-leak
-Wno-analyzer-mismatching-deallocation -Wno-analyzer-null-argument
-Wno-analyzer-null-dereference -Wno-analyzer-possible-null-argument
-Wno-analyzer-possible-null-dereference
-Wno-analyzer-shift-count-negative
-Wno-analyzer-shift-count-overflow -Wno-analyzer-stale-setjmp-buffer
-Wno-analyzer-tainted-array-index -Wanalyzer-too-complex
-Wno-analyzer-unsafe-call-within-signal-handler
-Wno-analyzer-use-after-free
-Wno-analyzer-use-of-pointer-in-stale-stack-frame
-Wno-analyzer-use-of-uninitialized-value
-Wno-analyzer-write-to-const -Wno-analyzer-write-to-string-literal
โจ C and Objective-C-only Warning Options โจ
these ones are for the C and Objective-C crowd only ๐ธ๐ if you're not writing those languages, you can skip this one, no judgment ๐
-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 โจ
the debugging era is here ๐ง๐ฅ this is where you go when things are being weird and you need the receipts ๐งพโจ every flag from the debugging list is right below, bestie ๐
-g -glevel -gdwarf -gdwarf-version -ggdb -grecord-gcc-switches
-gno-record-gcc-switches -gstabs -gstabs+ -gstrict-dwarf
-gno-strict-dwarf -gas-loc-support -gno-as-loc-support
-gas-locview-support -gno-as-locview-support -gcolumn-info
-gno-column-info -gdwarf32 -gdwarf64 -gstatement-frontiers
-gno-statement-frontiers -gvariable-location-views
-gno-variable-location-views -ginternal-reset-location-views
-gno-internal-reset-location-views -ginline-points
-gno-inline-points -gvms -gxcoff -gxcoff+ -gz[=type]
-gsplit-dwarf -gdescribe-dies -gno-describe-dies
-fdebug-prefix-map=old=new -fdebug-types-section
-fno-eliminate-unused-debug-types -femit-struct-debug-baseonly
-femit-struct-debug-reduced -femit-struct-debug-detailed[=spec-list]
-fno-eliminate-unused-debug-symbols -femit-class-debug-always
-fno-merge-debug-strings -fno-dwarf2-cfi-asm -fvar-tracking
-fvar-tracking-assignments
โจ Optimization Options โจ
okay bestie, buckle up ๐ญ๐ฅ this optimization menu is HUGE and honestly the vibes are immaculate ๐
-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-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-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-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
โจ Program Instrumentation Options โจ
the detective squad ๐ต๏ธ๐ these ones are all about watching the code do its thing, iykyk
-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]-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,...
โจ Preprocessor Options โจ
preprocessor era ๐ธ๐ everything gets lined up before the main show, it's giving prep school
-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 โจ
tiny section, big energy ๐ฆ
-Wa,option-Xassembler option
โจ Linker Options โจ
the linking era ๐๐ this is where all the pieces finally click together ๐ซถ
object-file-name-fuse-ld=linker-llibrary-nostartfiles-nodefaultlibs-nolibc-nostdlib-e entry--entry=entry-pie-pthread-r-rdynamic-s-static-static-pie-static-libgcc-static-libstdc++-static-libasan-static-libtsan-static-liblsan-static-libubsan-shared-shared-libgcc-symbolic-T script-Wl,option-Xlinker option-u symbol-z keyword
โจ Directory Options โจ
where everything lives ๐๏ธโจ it's giving GPS, bestie ๐งญ
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--sysroot=dir
โจ Code Generation Options โจ
the glow-up section ๐๐ this one is literally so extra
-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 โจ
for the people who love peeking under the hood ๐๐ ngl I'm obsessed with this whole section
-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 โจ
every target gets its own VIP list ๐ค๐ the hardware is giving main character energy
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, this part is basically a big sparkly list of machine-specific flags, and the page just names them without explaining what they do. so I'm not gonna make stuff up ๐ซถ
-mhalf-reg-file๐-mprefer-short-insn-regsโจ-mbranch-cost=num๐-mcmove๐ฆ-mnops=num๐ธ-msoft-cmpsf๐-msplit-lohi๐ซถ-mpost-inc๐ฅ-mpost-modify๐-mstack-offset=num๐-mround-nearestโญ-mlong-calls๐-mshort-calls๐ง-msmall16๐-mfp-mode=mode๐-mvect-doubleโจ-max-vect-align=num๐-msplit-vecmove-early๐ฆ-m1reg-reg๐ธ
โจ AMD GCN Options โจ
-march=gpu๐-mtune=gpu๐ซถ-mstack-size=bytes๐ฅ
โจ ARC Options โจ
-mbarrel-shifter๐-mjli-always๐-mcpu=cpuโญ-mA6๐-mARC600๐ง-mA7๐-mARC700๐-mdpfpโจ-mdpfp-compact๐-mdpfp-fast๐ฆ-mno-dpfp-lrsr๐ธ-mea๐-mno-mpy๐ซถ-mmul32x16๐ฅ-mmul64๐-matomic๐-mnormโญ-mspfp๐-mspfp-compact๐ง-mspfp-fast๐-msimd๐-msoft-floatโจ-mswap๐-mcrc๐ฆ-mdsp-packa๐ธ-mdvbf๐-mlock๐ซถ-mmac-d16๐ฅ-mmac-24๐-mrtsc๐-mswapeโญ-mtelephony๐-mxy๐ง-misize๐-mannotate-align๐-marclinuxโจ-marclinux_prof๐-mlong-calls๐ฆ-mmedium-calls๐ธ-msdata๐-mirq-ctrl-saved๐ซถ-mrgf-banked-regs๐ฅ-mlpc-width=width๐-G num๐-mvolatile-cacheโญ-mtp-regno=regno๐-malign-call๐ง-mauto-modify-reg๐-mbbit-peephole๐-mno-brccโจ-mcase-vector-pcrel๐-mcompact-casesi๐ฆ-mno-cond-exec๐ธ-mearly-cbranchsi๐-mexpand-adddi๐ซถ-mindexed-loads๐ฅ-mlra๐-mlra-priority-none๐-mlra-priority-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๐
the original is missing the leading dash on mlra-priority-noncompact, so I kept it exactly as written ๐
โจ ARM Options โจ
-mapcs-frameโจ-mno-apcs-frame๐-mabi=name๐ฆ-mapcs-stack-check๐ธ-mno-apcs-stack-check๐-mapcs-reentrant๐ซถ-mno-apcs-reentrant๐ฅ-mgeneral-regs-only๐-msched-prolog๐-mno-sched-prologโญ-mlittle-endian๐-mbig-endian๐ง-mbe8๐-mbe32๐-mfloat-abi=nameโจ-mfp16-format=name๐-mthumb-interwork๐ฆ-mno-thumb-interwork๐ธ-mcpu=name๐-march=name๐ซถ-mfpu=name๐ฅ-mtune=name๐-mprint-tune-info๐-mstructure-size-boundary=nโญ-mabort-on-noreturn๐-mlong-calls๐ง-mno-long-calls๐-msingle-pic-base๐-mno-single-pic-baseโจ-mpic-register=reg๐-mnop-fun-dllimport๐ฆ-mpoke-function-name๐ธ-mthumb๐-marm๐ซถ-mflip-thumb๐ฅ-mtpcs-frame๐-mtpcs-leaf-frame๐-mcaller-super-interworkingโญ-mcallee-super-interworking๐-mtp=name๐ง-mtls-dialect=dialect๐-mword-relocations๐-mfix-cortex-m3-ldrdโจ-munaligned-access๐-mneon-for-64bits๐ฆ-mslow-flash-data๐ธ-masm-syntax-unified๐-mrestrict-it๐ซถ-mverbose-cost-dump๐ฅ-mpure-code๐-mcmse๐-mfix-cmse-cve-2021-35465โญ-mfdpic๐
โจ AVR Options โจ
-mmcu=mcu๐ง-mabsdata๐-maccumulate-args๐-mbranch-cost=costโจ-mcall-prologues๐-mgas-isr-prologues๐ฆ-mint8๐ธ-mdouble=bits๐-mlong-double=bits๐ซถ-mn_flash=size๐ฅ-mno-interrupts๐-mmain-is-OS_task๐-mrelaxโญ-mrmw๐-mstrict-X๐ง-mtiny-stack๐-mfract-convert-truncate๐-mshort-callsโจ-nodevicelib๐-nodevicespecs๐ฆ-Waddr-space-convert๐ธ-Wmisspelled-isr๐
โจ Blackfin Options โจ
-mcpu=cpu[-sirevision]๐ซถ-msim๐ฅ-momit-leaf-frame-pointer๐-mno-omit-leaf-frame-pointer๐-mspecld-anomalyโญ-mno-specld-anomaly๐-mcsync-anomaly๐ง-mno-csync-anomaly๐-mlow-64k๐-mno-low64kโจ-mstack-check-l1๐-mid-shared-library๐ฆ-mno-id-shared-library๐ธ-mshared-library-id=n๐-mleaf-id-shared-library๐ซถ-mno-leaf-id-shared-library๐ฅ-msep-data๐-mno-sep-data๐-mlong-callsโญ-mno-long-calls๐-mfast-fp๐ง-minline-plt๐-mmulticore๐-mcoreaโจ-mcoreb๐-msdram๐ฆ-micplb๐ธ
โจ C6X Options โจ
-mbig-endian๐-mlittle-endian๐ซถ-march=cpu๐ฅ-msim๐-msdata=sdata-type๐
โจ CRIS Options โจ
-mcpu=cpuโญ-march=cpu๐-mtune=cpu๐ง-mmax-stack-frame=n๐-metrax4๐-metrax100โจ-mpdebug๐-mcc-init๐ฆ-mno-side-effects๐ธ-mstack-align๐-mdata-align๐ซถ-mconst-align๐ฅ-m32-bit๐-m16-bit๐-m8-bitโญ-mno-prologue-epilogue๐-melf๐ง-maout๐-sim๐-sim2โจ-mmul-bug-workaround๐-mno-mul-bug-workaround๐ฆ
โจ CR16 Options โจ
-mmac๐ธ-mcr16cplus๐-mcr16c๐ซถ-msim๐ฅ-mint32๐-mbit-ops๐-mdata-model=modelโญ
โจ C-SKY Options โจ
-march=arch๐-mcpu=cpu๐ง-mbig-endian๐-EB๐-mlittle-endianโจ-EL๐-mhard-float๐ฆ-msoft-float๐ธ-mfpu=fpu๐-mdouble-float๐ซถ-mfdivdu๐ฅ-mfloat-abi=name๐-melrw๐-mistackโญ-mmp๐-mcp๐ง-mcache๐-msecurity๐-mtrustโจ-mdsp๐-medsp๐ฆ-mvdsp๐ธ-mdiv๐-msmart๐ซถ-mhigh-registers๐ฅ-manchor๐-mpushpop๐-mmultiple-stldโญ-mconstpool๐-mstack-size๐ง-mccrt๐-mbranch-cost=n๐-mcse-ccโจ-msched-prolog๐-msim๐ฆ
โจ Darwin Options โจ
-all_load๐ธ-allowable_client๐-arch๐ซถ-arch_errors_fatal๐ฅ-arch_only๐-bind_at_load๐-bundleโญ-bundle_loader๐-client_name๐ง-compatibility_version๐-current_version๐-dead_stripโจ-dependency-file๐-dylib_file๐ฆ-dylinker_install_name๐ธ-dynamic๐-dynamiclib๐ซถ-exported_symbols_list๐ฅ-filelist๐-flat_namespace๐-force_cpusubtype_ALLโญ-force_flat_namespace๐-headerpad_max_install_names๐ง-iframework๐-image_base๐-initโจ-install_name๐-keep_private_externs๐ฆ-multi_module๐ธ-multiply_defined๐-multiply_defined_unused๐ซถ-noall_load๐ฅ-no_dead_strip_inits_and_terms๐-nofixprebinding๐-nomultidefsโญ-noprebind๐-noseglinkedit๐ง-pagezero_size๐-prebind๐-prebind_all_twolevel_modulesโจ-private_bundle๐-read_only_relocs๐ฆ-sectalign๐ธ-sectobjectsymbols๐-whyload๐ซถ-seg1addr๐ฅ-sectcreate๐-sectorder๐-segaddrโญ-segs_read_only_addr๐-segs_read_write_addr๐ง-seg_addr_table๐-seg_addr_table_filename๐-seglinkeditโจ-segprot๐-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๐ธ
-sectobjectsymbols,-segs_read_only_addrand-segs_read_write_addreach show up twice in the original, so I listed them once each here ๐
โจ DEC Alpha Options โจ
-mno-fp-regs๐-msoft-float๐ซถ-mieee๐ฅ-mieee-with-inexact๐-mieee-conformant๐-mfp-trap-mode=modeโญ-mfp-rounding-mode=mode๐-mtrap-precision=mode๐ง-mbuild-constants๐-mcpu=cpu-type๐-mtune=cpu-typeโจ-mbwx๐-mmax๐ฆ-mfix๐ธ-mcix๐-mfloat-vax๐ซถ-mfloat-ieee๐ฅ-mexplicit-relocs๐-msmall-data๐-mlarge-dataโญ-msmall-text๐-mlarge-text๐ง-mmemory-latency=time๐
โจ eBPF Options โจ
-mbig-endian๐-mlittle-endianโจ-mkernel=version๐-mframe-limit=bytes๐ฆ-mxbpf๐ธ
โจ FR30 Options โจ
-msmall-model๐-mno-lsim๐ซถ
โจ FT32 Options โจ
-msim๐ฅ-mlra๐-mnodiv๐-mft32bโญ-mcompress๐-mnopm๐ง
โจ FRV Options โจ
-mgpr-32๐-mgpr-64๐-mfpr-32โจ-mfpr-64๐-mhard-float๐ฆ-msoft-float๐ธ-malloc-cc๐-mfixed-cc๐ซถ-mdword๐ฅ-mno-dword๐-mdouble๐-mno-doubleโญ-mmedia๐-mno-media๐ง-mmuladd๐-mno-muladd๐-mfdpicโจ-minline-plt๐-mgprel-ro๐ฆ-multilib-library-pic๐ธ-mlinked-fp๐-mlong-calls๐ซถ-malign-labels๐ฅ-mlibrary-pic๐-macc-4๐-macc-8โญ-mpack๐-mno-pack๐ง-mno-eflags๐-mcond-move๐-mno-cond-moveโจ-moptimize-membar๐-mno-optimize-membar๐ฆ-mscc๐ธ-mno-scc๐-mcond-exec๐ซถ-mno-cond-exec๐ฅ-mvliw-branch๐-mno-vliw-branch๐-mmulti-cond-execโญ-mno-multi-cond-exec๐-mnested-cond-exec๐ง-mno-nested-cond-exec๐-mtomcat-stats๐-mTLSโจ-mtls๐-mcpu=cpu๐ฆ
โจ GNU/Linux Options โจ
-mglibc๐ธ-muclibc๐-mmusl๐ซถ-mbionic๐ฅ-mandroid๐-tno-android-cc๐-tno-android-ldโญ
โจ H8/300 Options โจ
-mrelax๐-mh๐ง-ms๐-mn๐-mexrโจ-mno-exr๐-mint32๐ฆ-malign-300๐ธ
โจ HPPA Options โจ
-march=architecture-type๐-mcaller-copies๐ซถ-mdisable-fpregs๐ฅ-mdisable-indexing๐-mfast-indirect-calls๐-mgasโญ-mgnu-ld๐-mhp-ld๐ง-mfixed-range=register-range๐-mjump-in-delay๐-mlinker-optโจ-mlong-calls๐-mlong-load-store๐ฆ-mno-disable-fpregs๐ธ-mno-disable-indexing๐-mno-fast-indirect-calls๐ซถ-mno-gas๐ฅ-mno-jump-in-delay๐-mno-long-load-store๐-mno-portable-runtimeโญ-mno-soft-float๐-mno-space-regs๐ง-msoft-float๐-mpa-risc-1-0๐-mpa-risc-1-1โจ-mpa-risc-2-0๐-mportable-runtime๐ฆ-mschedule=cpu-type๐ธ-mspace-regs๐-msio๐ซถ-mwsio๐ฅ-munix=unix-std๐-nolibdld๐-staticโญ-threads๐
โจ IA-64 Options โจ
-mbig-endian๐ง-mlittle-endian๐-mgnu-as๐-mgnu-ldโจ-mno-pic๐-mvolatile-asm-stop๐ฆ-mregister-names๐ธ-msdata๐-mno-sdata๐ซถ-mconstant-gp๐ฅ-mauto-pic๐-mfused-madd๐-minline-float-divide-min-latencyโญ-minline-float-divide-max-throughput๐-mno-inline-float-divide๐ง-minline-int-divide-min-latency๐-minline-int-divide-max-throughput๐-mno-inline-int-divideโจ-minline-sqrt-min-latency๐-minline-sqrt-max-throughput๐ฆ-mno-inline-sqrt๐ธ-mdwarf2-asm๐-mearly-stop-bits๐ซถ-mfixed-range=register-range๐ฅ-mtls-size=tls-size๐-mtune=cpu-type๐-milp32โญ-mlp64๐-msched-br-data-spec๐ง-msched-ar-data-spec๐-msched-control-spec๐-msched-br-in-data-specโจ-msched-ar-in-data-spec๐-msched-in-control-spec๐ฆ-msched-spec-ldc๐ธ-msched-spec-control-ldc๐-msched-prefer-non-data-spec-insns๐ซถ-msched-prefer-non-control-spec-insns๐ฅ-msched-stop-bits-after-every-cycle๐-msched-count-spec-in-critical-path๐-msel-sched-dont-check-control-specโญ-msched-fp-mem-deps-zero-cost๐-msched-max-memory-insns-hard-limit๐ง-msched-max-memory-insns=max-insns๐
โจ LM32 Options โจ
-mbarrel-shift-enabled๐-mdivide-enabledโจ-mmultiply-enabled๐-msign-extend-enabled๐ฆ-muser-enabled๐ธ
โจ M32R/D Options โจ
-m32r2๐-m32rx๐ซถ-m32r๐ฅ-mdebug๐-malign-loops๐-mno-align-loopsโญ-missue-rate=number๐-mbranch-cost=number๐ง-mmodel=code-size-model-type๐-msdata=sdata-type๐-mno-flush-funcโจ-mflush-func=name๐-mno-flush-trap๐ฆ-mflush-trap=number๐ธ-G num๐
โจ M32C Options โจ
-mcpu=cpu๐ซถ-msim๐ฅ-memregs=number๐
โจ M680x0 Options โจ
-march=arch๐-mcpu=cpuโญ-mtune=tune๐-m68000๐ง-m68020๐-m68020-40๐-m68020-60โจ-m68030๐-m68040๐ฆ-m68060๐ธ-mcpu32๐-m5200๐ซถ-m5206e๐ฅ-m528x๐-m5307๐-m5407โญ-mcfv4e๐-mbitfield๐ง-mno-bitfield๐-mc68000๐-mc68020โจ-mnobitfield๐-mrtd๐ฆ-mno-rtd๐ธ-mdiv๐-mno-div๐ซถ-mshort๐ฅ-mno-short๐-mhard-float๐-m68881โญ-msoft-float๐-mpcrel๐ง-malign-int๐-mstrict-align๐-msep-dataโจ-mno-sep-data๐-mshared-library-id=n๐ฆ-mid-shared-library๐ธ-mno-id-shared-library๐-mxgot๐ซถ-mno-xgot๐ฅ-mlong-jump-table-offsets๐
โจ MCore Options โจ
-mhardlit๐-mno-hardlitโญ-mdiv๐-mno-div๐ง-mrelax-immediates๐-mno-relax-immediates๐-mwide-bitfieldsโจ-mno-wide-bitfields๐-m4byte-functions๐ฆ-mno-4byte-functions๐ธ-mcallgraph-data๐-mno-callgraph-data๐ซถ-mslow-bytes๐ฅ-mno-slow-bytes๐-mno-lsim๐-mlittle-endianโญ-mbig-endian๐-m210๐ง-m340๐-mstack-increment๐
โจ MeP Options โจ
-mabsdiffโจ-mall-opts๐-maverage๐ฆ-mbased=n๐ธ-mbitops๐-mc=n๐ซถ-mclip๐ฅ-mconfig=name๐-mcop๐-mcop32โญ-mcop64๐-mivc2๐ง-mdc๐-mdiv๐-mebโจ-mel๐-mio-volatile๐ฆ-ml๐ธ-mleadz๐-mm๐ซถ-mminmax๐ฅ-mmult๐-mno-opts๐-mrepeatโญ-ms๐-msatur๐ง-msdram๐-msim๐-msimnovecโจ-mtf๐-mtiny=n๐ฆ
โจ MicroBlaze Options โจ
-msoft-float๐ธ-mhard-float๐-msmall-divides๐ซถ-mcpu=cpu๐ฅ-mmemcpy๐-mxl-soft-mul๐-mxl-soft-divโญ-mxl-barrel-shift๐-mxl-pattern-compare๐ง-mxl-stack-check๐-mxl-gp-opt๐-mno-clearbssโจ-mxl-multiply-high๐-mxl-float-convert๐ฆ-mxl-float-sqrt๐ธ-mbig-endian๐-mlittle-endian๐ซถ-mxl-reorder๐ฅ-mxl-mode-app-model๐-mpic-data-is-text-relative๐
๐ฆ MIPS Options ๐ฆ
Bestie, this is the whole MIPS squad. The page just lists them here without a deep dive, so we're vibing with the names ๐
-EL-EB-march=arch-mtune=arch-mips1-mips2-mips3-mips4-mips32-mips32r2-mips32r3-mips32r5-mips32r6-mips64-mips64r2-mips64r3-mips64r5-mips64r6-mips16-mno-mips16-mflip-mips16-minterlink-compressed-mno-interlink-compressed-minterlink-mips16-mno-interlink-mips16-mabi=abi-mabicalls-mno-abicalls-mshared-mno-shared-mplt-mno-plt-mxgot-mno-xgot-mgp32-mgp64-mfp32-mfpxx-mfp64-mhard-float-msoft-float-mno-float-msingle-float-mdouble-float-modd-spreg-mno-odd-spreg-mabs=mode-mnan=encoding-mdsp-mno-dsp-mdspr2-mno-dspr2-mmcu-mmno-mcu-meva-mno-eva-mvirt-mno-virt-mxpa-mno-xpa-mcrc-mno-crc-mginv-mno-ginv-mmicromips-mno-micromips-mmsa-mno-msa-mloongson-mmi-mno-loongson-mmi-mloongson-ext-mno-loongson-ext-mloongson-ext2-mno-loongson-ext2-mfpu=fpu-type-msmartmips-mno-smartmips-mpaired-single-mno-paired-single-mdmx-mno-mdmx-mips3d-mno-mips3d-mmt-mno-mt-mllsc-mno-llsc-mlong64-mlong32-msym32-mno-sym32-Gnum-mlocal-sdata-mno-local-sdata-mextern-sdata-mno-extern-sdata-mgpopt-mno-gopt-membedded-data-mno-embedded-data-muninit-const-in-rodata-mno-uninit-const-in-rodata-mcode-readable=setting-msplit-addresses-mno-split-addresses-mexplicit-relocs-mno-explicit-relocs-mcheck-zero-division-mno-check-zero-division-mdivide-traps-mdivide-breaks-mload-store-pairs-mno-load-store-pairs-mmemcpy-mno-memcpy-mlong-calls-mno-long-calls-mmad-mno-mad-mimadd-mno-imadd-mfused-madd-mno-fused-madd-nocpp-mfix-24k-mno-fix-24k-mfix-r4000-mno-fix-r4000-mfix-r4400-mno-fix-r4400-mfix-r5900-mno-fix-r5900-mfix-r10000-mno-fix-r10000-mfix-rm7000-mno-fix-rm7000-mfix-vr4120-mno-fix-vr4120-mfix-vr4130-mno-fix-vr4130-mfix-sb1-mno-fix-sb1-mflush-func=func-mno-flush-func-mbranch-cost=num-mbranch-likely-mno-branch-likely-mcompact-branches=policy-mfp-exceptions-mno-fp-exceptions-mvr4130-align-mno-vr4130-align-msynci-mno-synci-mlxc1-sxc1-mno-lxc1-sxc1-mmadd4-mno-madd4-mrelax-pic-calls-mno-relax-pic-calls-mmcount-ra-address-mframe-header-opt-mno-frame-header-opt
๐ MMIX Options ๐
Next up, the MMIX crew ๐ง Same deal, just the names on this page.
-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 ๐
The MN10300 options, bestie ๐
-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 ๐
Moxie gets four flags, and they're all right here ๐ซถ
-meb-mel-mmul.x-mno-crt0
๐ธ MSP430 Options ๐ธ
MSP430 is giving a whole buffet of flags ๐ฐ
-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 ๐ซง
NDS32, the squad is big and I'm obsessed ๐ฅ
-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 ๐ง
Nios II, the longest list of the bunch and still slaying ๐
-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 ๐
Three flags, very power-move energy โญ
-m64-mmainkernel-moptimize
๐ OpenRISC Options ๐
OpenRISC, let's go ๐
-mboard=name-mnewlib-mhard-mul-mhard-div-msoft-mul-msoft-div-msoft-float-mhard-float-mdouble-float-munordered-float-mcmov-mror-mrori-msext-msfimm-mshftimm
๐ฆ PDP-11 Options ๐ฆ
PDP-11, a whole retro era, iykyk ๐
-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 ๐ท
picoChip, four flags and a whole vibe ๐ฆ
-mae=ae_type-mvliw-lookahead=N-msymbol-as-address-mno-inefficient-warnings
โก PowerPC Options โก
No list of its own, bestie. PowerPC is all tucked into the RS/6000 section
See RS/6000 and PowerPC Options.
๐ชฒ PRU Options ๐ชฒ
PRU, small but mighty ๐ฅ
-mmcu=mcu-minrt-mno-relax-mloop-mabi=variant
๐ฟ RISC-V Options ๐ฟ
RISC-V is a whole main character with a long list of flags, and I'm here for it ๐
-mbranch-cost=N-instruction-mplt-mno-plt-mabi=ABI-string-mfdiv-mno-fdiv-mdiv-mno-div-march=ISA-string-mtune=processor-string-mpreferred-stack-boundary=num-msmall-data-limit=N-bytes-msave-restore-mno-save-restore-mshorten-memrefs-mno-shorten-memrefs-mstrict-align-mno-strict-align-mcmodel=medlow-mcmodel=medany-mexplicit-relocs-mno-explicit-relocs-mrelax-mno-relax-mriscv-attribute-mmo-riscv-attribute-malign-data=type-mbig-endian-mlittle-endian+-mstack-protector-guard=guard-mstack-protector-guard-reg=reg+-mstack-protector-guard-offset=offset
๐ฌ RL78 Options ๐ฌ
RL78 has its own little lineup, and it's sweet ๐ญ
-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, the main event, the whole PowerPC universe โจ
-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 ๐
RX is the next stop on the train, choo choo ๐
-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 ๐๏ธ
S/390 and zSeries, a classic with a long guest list ๐ฉ
-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 ๐ป
Score, nine flags and a sunny attitude โ๏ธ
-meb-mel-mnhwloop-muls-mmac-mscore5-mscore5u-mscore7-mscore7d
๐ SH Options ๐
SH has a huge lineup and every single one is giving ๐
-m1-m2-m2e-m2a-nofpu-m2a-single-only-m2a-single-m2a-m3-m3e-m4-nofpu-m4-single-only-m4-single-m4-m4a-nofpu-m4a-single-only-m4a-single-m4a-m4al-mb-ml-mdalign-mrelax-mbigtable-mfmovd-mrenesas-mno-renesas-mnomacsave-mieee-mno-ieee-mbitops-misize-minline-ic_invalidate-mpadstruct-mprefergot-musermode-multcost=number-mdiv=strategy-mdivsi3_libfunc=name-mfixed-range=register-range-maccumulate-outgoing-args-matomic-model=atomic-model-mbranch-cost=num-mzdcbranch-mno-zdcbranch-mcbranch-force-delay-slot-mfused-madd-mno-fused-madd-mfsca-mno-fsca-mfsrra-mno-fsrra-mpretend-cmove-mtas
โ๏ธ Solaris 2 Options โ๏ธ
Solaris 2, a short and sweet set ๐
-mclear-hwcap-mno-clear-hwcap-mimpure-text-mno-impure-text-pthreads
๐ SPARC Options ๐
SPARC has a huge closet of flags and I'm obsessed ๐
-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 ๐
System V, the classic finale of this bunch ๐
-Qy-Qn-YP,paths-Ym,dir
๐ TILE-Gx Options ๐
TILE-Gx, out of this world and totally iconic ๐ธ
-mcpu=CPU-m32-m64-mbig-endian-mlittle-endian-mcmodel=code-model
๐ TILEPro Options ๐
Last but not least, TILEPro, the cherry on top ๐๐
-mcpu=cpu-m32
๐ฆ V850 Options ๐ฆ
Okay so the V850 squad is up first, bestie ๐ Here's the whole lineup:
-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 ๐ธ
Three little flags, and they're all giving main character energy โจ
-mg -mgnu -munix
๐ Visium Options ๐
-mdebug -msim -mfpu -mno-fpu -mhard-float
-msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
๐ VMS Options ๐
-mvms-return-codes -mdebug-main=prefix -mmalloc64
-mpointer-size=size
๐ VxWorks Options ๐
-mrtp -non-static -Bstatic -Bdynamic -Xbind-lazy
-Xbind-now
๐ x86 Options ๐
Okay this one is LONG, bestie ๐ญ Grab a snack, it's a whole buffet of flags:
-mtune=cpu-type -march=cpu-type -mtune-ctrl=feature-list
-mdump-tune-features -mno-default -mfpmath=unit -masm=dialect
-mno-fancy-math-387 -mno-fp-ret-in-387 -m80387 -mhard-float
-msoft-float -mno-wide-multiply -mrtd -malign-double
-mpreferred-stack-boundary=num -mincoming-stack-boundary=num -mcld
-mcx16 -msahf -mmovbe -mcrc32 -mmwait -mrecip -mrecip=opt
-mvzeroupper -mprefer-avx128 -mprefer-vector-width=opt -mmmx
-msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx
-mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd -mavx512vl
-mavx512bw -mavx512dq -mavx512ifma -mavx512vbmi -msha -maes
-mpclmul -mfsgsbase -mrdrnd -mf16c -mfma -mpconfig -mwbnoinvd
-mptwrite -mprefetchwt1 -mclflushopt -mclwb -mxsavec -mxsaves
-msse4a -m3dnow -m3dnowa -mpopcnt -mabm -mbmi -mtbm -mfma4
-mxop -madx -mlzcnt -mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm
-mhle -mlwp -mmwaitx -mclzero -mpku -mthreads -mgfni -mvaes
-mwaitpkg -mshstk -mmanual-endbr -mforce-indirect-call
-mavx512vbmi2 -mavx512bf16 -menqcmd -mvpclmulqdq -mavx512bitalg
-mmovdiri -mmovdir64b -mavx512vpopcntdq -mavx5124fmaps
-mavx512vnni -mavx5124vnniw -mprfchw -mrdpid -mrdseed -msgx
-mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8
-mamx-bf16 -muintr -mhreset -mavxvnni -mcldemote -mms-bitfields
-mno-align-stringops -minline-all-stringops
-minline-stringops-dynamically -mstringop-strategy=alg -mkl
-mwidekl -mmemcpy-strategy=strategy -mmemset-strategy=strategy
-mpush-args -maccumulate-outgoing-args -m128bit-long-double
-m96bit-long-double -mlong-double-64 -mlong-double-80
-mlong-double-128 -mregparm=num -msseregparm -mveclibabi=type
-mvect8-ret-in-mem -mpc32 -mpc64 -mpc80 -mdaz-ftz -mstackrealign
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs
-mcmodel=code-model -mabi=name -maddress-mode=mode -m32 -m64
-mx32 -m16 -miamcu -mlarge-data-threshold=num -msse2avx -mfentry
-mrecord-mcount -mnop-mcount -m8bit-idiv -minstrument-return=type
-mfentry-name=name -mfentry-section=name
-mavx256-split-unaligned-load -mavx256-split-unaligned-store
-malign-data=type -mstack-protector-guard=guard
-mstack-protector-guard-reg=reg
-mstack-protector-guard-offset=offset
-mstack-protector-guard-symbol=symbol -mgeneral-regs-only
-mcall-ms2sysv-xlogues -mindirect-branch=choice
-mfunction-return=choice -mindirect-branch-register
-mharden-sls=choice -mindirect-branch-cs-prefix -mneeded
๐ซถ x86 Windows Options ๐ซถ
-mconsole -mcygwin -mno-cygwin -mdll
-mnop-fun-dllimport -mthread -municode -mwin32 -mwindows
-fno-set-stack-executable
โญ Xstormy16 Options โญ
-msim
๐ธ Xtensa Options ๐ธ
-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 ๐ง
See S/390 and zSeries Options. The zSeries flags live over there, bestie, so go check them out ๐
๐ Options Controlling the Kind of Output ๐
Okay so compilation can involve up to four stages: preprocessing, compilation proper, assembly and linking, always in that order โจ GCC can preprocess and compile several files into several assembler input files, or into one assembler input file. Then each assembler input file produces an object file, and linking combines all the object files (the ones newly compiled and the ones you passed in) into an executable file. It's giving teamwork ๐ซถ
For any given input file, the file name suffix decides what kind of compilation happens. Here's the cheat sheet:
file.cโ C source code that must be preprocessed.file.iโ C source code that should not be preprocessed.file.iiโ C++ source code that should not be preprocessed.file.mโ Objective-C source code. Heads up, you must link with the libobjc library 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. You must link with the libobjc library to make an Objective-C++ program 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 to be turned into a precompiled header (default), or a C or C++ header file to be turned into an Ada spec (via the-fdump-ada-specswitch) ๐ธfile.cc,file.cp,file.cxx,file.cpp,file.CPP,file.c++,file.Cโ C++ source code that must be preprocessed. Note that in.cxx, the last two letters must both be literallyx. Likewise,.Cmeans a literal capital C ๐ฆfile.mm,file.Mโ Objective-C++ source code that must be preprocessed.file.miiโ Objective-C++ source code that should not be preprocessed.file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ header file to be turned into a precompiled header or Ada spec.file.f,file.for,file.ftnโ Fixed form Fortran source code that should not be preprocessed.file.F,file.FOR,file.fpp,file.FPP,file.FTNโ Fixed form Fortran source code that must be preprocessed (with the traditional preprocessor).file.f90,file.f95,file.f03,file.f08โ Free form Fortran source code that should not be preprocessed.file.F90,file.F95,file.F03,file.F08โ Free form Fortran source code that must be preprocessed (with the traditional preprocessor).file.goโ Go source code ๐ฉตfile.brigโ BRIG files (binary representation of HSAIL).file.dโ D source code.file.diโ D interface file.file.ddโ D documentation code (Ddoc).file.adsโ Ada source code file that contains a library unit declaration (a declaration of a package, subprogram, or generic, or a generic instantiation), or a library unit renaming declaration (a package, generic, or subprogram renaming declaration). These files are also called specs ๐file.adbโ Ada source code file containing a library unit body (a subprogram or package body). These files are also called bodies.file.sโ Assembler code.file.S,file.sxโ Assembler code that must be preprocessed.otherโ An object file to be fed straight into linking. Any file name with no recognized suffix is treated this way ๐ง
You can also spell out the input language yourself with the -x option, which is honestly so handy ๐
-x languageโ Explicitly sets the language for the following input files, instead of letting the compiler pick a default based on the file name suffix. This applies to all following input files until the next-xoption. The possible values for language are:
c c-header cpp-output
c++ c++-header c++-system-header c++-user-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
ada
d
f77 f77-cpp-input f95 f95-cpp-input
go
brig
-x noneโ Turns off any language specification, so later files are handled by their file name suffixes, just like they would be if-xhad never been used at all.
If you only want some of the stages, use -x (or the filename suffixes) to tell gcc where to start, and one of the options -c, -S, or -E to say where gcc should stop. Be careful, though: some combinations, like -x cpp-output -E, instruct gcc to do nothing at all ๐ญ
-cโ Compiles or assembles the source files, but does not link. The linking stage simply doesn't happen, so the final 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.
-Sโ Stops after the compilation proper stage and does not assemble. The output is an assembler code file for each non-assembler input file you specify.
By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s.
Input files that don't require compilation are ignored.
-Eโ Stops after the preprocessing stage and does not run the compiler proper. The output is preprocessed source code, which gets sent to the standard output.
Input files that don't require preprocessing are ignored.
-o fileโ Places the primary output infile. This works for whatever you're producing, whether that's an executable file, an object file, an assembler file, or preprocessed C code ๐
If you don't specify -o, the default is to put an executable file in a.out, the object file for source.suffix in source.o, its assembler file in source.s, a precompiled header file in source.suffix.gch, and all preprocessed C source on standard output ๐
Okay so, even though -o only names the main output, it's also secretly in charge of naming the aux and dump outputs ๐๐ Unless you override it, those extras get parked in the same folder as your primary output ๐
For aux outputs, the input file's suffix gets swapped out for the aux file type's suffix. For dump outputs, the dump file's suffix gets tacked onto the input file's suffix โจ In compilation commands, both aux and dump outputs borrow the base name of the primary output. In compile-and-link commands, the primary output name (minus the executable suffix) gets combined with the input file name ๐ฆ If both end up with the same base name (ignoring the suffix), the result is just that base name. If they don't match, they get joined with a dash.
gcc -c foo.c ...
This will use foo.o as the primary output and drop the aux outputs and dumps right next to it. For example, you get the aux file foo.dwo for -gsplit-dwarf, and the dump file foo.c.???r.final for -fdump-rtl-final ๐ง
If you explicitly specify a non-linker output file, the aux and dump files take the same base name by default ๐
gcc -c foo.c -o dir/foobar.o ...
This will name the aux outputs dir/foobar.* and the dump outputs dir/foobar.c.* ๐ธ
A linker output works differently and prefixes the aux and dump outputs instead ๐
gcc foo.c bar.c -o dir/foobar ...
This will generally name the aux outputs dir/foobar-foo.* and dir/foobar-bar.*, and the dump outputs dir/foobar-foo.c.* and dir/foobar-bar.c.* ๐ซถ
There's one exception, and it's iconic. If the executable shares its base name with the single input, the naming goes back to normal ๐
gcc foo.c -o dir/foo ...
In that case the aux outputs are named dir/foo.* and the dump outputs are named dir/foo.c.* ๐
You can tweak the location and names of the aux and dump outputs with the options -dumpbase, -dumpbase-ext, -dumpdir, -save-temps=cwd, and -save-temps=obj โจ
๐ -dumpbase dumpbase
This option sets the base name for the aux and dump output files. It does not change the name of the primary output file ๐ฆ Intermediate outputs, when they're preserved, aren't treated as primary outputs. They count as aux outputs instead ๐
gcc -save-temps -S foo.c
This saves the (no longer) temporary preprocessed file as foo.i, then compiles to the (implied) output file foo.s. Compare that with:
gcc -save-temps -dumpbase save-foo -c foo.c
This preprocesses into save-foo.i, compiles to save-foo.s (which is now an intermediate, and therefore an aux output), and then assembles to the (implied) output file foo.o ๐
Without this option, the dump and aux files take their names from the input file, or from the (non-linker) output file if you explicitly specified one. Dump output files (like the ones requested by -fdump-* options) keep the input name suffix. Aux output files (the ones requested by other non-dump options, like -save-temps, -gsplit-dwarf, or -fcallgraph-info) drop it ๐
You can get similar suffix differentiation for dump and aux outputs with an explicit -dumpbase basename.suf by also specifying -dumpbase-ext .suf ๐
If dumpbase is explicitly given with any directory component, then any dumppfx specification (like -dumpdir or -save-temps=*) gets ignored. The dumpbase fully overrides it instead of getting appended to it ๐
gcc foo.c -c -o dir/foo.o -dumpbase alt/foo \
-dumpdir pfx- -save-temps=cwd ...
This creates aux and dump outputs named alt/foo.*. It disregards the dir/ in -o, the ./ prefix implied by -save-temps=cwd, and the pfx- in -dumpdir ๐ญ
When -dumpbase is used in a command that compiles multiple inputs, or that compiles and then links, it can be combined with a dumppfx, same as under -dumpdir. Then each input file gets compiled using the combined dumppfx, and the default values for dumpbase and auxdropsuf get computed for each input file ๐ง
gcc foo.c bar.c -c -dumpbase main ...
This creates foo.o and bar.o as primary outputs. It also avoids overwriting the aux and dump outputs by using the dumpbase as a prefix, so you get aux and dump outputs named main-foo.* and main-bar.* ๐ซถ
An empty string given as the dumpbase keeps the output basename from influencing 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 the aux outputs dir/foo.* and the dump outputs dir/foo.c.*. Notice how their 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 ๐ฆ
gcc foo.c bar.c -o dir/foobar -dumpbase " -flto ...
The compilation of the source files names the aux outputs dir/foo.* and dir/bar.*, and the dump outputs dir/foo.c.* and dir/bar.c.*. The LTO recompilation during linking uses dir/foobar as the prefix for dumps and aux files ๐
๐ -dumpbase-ext auxdropsuf
When forming the name of an auxiliary output file (but not a dump output file), this option drops the trailing auxdropsuf from the dumpbase before any suffixes get appended ๐ If you don't specify it, it defaults to the suffix of a default dumpbase. That means the suffix of the input file when -dumpbase isn't on the command line, or when the dumpbase is combined with a dumppfx โจ
gcc foo.c -c -o dir/foo.o -dumpbase x-foo.c -dumpbase-ext .c ...
This creates dir/foo.o as the main output. It generates aux outputs in dir/x-foo.*, using the location of the primary output and dropping the .c suffix from the dumpbase. Dump outputs keep the suffix, so you get dir/x-foo.c.* ๐ฆ
This option gets disregarded if it doesn't match the suffix of a specified dumpbase. The one exception is when it acts as an alternative to the executable suffix while the linker output base name is being appended to dumppfx, as described below ๐
gcc foo.c bar.c -o main.out -dumpbase-ext .out ...
This creates main.out as the primary output. It avoids overwriting the aux and dump outputs by using the executable name minus auxdropsuf as a prefix. That gives you aux outputs named main-foo.* and main-bar.*, and dump outputs named main-foo.c.* and main-bar.c.* ๐
๐ธ -dumpdir dumppfx
When forming the name of an auxiliary or dump output file, this option 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 named pfx-foo.c.* ๐ซถ
If you want to use dumppfx as a directory name, it has to end with a directory separator ๐
gcc -dumpdir dir/ -c foo.c -o obj/bar.o ...
This creates obj/bar.o as the primary output and auxiliary outputs named dir/bar.*. It combines the given dumppfx with the default dumpbase derived from the primary output name. Dump outputs take the input name suffix too, so they're named dir/bar.c.* ๐
By default, the dumppfx is the location of the output file. The exception is when the output is a special file like "/dev/null". The options -save-temps=cwd and -save-temps=obj override this default, just like an explicit -dumpdir option does. If you give several of these, 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 give -dumpbase, the dumpbase (minus an auxdropsuf suffix) and a dash get appended to the explicit or defaulted dumppfx. If the dumpbase contains any directory components, it overrides the dumppfx instead. Either way, each of the multiple compilations ends up with differently-named aux and dump outputs ๐ฆ
gcc foo.c bar.c -c -dumpdir dir/pfx- -dumpbase main ...
This sends the auxiliary dumps to dir/pfx-main-foo.* and dir/pfx-main-bar.*, appending dumpbase- to the dumppfx. Dump outputs keep the input file suffix, so you get dir/pfx-main-foo.c.* and dir/pfx-main-bar.c.*, respectively ๐
Now contrast that with the single-input version:
gcc foo.c -c -dumpdir dir/pfx- -dumpbase main ...
Applying -dumpbase to a single source doesn't compute and append a separate dumpbase per input file. Its aux and dump outputs go in dir/pfx-main.* ๐ง
When you compile and then link from multiple input files, a defaulted or explicit dumppfx also goes through the dumpbase- transformation from above. The example would be the compilation of foo.c and bar.c from earlier, just without -c. If you give neither -dumpdir nor -dumpbase, then the linker output base name gets appended to the default dumppfx instead. Before that happens, the base name has the auxdropsuf removed if you specified one. Otherwise the executable suffix gets removed. Then a dash gets added ๐ซถ
Here's the twist, though. Unlike the earlier linking cases, this one doesn't work the same way:
gcc foo.c bar.c -dumpdir dir/pfx- -o main ...
This does not append the output name main to the dumppfx, because -dumpdir was explicitly specified. The idea is that an explicitly specified dumppfx can include the output name as part of its prefix, if you want that. Only an explicitly specified -dumpbase gets combined with it, so you don't accidentally throw away a meaningful option ๐
When you compile and then link from a single input file, the linker output base name gets appended to the default dumppfx (as described above) only if it doesn't share its base name with the single input file name. That covers the single-input linking cases from earlier. It doesn't cover an explicit -dumpdir that stops the combination from happening, even if -save-temps=* overrides it later:
gcc foo.c -dumpdir alt/pfx- -o dir/main.exe -save-temps=cwd ...
In this case, the auxiliary outputs are named foo.* and the dump outputs are named foo.c.*. They end up in the current working directory, as -save-temps=cwd ultimately requests ๐ธ
Okay so, here's the naming situation all in one place (it's a little simplified, but it gets the vibe across ๐
). The main output name gets split into a directory part and a basename part ๐ฆ. The directory part becomes dumppfx, unless you've overridden it with -dumpdir or -save-temps=*. The basename becomes dumpbase, unless you've overridden it with -dumpbase ๐ซถ. If there are multiple inputs or you're linking, dumpbase can get combined with dumppfx and pulled from each input file โจ. Auxiliary output names for each input are built by smooshing together dumppfx, dumpbase minus its suffix, and the auxiliary output suffix ๐. Dump output names are almost the same thing, except the suffix from dumpbase gets to stay ๐.
Now for LTO recompilation ๐. A combo of dumppfx and dumpbase gets passed down to lto-wrapper as a -dumpdir option, with a trailing period swapped in for the compiler-added dash (if there is one). This happens whether that combo is the one you gave, or one derived from the linker output name and not from the inputs, and even when it wouldn't normally be used that way ๐ง. Since gcc is involved in linking, it doesn't normally get any -dumpbase or -dumpbase-ext, and it ignores them if they show up ๐.
When lto-wrapper runs sub-compilers ๐
, it adds the LTO stage names onto the dumppfx it received. It makes sure that thing has a directory component so it overrides any -dumpdir, then passes the result along as -dumpbase to the sub-compilers ๐.
-vโ Prints the commands run for each stage of compilation ๐ (on standard error output, bestie). It also shows the version number of the compiler driver program, plus the version of the preprocessor and the compiler proper ๐ฅ.-###โ Basically-v, except nothing actually runs ๐ โโ๏ธ. Arguments get wrapped in quotes unless they only contain alphanumeric characters or"./-_". This is super useful for shell scripts that want to capture the command lines the driver generates ๐.--helpโ Prints (on standard output) a rundown of the command-line optionsgccunderstands ๐. If-vis also there,--helpgets passed on to the other processes gcc invokes, so they can show the options they accept ๐ธ. If-Wextrawas specified before--help, then options with no documentation get shown too โจ.--target-helpโ Prints (on standard output) the target-specific command-line options for each tool ๐ฏ. For some targets, extra target-specific info might get printed too ๐ฆ.--help={class|[^]qualifier}[,...]โ Prints (on standard output) the options that fit into all the classes and qualifiers you list ๐. Here are the classes:optimizersโ every optimization option the compiler supports ๐.warningsโ every option that controls warning messages ๐จ.targetโ target-specific options ๐. Unlike--target-help, the linker's and assembler's target options don't show up here, since those tools don't support the extended--help=syntax yet ๐.paramsโ the values--paramrecognizes ๐.languageโ the options for language, which is any one of the languages this GCC version supports ๐. If an option works with every language, you need to pick thecommonclass instead.commonโ the options shared by all languages ๐ซถ.
And here are the qualifiers:
undocumentedโ only the options with no documentation ๐ซฅ.joinedโ options that take an argument right after an equal sign, in the same chunk of text, like--help=target๐งฉ.separateโ options that take an argument as a separate word after the original option, like-o output-file๐.
Want every undocumented target-specific switch the compiler supports? Use:
--help=target,undocumented
You can flip a qualifier by putting ^ in front of it. So to show all the binary warning options (the ones that are either on or off and don't take an argument) that do have a description, use:
--help=warnings,^joined,^undocumented
The argument to --help= can't be made up only of inverted qualifiers, so don't try that ๐
โโ๏ธ. Combining several classes is possible, but it usually narrows the output so much there's nothing left to show ๐ญ. One combo that actually works is pairing target with another class. To see all the target-specific optimization options, use:
--help=target,optimizers
You can repeat --help= on the command line. Each use displays its requested class and skips anything already shown ๐. If --help is also anywhere on the command line, it beats any --help= option ๐.
If -Q shows up on the command line before --help=, the descriptive text changes ๐ช. Instead of describing the options, it tells you whether each one is enabled, disabled, or set to a specific value (as long as the compiler knows that at the point where --help= is used). Here's a truncated example from the ARM port of gcc:
% gcc -Q -mabi=2 --help=target -c
The following options are target specific:
-mabi= 2
-mabort-on-noreturn [disabled]
-mapcs [disabled]
The output depends on earlier options, so you can find out which optimizations are enabled at -O2 with:
-Q -O2 --help=optimizers
Or, if you want to see which binary optimizations -O3 enables, you can do:
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โ Shows the version number and copyright info of the GCC you invoked ๐.-pass-exit-codesโ Normallygccexits with code 1 if any phase of the compiler returns a non-success code ๐ฌ. With-pass-exit-codes, it instead returns the numerically highest error from any phase that gave back an error indication ๐. The C, C++, and Fortran front ends return 4 if they run into an internal compiler error ๐.-pipeโ Uses pipes instead of temporary files to pass stuff between compilation stages ๐ฐ. This fails on some systems where the assembler can't read from a pipe, but the GNU assembler has zero trouble with it ๐ .-specs=fileโ Processes file after the compiler reads in the standard specs file ๐. This lets you override the defaults that thegccdriver uses when figuring out which switches to pass tocc1,cc1plus,as,ld, and so on ๐ง. You can use more than one-specs=file, and they get processed in order, from left to right โก๏ธ.-wrapperโ Runs all subcommands under a wrapper program ๐. The wrapper's name and its parameters go in as a comma-separated list. For example:
gcc -c t.c -wrapper gdb,--args
That runs every gcc subprogram under gdb --args, so the cc1 invocation becomes gdb --args cc1 .... ๐.
-ffile-prefix-map=old=newโ When you compile files living in directory old, any references to them in the compilation result get recorded as if those files lived in directory new instead ๐บ๏ธ. Using this is the same as specifying all the individual-f*-prefix-mapoptions. It's handy for reproducible, location-independent builds ๐ซถ. See also-fmacro-prefix-mapand-fdebug-prefix-map๐.-fplugin=name.soโ Loads the plugin code from name.so, which is assumed to be a shared object the compiler willdlopen๐งฉ. The base name of the shared object file is what identifies the plugin when arguments get parsed (see-fplugin-arg-name-key=valuebelow). Each plugin should define the callback functions listed in the Plugins API ๐.-fplugin-arg-name-key=valueโ Defines an argument called key with a value of value for the plugin called name ๐.-fdump-ada-spec[-slim]โ For C and C++ source and include files, generates the matching Ada specs ๐ท.-fada-spec-parent=unitโ Used together with-fdump-ada-spec[-slim]above, this generates the Ada specs as child units of the parent unit ๐ถ.-fdump-go-spec=fileโ For input files in any language, generates the matching Go declarations in file ๐น. That means Goconst,type,var, andfuncdeclarations, which can be a great way to kick off writing a Go interface to code written in another language ๐.@fileโ Reads command-line options from file โ๏ธ. The options read get inserted right where the original@fileoption was, and that@fileis no longer there. If file doesn't exist or can't be read, then@filegets treated literally and is not removed ๐.
Options inside file are separated by whitespace. To include a whitespace character in an option, wrap the entire option in single or double quotes. To include any character (even a backslash), put a backslash in front of it. The file can contain more @file options too, and those get processed recursively ๐.
โจ Compiling C++ Programs โจ
C++ source files usually end in .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx ๐. C++ header files often end in .hh, .hpp, .H, or (for shared template code) .tcc ๐ซง, and preprocessed C++ files use the .ii suffix ๐ธ. GCC recognizes files with these names and compiles them as C++ programs, even if you call the compiler the same way you would for C programs (usually with the name gcc) ๐.
However, using gcc doesn't pull in the C++ library, bestie ๐ That's where g++ comes in. It's a program that calls GCC and automatically links against the C++ library ๐ It treats .c, .h and .i files as C++ source files instead of C source files, unless you use -x. It's also super useful for precompiling a C header file with a .h extension for use in C++ compilations ๐ง On many systems, g++ is also installed under the name c++ โจ
When you compile C++ programs, you can use lots of the same command-line options you'd use for any language ๐ You can also use options meant for C and related languages, or options that only matter for C++ programs. Main character energy, honestly ๐
๐ Options Controlling C Dialect ๐
The following options control the dialect of C (or languages derived from C, like C++, Objective-C and Objective-C++) that the compiler accepts ๐
-ansiโ okay, this one's a whole vibe. In C mode it's 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 the
asmandtypeofkeywords, plus predefined macros likeunixandvaxthat tell you what kind of system you're on ๐ It also turns on the undesirable, rarely used ISO trigraph feature. For the C compiler, it also disables recognition of C++ style//comments and theinlinekeyword. - The alternate keywords
__asm__,__extension__,__inline__and__typeof__still work with-ansiโจ You wouldn't want them in an ISO C program, obviously, but they're handy in header files that might get included in compilations done with-ansi. The alternate predefined macros__unix__and__vax__are available with or without-ansi๐ฆ -ansidoesn't reject non-ISO programs out of nowhere. For that, you need-Wpedanticin addition to-ansi๐- The macro
__STRICT_ANSI__is predefined when-ansiis used. Some header files notice it and skip declaring certain functions or defining certain macros that the ISO standard doesn't ask for, so they don't mess with programs using those names for other stuff ๐ซถ - Functions that are normally built in but don't have ISO C semantics, like
allocaandffs, are not built-in functions when-ansiis used ๐ฅ
- It turns off GCC features that clash with ISO C90 (for C code) or standard C++ (for C++ code), like the
-std=โ determines the language standard. This is only supported when compiling C or C++ ๐- The compiler can accept base standards like
c90orc++98, plus GNU dialects of those, likegnu90orgnu++98๐ With a base standard, it accepts all programs following that standard plus GNU extensions that don't contradict it. For example,-std=c90turns off GCC features that are incompatible with ISO C90, likeasmandtypeof, but keeps other GNU extensions that don't mean anything in ISO C90, like omitting 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. As a result, some strictly conforming programs may be rejected ๐ญ
-Wpedanticuses the standard to figure out which features are GNU extensions for that version. For example,-std=gnu90 -Wpedanticwarns about C++ style//comments, while-std=gnu99 -Wpedanticdoes not ๐- A value for this option must be provided. Possible values are:
c90,c89,iso9899:1990โ supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code.iso9899:199409โ ISO C90 as modified in amendment 1.c99,c9x,iso9899:1999,iso9899:199xโ ISO C99. 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<http://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). It's the same as C11 except for corrections of defects (all of which are also applied with-std=c11) and a new value of__STDC_VERSION__, so it's supported to the same extent as C11 โจc2xโ the next version of the ISO C standard, still under development. Support for this version is experimental and incomplete ๐งชgnu90,gnu89โ GNU dialect of ISO C90 (including some C99 features) ๐ธgnu99,gnu9xโ GNU dialect of ISO C99. The namegnu9xis deprecated.gnu11,gnu1xโ GNU dialect of ISO C11. The namegnu1xis deprecated.gnu17,gnu18โ GNU dialect of ISO C17. This is the default for C code ๐gnu2xโ the next version of the ISO C standard, still under development, plus GNU extensions. Support for this version is experimental and incomplete.c++98,c++03โ the 1998 ISO C++ standard plus the 2003 technical corrigendum and some additional defect reports. Same as-ansifor C++ code.gnu++98,gnu++03โ GNU dialect of-std=c++98.c++11,c++0xโ the 2011 ISO C++ standard plus amendments. The namec++0xis deprecated.gnu++11,gnu++0xโ GNU dialect of-std=c++11. The namegnu++0xis deprecated.c++14,c++1yโ the 2014 ISO C++ standard plus amendments. The namec++1yis deprecated.gnu++14,gnu++1yโ GNU dialect of-std=c++14. The namegnu++1yis deprecated.c++17,c++1zโ the 2017 ISO C++ standard plus amendments. The namec++1zis deprecated.gnu++17,gnu++1zโ GNU dialect of-std=c++17. This is the default for C++ code. The namegnu++1zis deprecated.c++20,c++2aโ the 2020 ISO C++ standard plus amendments. Support is experimental and could change in incompatible ways in future releases. The namec++2ais deprecated.gnu++20,gnu++2aโ GNU dialect of-std=c++20. Support is experimental and could change in incompatible ways in future releases. The namegnu++2ais deprecated.c++2b,c++23โ the next revision of the ISO C++ standard, planned for 2023. Support is highly experimental and will almost certainly change in incompatible ways in future releases โ ๏ธgnu++2b,gnu++23โ GNU dialect of-std=c++2b. Support is highly experimental, and will almost certainly change in incompatible ways in future releases.
- The compiler can accept base standards like
-fgnu89-inlineโ tells GCC to use the traditional GNU semantics forinlinefunctions when in C99 mode ๐ฆ- Using this option is roughly equivalent to adding the
gnu_inlinefunction attribute to all inline functions. - The option
-fno-gnu89-inlineexplicitly tells GCC to use the C99 semantics forinlinewhen in C99 orgnu99mode (i.e., it specifies the default behavior). This option is not supported in-std=c90or-std=gnu90mode. - The preprocessor macros
__GNUC_GNU_INLINE__and__GNUC_STDC_INLINE__may be used to check which semantics are in effect forinlinefunctions ๐
- Using this option is roughly equivalent to adding the
-fpermitted-flt-eval-methods=styleโ okay, this one's a brain-melt, but stay with me ๐ง ISO/IEC TS 18661-3 defines new permissible values forFLT_EVAL_METHODthat indicate 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. These new values are a superset of those permitted under C99/C11, which doesn't specify the meaning of other positive values ofFLT_EVAL_METHOD. So code conforming to C11 may not have been written expecting the new values ๐ฅบ-fpermitted-flt-eval-methodsspecifies whether the compiler should allow only theFLT_EVAL_METHODvalues specified in C99/C11, or the extended set of values specified in ISO/IEC TS 18661-3.styleis eitherc11orts-18661-3, as appropriate.- The default in a standards-compliant mode (
-std=c11or similar) is-fpermitted-flt-eval-methods=c11. The default in a GNU dialect (-std=gnu11or similar) is-fpermitted-flt-eval-methods=ts-18661-3.
-aux-info filenameโ outputs to the given filename prototyped declarations for all functions declared and/or defined in a translation unit, including those in header files ๐ This option is silently ignored in any language other than C.- Besides declarations, the file indicates, in comments, the origin of each declaration (source file and line), whether the declaration was implicit, prototyped or unprototyped (
I,Nfor new orOfor old, respectively, in the first character after the line number and the colon), and whether it came from a declaration or a definition (CorF, respectively, in the following character). - For function definitions, a K&R-style list of arguments followed by their declarations is also provided, inside comments, after the declaration ๐
- Besides declarations, the file indicates, in comments, the origin of each declaration (source file and line), whether the declaration was implicit, prototyped or unprototyped (
-fallow-parameterless-variadic-functionsโ accepts variadic functions without named parameters ๐- Sure, you can define one, but it's not very useful since you can't read the arguments ๐ This is only supported for C, since C++ already allows this construct.
-fno-asm: okay bestie, this one's giving "let me use your words." It stops GCC from treatingasm,inlineortypeofas keywords, so your code can use those words as identifiers ๐ซถ. If you still want the keyword powers, use__asm__,__inline__and__typeof__instead ๐ .-ansiimplies-fno-asm.
In C++, this switch only affects the typeof keyword, since asm and inline are standard keywords ๐ง. You may want to use the -fno-gnu-keywords flag instead, which has the same effect โจ. 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: don't recognize built-in functions that don't start with__builtin_as a prefix ๐.
Okay so 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 show up as calls, you cannot set a breakpoint on them, nor can you change how the functions behave by linking with a different library ๐. Also, when a function is recognized as a built-in, GCC may use info about it to warn you about sketchy calls, or to generate more efficient code, even if the result still contains calls to that function ๐. For example, you get warnings with -Wformat for bad calls to printf when printf is built in, and when strlen is known not to modify global memory ๐ฆ.
With -fno-builtin-function, only the built-in function function gets disabled. function must not begin with __builtin_. If you name a function that isn't built-in in this version of GCC, this option is ignored ๐. There is no matching -fbuiltin-function option. If you want to pick and choose built-in functions when using -fno-builtin or -ffreestanding, you can define macros like these:
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fgimple: enables parsing of function definitions marked with__GIMPLE. This is an experimental feature for unit testing GIMPLE passes ๐งช.-fhosted: asserts that compilation targets a hosted environment, and this implies-fbuiltin. A hosted environment is one where the entire standard library is available, and wheremainhas a return type ofint. Examples are basically everything except a kernel ๐. This is equivalent to-fno-freestanding.-ffreestanding: asserts that compilation targets a freestanding environment, and this implies-fno-builtin. A freestanding environment is one where the standard library may not exist, and program startup may not necessarily begin atmain. The most obvious example is an OS kernel ๐ง . This is equivalent to-fno-hosted.-fopenacc: enables handling of OpenACC directives,#pragma accin C/C++ and!$accin Fortran ๐. When you use-fopenacc, the compiler generates accelerated code according to the OpenACC Application Programming Interface v2.6 athttps://www.openacc.org. This option implies-pthread, so it's only supported on targets that support-pthread๐งต.-fopenacc-dim=geom: sets default compute dimensions for parallel offload regions that don't explicitly specify their own ๐. The geom value is a triple of:-separated sizes, in the order'gang','worker'and'vector'. You can leave a size out to use a target-specific default value ๐ซง.-fopenmp: enables handling of OpenMP directives,#pragma ompin C/C++ and!$ompin Fortran ๐. When you use-fopenmp, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5 athttps://www.openmp.org. This option implies-pthread, so it's only supported on targets that support-pthread.-fopenmpalso implies-fopenmp-simd๐.-fopenmp-simd: enables handling of OpenMP's SIMD directives written with#pragma ompin C/C++ and!$ompin Fortran. Other OpenMP directives get ignored ๐.-fgnu-tm: when you specify-fgnu-tm, the compiler generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009). This is an experimental feature whose interface may change in future versions of GCC, as the official specification changes ๐งช. Please note that not every architecture supports 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) ๐ซ.
-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;
};
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 x86 targets using ms-abi.
-fplan9-extensions: accepts some non-standard constructs used in Plan 9 code ๐.
This enables -fms-extensions, allows passing pointers to structures with anonymous fields to functions that expect pointers to elements of the field's type, and allows referring to anonymous fields declared using a typedef. This is only supported for C, not C++ ๐
โโ๏ธ.
-fcond-mismatch: allows conditional expressions with mismatched types in the second and third arguments. The value of such an expression isvoid. This option is not supported for C++ ๐ซ .-flax-vector-conversions: allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types. This option should not be used for new code ๐ฌ.-funsigned-char: lets the typecharbe unsigned, likeunsigned char๐.
Every kind of machine has a default for what char should be. It's either like unsigned char by default or like signed char by default ๐คทโโ๏ธ.
Ideally, a portable program should always use signed char or unsigned char when it depends on the signedness of an object. But plenty of programs were written to use plain char and expect it to be signed, or expect it to be unsigned, depending on the machines they were written for. This option, and its inverse, let you make those programs work with the opposite default ๐.
The type char is always a distinct type from each of signed char and unsigned char, even though its behavior is always just like one of those two ๐ฆ.
-fsigned-char: lets the typecharbe signed, likesigned charโญ.
This is equivalent to -fno-unsigned-char, which is the negative form of -funsigned-char. Likewise, the option -fno-signed-char is equivalent to -funsigned-char ๐.
-fsigned-bitfields,-funsigned-bitfields,-fno-signed-bitfields,-fno-unsigned-bitfields: these control whether a bit-field is signed or unsigned when the declaration doesn't use eithersignedorunsigned๐ฏ. By default, such a bit-field is signed, because that's consistent: basic integer types likeintare signed types ๐.-fsso-struct=endianness: sets the default scalar storage order of structures and unions to the specified endianness. The accepted values arebig-endian,little-endianandnative(the default), wherenativemeans the native endianness of the target. 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 only matter for C++ programs ๐. You can also use most of the GNU compiler options no matter what language your program is in ๐ธ. For example, you might compile a file firstClass.C like this:
g++ -g -fstrict-enums -O -c firstClass.C
In this example, only -fstrict-enums is an option meant only for C++ programs. You can use the other options with any language GCC supports ๐ซถ.
Some options for compiling C programs, such as -std, are also relevant for C++ programs ๐ง.
Here 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 0 refers to the version conforming most closely to the C++ ABI specification. That means the ABI you get from version 0 will change in different versions of G++ as ABI bugs get fixed ๐ ๏ธ.
Version 1 is the version of the C++ ABI that first appeared in G++ 3.2 ๐ฑ.
Version 2 is the version of the C++ ABI that first appeared in G++ 3.4, and it was the default through G++ 4.9 ๐.
Version 3 corrects an error in mangling a constant address as a template argument ๐ง.
Version 4, which first appeared in G++ 4.5, implements a standard mangling for vector types ๐ฆ.
Version 5, which first appeared in G++ 4.6, corrects the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and use of a function parameter in the declaration of another parameter ๐งฉ.
Version 6, which first appeared in G++ 4.7, corrects the promotion behavior of C++11 scoped enums and the mangling of template argument packs, const/static_cast, prefix ++ and --, and a class scope function used as a template argument ๐.
Version 7, which first appeared in G++ 4.8, that treats nullptr_t as a builtin type and corrects the mangling of lambdas in default argument scope ๐ญ.
Version 8, which first appeared in G++ 4.9, corrects the substitution behavior of function types with function-cv-qualifiers ๐
.
Version 9, which first appeared in G++ 5.2, corrects the alignment of nullptr_t โจ.
Version 10, which first appeared in G++ 6.1, adds mangling of attributes that affect type identity, such as ia32 calling convention attributes (e.g. stdcall) ๐ฆ.
- Version 11 ๐ (first showed up in G++ 7) fixes how
sizeof...expressions and operator names get mangled. Okay so for multiple entities with the same name inside one function that are declared in different scopes, the mangling changes starting with the twelfth occurrence ๐ It also implies-fnew-inheriting-ctors. - Version 12 ๐ญ (first showed up in G++ 8) fixes calling conventions for empty classes on the x86_64 target and for classes with only deleted copy/move constructors. Bestie, it also accidentally changes the calling convention for classes with a deleted copy constructor and a trivial move constructor.
- Version 13 ๐ซถ (first showed up in G++ 8.2) fixes that accidental change from version 12. Iconic redemption arc.
- Version 14 โจ (first showed up in G++ 10) corrects the mangling of the
nullptrexpression. - Version 15 ๐ฆ (first showed up in G++ 11) makes the mangling of
__alignof__distinct fromalignof, and also changes the mangling of dependent operator names.
Also, see -Wabi ๐
โจ OPTIONS โจ (continued)
-fabi-compat-version=n๐ธ โ On targets that support strong aliases, G++ works around mangling changes by creating an alias with the correct mangled name whenever it defines a symbol with an incorrect mangled name. This switch picks which ABI version the alias uses.- With
-fabi-version=0(the default), this defaults to11(GCC 7 compatibility). If you explicitly pick a different ABI version, it defaults to0. - For compatibility with GCC versions 3.2 through 4.9, use
-fabi-compat-version=2. - If this option isn't provided but
-Wabi=nis, that version is used for the compatibility aliases. If this option is provided along with-Wabi(without a version), the version from this option is used for the warning.
- With
-fno-access-control๐ โ Turns off all access checking. Mainly useful for working around bugs in the access control code, so it's a lowkey lifesaver for that specific situation.-faligned-new๐ โ Enables support for C++17newof types that need more alignment thanvoid* ::operator new(std::size_t)provides. You can pass a number like-faligned-new=32to say how much alignment (in bytes) that function provides, but few users will need to override the default ofalignof(std::max_align_t). This flag is enabled by default for-std=c++17.-fchar8_t,-fno-char8_t๐ โ Enables support forchar8_t, as adopted for C++20. This brings a newchar8_tfundamental type, changes to the types of UTF-8 string and character literals, new signatures for user-defined literals, associated standard library updates, and the new__cpp_char8_tand__cpp_lib_char8_tfeature test macros.
This option lets functions be overloaded for ordinary and UTF-8 strings:
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
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;
The change to the types of UTF-8 string and character literals introduces incompatibilities with ISO C++11 and later standards. For example, the following code is well-formed under ISO C++11, but is ill-formed when -fchar8_t is specified.
char ca[] = u8"xx"; // error: char-array initialized from wide
// string
const char *cp = u8"xx";// error: invalid conversion from
// `const char8_t*' to `const char*'
int f(const char*);
auto v = f(u8"xx"); // error: invalid conversion from
// `const char8_t*' to `const char*'
std::string s{u8"xx"}; // error: no matching function for call to
// `std::basic_string<char>::basic_string()'
using namespace std::literals;
s = u8"xx"s; // error: conversion from
// `basic_string<char8_t>' to non-scalar
// type `basic_string<char>' requested
-fcheck-new๐ โ Checks that the pointer returned byoperator newis non-null before it tries to modify the storage it allocated. This check is normally unnecessary, because the C++ standard saysoperator newonly returns 0 if it's declaredthrow(). In that case the compiler always checks the return value, even without this option. In all other cases, whenoperator newhas a non-empty exception specification, memory exhaustion is signalled by throwingstd::bad_alloc. See alsonew (nothrow).-fconcepts,-fconcepts-ts๐งฉ โ Below-std=c++20,-fconceptsenables support for the C++ Extensions for Concepts Technical Specification, ISO 19217 (2015).
With -std=c++20 and above, Concepts are part of the language standard, so -fconcepts defaults to on. But the standard's specification of Concepts differs significantly from the TS, so some constructs that were allowed in the TS but didn't make it into the standard can still be enabled with -fconcepts-ts.
-fconstexpr-depth=n๐ โ Sets the maximum nested evaluation depth for C++11constexprfunctions ton. A limit is needed to catch endless recursion during constant expression evaluation. The minimum the standard specifies is512.-fconstexpr-cache-depth=n๐ง โ Sets the maximum nested evaluation depth for C++11constexprfunctions that will be cached ton. This is a heuristic that trades compilation speed (when the cache avoids repeated calculations) against memory consumption (when the cache grows huge from highly recursive evaluations). The default is8. Very few users are likely to want to adjust it, but if your code does heavyconstexprcalculations, you might want to experiment to find which value works best for you.-fconstexpr-loop-limit=n๐ โ Sets the maximum number of iterations for a loop in C++14constexprfunctions ton. A limit is needed to catch infinite loops during constant expression evaluation. The default is262144(1<<18).-fconstexpr-ops-limit=nโฑ๏ธ โ Sets the maximum number of operations during a singleconstexprevaluation. Even when the number of iterations of a single loop is capped by the limit above, several nested loops that each have lots of iterations (but still fewer than that limit), or too many expressions to evaluate in a loop body or even outside a loop, can make theconstexprevaluation take too long. The default is33554432(1<<25).-fcoroutines๐งต โ Enables support for the C++ coroutines extension. This one is experimental, so proceed with main character energy and a little caution ๐-fno-elide-constructors๐ซ โ The C++ standard lets an implementation skip creating a temporary that's only used to initialize another object of the same type. Specifying this option disables that optimization and forces G++ to call the copy constructor in all cases. It also causes G++ to call trivial member functions that would otherwise be expanded inline.
In C++17, the compiler is required to omit these temporaries, but this option still affects trivial member functions.
-fno-enforce-eh-specsโ ๏ธ โ Don't generate code that checks for violations of exception specifications at run time. This option violates the C++ standard, but it may be useful for shrinking code size in production builds, kind of like definingNDEBUG. It does not give your code permission to throw exceptions in violation of the exception specifications. The compiler still optimizes based on the specifications, so throwing an unexpected exception results in undefined behavior at run time.
Bestie, this is a "don't throw the unexpected exception" situation. Undefined behavior is not a vibe.
-fextern-tls-init,-fno-extern-tls-init๐งต โ The C++11 and OpenMP standards letthread_localandthreadprivatevariables have dynamic (runtime) initialization. To support that, any use of such a variable goes through a wrapper function that does any necessary initialization. When the use and definition are in the same translation unit, this overhead can be optimized away. But when the use is in a different translation unit, there's significant overhead even if the variable doesn't actually need dynamic initialization. If the programmer can be sure that no use of the variable in a non-defining TU needs to trigger dynamic initialization (either because the variable is statically initialized, or because a use in the defining TU will run before any uses in another TU), they can avoid this overhead with-fno-extern-tls-init.
On targets that support symbol aliases, the default is -fextern-tls-init. On targets that don't support symbol aliases, the default is -fno-extern-tls-init.
-fno-gnu-keywords๐ค โ Stopstypeoffrom being recognized as a keyword, so your code can use that word as an identifier. You can use the keyword__typeof__instead. This option is implied by the strict ISO C++ dialects:-ansi,-std=c++98,-std=c++11, etc.-fno-implicit-templates๐ โ Never emits code for non-inline templates that are instantiated implicitly (that is, by use). Only explicit instantiations get code. If you use this option, you must be careful to structure your code so it includes all the necessary explicit instantiations, 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 that compiles with and without optimization need the same set of explicit instantiations.-fno-implement-inlines๐ชถ โ To save space, doesn't emit out-of-line copies of inline functions controlled by#pragma implementation. This causes linker errors if these functions aren't inlined everywhere they're called.-fmodules-ts,-fno-modules-ts๐ฆ โ Enables support for C++20 modules. The-fno-modules-tsoption is usually not needed, since that's the default. Even though this is a C++20 feature, selecting that standard version does not currently implicitly enable it.-fmodule-header,-fmodule-header=user,-fmodule-header=systemโ okay bestie, these take a header file and compile it into an importable header unit ๐ So you can import it later and skip the whole#includecircus ๐-fmodule-implicit-inlineโ ngl this one is a lil tricky ๐ Member functions defined inside their class definitions are not implicitly inline for modular code. That's different from traditional C++ behavior, and there are good reasons for it ๐ง But it can be a headache when you're porting code. This option makes those function definitions implicitly inline. Just know it creates an ABI incompatibility, so you have to use it everywhere or nowhere, no cap ๐ญ (Definitions outside of a named module stay implicitly inline either way, regardless ๐ )-fno-module-lazyโ Turns off lazy module importing and module mapper creation ๐ฆ-fmodule-mapper=[hostname]:port[?ident],-fmodule-mapper=|program[?ident] args...,-fmodule-mapper==socket[?ident],-fmodule-mapper=<>[inout][?ident],-fmodule-mapper=<in>out[?ident],-fmodule-mapper=file[?ident]โ The module mapper is an oracle ๐ฎ that answers "which filename goes with this module name?" ๐ If you don't set one, theCXX_MODULE_MAPPERenvironment variable gets used, and if that's unset too, you get an in-process default ๐-fmodule-onlyโ Only emit the Compiled Module Interface, and skip any object file ๐ธ-fms-extensionsโ Turns offWpedanticwarnings for MFC-style stuff ๐ like implicitintand grabbing a pointer to a member function with non-standard syntax. It's giving "I know what I'm doing" energy ๐-fnew-inheriting-ctorsโ Turns on the P0136 tweak to how C++11 constructor inheritance works ๐ฅ It's part of C++17, but it's also considered a Defect Report against C++11 and C++14 ๐ค This flag is on by default unless you specify-fabi-version=10or lower ๐-fnew-ttp-matchingโ Enables the P0522 resolution to Core issue 150, which covers template template parameters and default arguments โจ It lets a template with default template arguments be an argument for a template template parameter with fewer template parameters ๐ This is on by default for-std=c++17๐-fno-nonansi-builtinsโ Disables built-in declarations of functions that ANSI/ISO C doesn't mandate ๐ Thinkffs,alloca,_exit,index,bzero,conjf, and other related functions.-fnothrow-optโ Treats athrow()exception specification as if it werenoexcept๐ง so the text size overhead drops compared to a function with no exception specification. Lowkey clever: if the function has local variables with non-trivial destructors, the spec actually makes the function smaller, because the EH cleanups for those variables can get optimized away ๐ซถ Heads up: an exception thrown out of a function with this spec results in a call toterminaterather thanunexpected๐-fno-operator-namesโ Don't treat the operator name keywordsand,bitand,bitor,compl,not,or, andxoras synonyms for keywords ๐-fno-optional-diagsโ Turns off diagnostics the standard says a compiler doesn't need to issue ๐ฅบ Right now the only one G++ issues in that category is the one for a name having multiple meanings within a class.-fpermissiveโ Downgrades some diagnostics about nonconformant code from errors to warnings ๐ So-fpermissivelets some nonconforming code compile. Use with a little caution, bestie ๐ซถ-fno-pretty-templatesโ When an error message refers to a function template specialization, the compiler normally prints the template signature followed by the template arguments and any typedefs or typenames in the signature. So you getvoid f(T) [with T = int]instead ofvoid f(int), which makes it clear which template is involved ๐ For class template specializations, the compiler leaves out any template arguments that match the default template arguments. If either of these makes the error harder to understand instead of easier, use-fno-pretty-templatesto turn them off ๐-fno-rttiโ Disables generating info about every class with virtual functions for the C++ run-time type identification features (dynamic_castandtypeid) ๐ If you don't use those parts of the language, you can save some space with this flag. Exception handling uses the same information, but G++ generates it as needed. Thedynamic_castoperator can still be used 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โ Turns on the built-in global declarations ๐
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
These 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 โก Enabled by default under -std=c++14 and above. The flag -Wsized-deallocation warns about places that might want to add a definition.
-fstrict-enumsโ Lets the compiler optimize using the assumption that a value of an enumerated type can only be one of the values of the enumeration ๐ง (As defined in the C++ standard: basically, a value that can be represented in the minimum number of bits needed to represent all the enumerators.)
This assumption may not be valid if the 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 in left-to-right order, and assignment in right-to-left order, 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 value is 10.-ftemplate-depth=nโ Sets the maximum instantiation depth for template classes ton๐ The limit is needed to detect 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 value 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 the C++ ABI specifies for thread-safe initialization of local statics ๐งต You can use this to shave a little code size in code that doesn't need to be thread-safe.-fuse-cxa-atexitโ Registers destructors for objects with static storage duration with the__cxa_atexitfunction instead ofatexitโก This option is required for fully standards-compliant handling of static destructors, but it only works if your C library supports__cxa_atexit๐-fno-use-cxa-get-exception-ptrโ Don't use the__cxa_get_exception_ptrruntime routine. Heads up: this makesstd::uncaught_exceptionincorrect, but it's necessary if the runtime routine isn't available ๐ญ-fvisibility-inlines-hiddenโ This switch declares that you don't try to compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects ๐ฆ
So GCC may effectively mark inline methods with __attribute__ ((visibility ("hidden"))), so they don't appear in the export table of a DSO and don't need PLT indirection when used within the DSO. Turning this on can have a dramatic effect on load and link times of a DSO, because it massively reduces the size of the dynamic export table when the library makes heavy use of templates ๐คฏ
This isn't quite the same as marking methods hidden directly, because it doesn't affect static variables local to the function, and it doesn't cause the compiler to deduce that the function is defined in only one shared object ๐ค
You can mark a method with an explicit visibility to negate the effect of the switch for that method. For example, if you do want to compare pointers to a particular inline method, you might mark it as having default visibility. Marking the enclosing class with explicit visibility has no effect ๐
Explicitly instantiated inline methods are unaffected by this option, since their linkage might otherwise cross a shared library boundary ๐
-fvisibility-ms-compatโ This flag attempts to use visibility settings to make GCC's C++ linkage model compatible with Microsoft Visual Studio's ๐ช It makes these changes to GCC's linkage model:- It sets the default visibility to
hidden, like-fvisibility=hidden. - Types, but not their members, are not hidden by default.
- The One Definition Rule is relaxed for types without explicit visibility specifications that are defined in more than one shared object: those declarations are permitted if they are permitted when this option is not used.
- It sets the default visibility to
In new code it's better to use -fvisibility=hidden and export those classes that are intended to be externally visible. Unfortunately, it's possible for code to rely, perhaps accidentally, on the Visual Studio behavior ๐ฌ
Among the consequences of these changes: static data members of the same type with the same name but defined in different shared objects are different, so changing one doesn't change the other. Also, pointers to function members defined in different shared objects may not compare equal. When this flag is given, it's a violation of the ODR (One Definition Rule) to define types with the same name differently ๐
-fno-weakโ Doesn't use weak symbol support, even if the linker provides it. By default, G++ uses weak symbols if they're available.
This option exists only for testing, and should not be used by end-users; it results in inferior code and has no benefits. It may be removed in a future release of G++. ๐ซ
-fext-numeric-literals(C++ and Objective-C++ only): okay so this one lets you use imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions ๐ When it's 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++: bestie, this one skips the C++-specific standard directories when it's searching for headers ๐ but it still checks the other standard directories โจ (It's used when building the C++ library, so it's kind of a big deal ๐)-flang-info-include-translate,-flang-info-include-translate-not,-flang-info-include-translate=header: this is the info-tea on include translation events ๐ต The first one reports accepted include translations, and the second one reports declined ones. Theheaderform only gives you the scoop on that one specific header. If header is"user"or"<system>", it gets resolved to a specific user or system header using the include path ๐ง-flang-info-module-cmi,-flang-info-module-cmi=module: this one's all about Compiled Module Interface pathnames ๐ธ The first option notes every CMI pathname that gets read. Themoduleform notes when a specific module's CMI is read. module can be a named module or a header-unit, and you can tell it's a header-unit when the pathname has directory separators or is 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, G++'s native C++ runtime) andlibc++, which is the C++ runtime installed on some operating systems (like Darwin versions from Darwin11 onwards). This option switches G++ to the headers from whichever library you pick, and it emits-lstdc++or-lc++respectively when a C++ runtime is needed for linking ๐
On top of that, these warning options only have meaning for C++ programs ๐
-Wabi-tag(C++ and Objective-C++ only): this warns when a type with an ABI tag gets used in a context that doesn't have that ABI tag ๐ Check out C++ Attributes for more info about ABI tags.-Wcomma-subscript(C++ and Objective-C++ only): this one warns about comma expressions used inside a subscripting expression ๐ That usage was deprecated in C++20, but a comma expression wrapped in( )is not deprecated. Example:
void f(int *a, int b, int c) {
a[b,c]; // deprecated
a[(b,c)]; // OK
}
It's enabled by default with -std=c++20.
-Wctad-maybe-unsupported(C++ and Objective-C++ only): this warns when you do class template argument deduction (CTAD) on a type that has no explicitly written deduction guides ๐ง It points out cases where CTAD only worked because the compiler synthesized the implicit deduction guides, which might not be what you meant. Some style guides only allow CTAD on types that specifically "opt-in," meaning types designed to support CTAD. You can suppress this warning with this 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): this warns when a class seems totally unusable because all of its constructors or destructors are private, and it has neither friends nor public static member functions ๐ It also warns if there are no non-private methods and there's at least one private member function that isn't a constructor or destructor.-Wdelete-non-virtual-dtor(C++ and Objective-C++ only): this warns whendeleteis used to destroy an instance of a class that has virtual functions and a non-virtual destructor ๐ It's unsafe to delete a derived class instance through a base class pointer if the base class doesn't have a virtual destructor. This warning is enabled by-Wall.-Wdeprecated-copy(C++ and Objective-C++ only): this warns that the implicit declaration of a copy constructor or copy assignment operator is deprecated when 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 copy when the class has a user-provided destructor.-Wno-deprecated-enum-enum-conversion(C++ and Objective-C++ only): this turns off the warning for when the usual arithmetic conversions get applied to operands where one is an enumeration type and the other is a different enumeration type ๐ This conversion was deprecated in C++20. For example:
enum E1 { e };
enum E2 { f };
int k = f - e;
-Wdeprecated-enum-enum-conversion is enabled by default with -std=c++20. In pre-C++20 dialects, you can enable this warning with -Wenum-conversion.
-Wno-deprecated-enum-float-conversion(C++ and Objective-C++ only): this turns off the warning for when the usual arithmetic conversions get applied to operands where one is an enumeration type and the other is a floating-point type ๐ This conversion was deprecated in C++20. For example:
enum E1 { e };
enum E2 { f };
bool b = e <= 3.7;
-Wdeprecated-enum-float-conversion is enabled by default with -std=c++20. In pre-C++20 dialects, you can enable this warning with -Wenum-conversion.
-Wno-init-list-lifetime(C++ and Objective-C++ only): this stops the warning about uses ofstd::initializer_listthat are likely to end up with dangling pointers ๐ญ The underlying array for aninitializer_listis handled like a normal C++ temporary object, so it's super easy to accidentally keep a pointer to the array after its lifetime has ended. Some examples:- If a function returns a temporary
initializer_list, or a localinitializer_listvariable, the array's lifetime ends at the end of the return statement, so the returned value has a dangling pointer. - If a new-expression creates an
initializer_list, the array only lives until the end of the enclosing full-expression, so theinitializer_liston the heap has a dangling pointer. - When an
initializer_listvariable is assigned from a brace-enclosed initializer list, the temporary array created for the right side of the assignment only lives until the end of the full-expression. So at the next statement, theinitializer_listvariable has a dangling pointer. - When a list constructor stores the
beginpointer from theinitializer_listargument, this doesn't extend the lifetime of the array. So if a class variable is constructed from a temporaryinitializer_list, the pointer is left dangling by the end of the variable declaration statement.
- If a function returns a temporary
// li's initial underlying array lives as long as li
std::initializer_list<int> li = { 1,2,3 };
// assignment changes li to point to a temporary array
li = { 4, 5 };
// now the temporary is gone and li has a dangling pointer
int i = li.begin()[0] // undefined behavior
-Winvalid-imported-macros: this verifies that all imported macro definitions are valid at the end of compilation ๐งฉ It's not enabled by default, since it needs some extra processing to figure out. It can be super useful when you're preparing sets of header-units and want consistent macros ๐-Wno-literal-suffix(C++ and Objective-C++ only): this stops the warning when a string or character literal is followed by a ud-suffix that doesn't begin with an underscore ๐ As a conforming extension, GCC treats those suffixes as separate preprocessing tokens so that older code using formatting macros from<inttypes.h>keeps working. For example:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
int main() {
int64_t i64 = 123;
printf("My int64: %" PRId64"\n", i64);
}
In this case, PRId64 is treated as a separate preprocessing token.
This option also controls warnings when a user-defined literal operator is declared with a literal suffix identifier that doesn't begin with an underscore. Literal suffix identifiers that don't begin with an underscore are reserved for future standardization โ ๏ธ These warnings are enabled by default.
-Wno-narrowing(C++ and Objective-C++ only): for C++11 and later standards, narrowing conversions get diagnosed by default, because the standard requires it ๐ซ A narrowing conversion from a constant produces an error, and a narrowing conversion from a non-constant produces a warning, but-Wno-narrowingsuppresses the diagnostic. This doesn't change the meaning of well-formed code, since narrowing conversions are still ill-formed in SFINAE contexts. With-Wnarrowingin C++98, you get a warning when a narrowing conversion prohibited by C++11 happens within{ }, for example:
int i = { 2.2 }; // error: narrowing from double to int
This flag is included in -Wall and -Wc++11-compat.
-Wnoexcept(C++ and Objective-C++ only): this warns when a noexcept-expression evaluates to false because of a call to a function that doesn't have a non-throwing exception specification (that is,throw()ornoexcept), but that the compiler knows will never throw an exception ๐ฆ-Wnoexcept-type(C++ and Objective-C++ only): this warns if the C++17 feature that makesnoexceptpart of a function type changes the mangled name of a symbol compared to C++14 โจ It's enabled by-Wabiand-Wc++17-compat. 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) โ okay so this one yells when you hand a raw memory function likememsetormemcpya destination that's an object of class type ๐ญ. The danger is that writing into it can skip a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers. Messing with the guts of these objects can violate invariants the class's member functions depend on ๐ . Like, thememsetcall below is undefined because it modifies a non-trivial class object, so it gets flagged ๐. The safe way to initialize or clear storage for these types is to use the appropriate constructor or assignment operator, if one exists โจ.-Wclass-memaccessis enabled by-Wall. Casting the pointer to the class object tovoid *, or to a type the raw memory function can safely access, suppresses the warning ๐ซถ.
std::string str = "abc";
memset (&str, 0, sizeof str);
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ this one catches a class that has virtual functions but an accessible non-virtual destructor, either on itself or in an accessible polymorphic base class ๐. That combo means deleting a derived instance through a pointer to the class or base class is possible but unsafe ๐. It turns on automatically if-Weffc++is specified ๐ธ.-Wregister(C++ and Objective-C++ only) โ warns on uses of theregisterstorage class specifier, unless it's part of the GNU Explicit Register Variables extension ๐ฆ. Fun fact, theregisterkeyword got deprecated in C++11 and fully removed in C++17 ๐ฅ. It's enabled by default with-std=c++17๐.-Wreorder(C++ and Objective-C++ only) โ warns when the order of your member initializers doesn't match the order they actually have to run in ๐ง. For instance:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler quietly rearranges the member initializers for i and j to match the declaration order of the members, and it emits a warning about it โ ๏ธ. This warning is enabled by -Wall.
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this warning pops up when a call tostd::moveblocks copy elision ๐ โโ๏ธ. A typical copy elision situation is returning from a function with a class return type, where the returned expression is the name of a non-volatile automatic object (not a function parameter) with the same type as the return type ๐. But in this example, thestd::movecall prevents copy elision:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
This warning is enabled by -Wall.
-Wno-redundant-move(C++ and Objective-C++ only) โ this one warns about redundant calls tostd::move, aka the times a move would've happened even without thestd::movecall ๐. It happens because the compiler gets forced to treat the object as an rvalue in certain spots, like returning a local variable where copy elision doesn't apply ๐. Consider:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant ๐. Because G++ implements Core Issue 1579, another example is:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this one, copy elision isn't applicable because the type of the returned expression and the function return type differ, yet G++ still treats the return value as if it were designated by an rvalue ๐. This warning is enabled by -Wextra.
-Wrange-loop-construct(C++ and Objective-C++ only) โ this warns when a C++ range-based for-loop is making an unnecessary copy ๐. That usually happens when the range declaration isn't a reference, but it probably should be โจ. For example:
struct S { char arr[128]; };
void fn () {
S arr[5];
for (const auto x : arr) { ... }
}
It does not warn when the type being copied is trivially-copyable and smaller than 64 bytes ๐.
It also warns when a loop variable in a range-based for-loop gets 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 creates and destroys a temporary value of type double, which the reference const double & is bound to ๐ฅ. This warning is enabled by -Wall.
-Wredundant-tags(C++ and Objective-C++ only) โ warns about redundant class-key and enum-key in references to class types and enumerated types, in spots where the key can be dropped without causing ambiguity ๐ง. For example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
On the other hand, this example gets no warning:
struct foo;
void foo (); // "hides" struct foo
void bar (struct foo&); // no warning, keyword struct is necessary
-Wno-subobject-linkage(C++ and Objective-C++ only) โ don't warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐. If a type A depends on a type B with no or internal linkage, defining it in multiple translation units would be an ODR violation, because the meaning of B differs in each translation unit ๐ฌ. If A only shows up in a single translation unit, the best way to silence the warning is to give it internal linkage by putting it in an anonymous namespace too ๐ซถ. The compiler doesn't warn for types defined in the main.Cfile, since those are unlikely to have multiple definitions ๐ .-Wsubobject-linkageis enabled by default.-Weffc++(C++ and Objective-C++ only) โ this one warns about violations of the style guidelines from Scott Meyers' Effective C++ series of books ๐. The guidelines it checks are:- Define a copy constructor and an assignment operator for classes with dynamically-allocated memory.
- Prefer initialization to assignment in constructors.
- Have
operator=return a reference to*this. - Don't try to return a reference when you must return an object.
- Distinguish between prefix and postfix forms of increment and decrement operators.
- Never overload
&&,||, or,.
This option also turns on -Wnon-virtual-dtor, which is one of the Effective C++ recommendations too ๐ธ. The check is extended, though, to warn about a missing virtual destructor in accessible non-polymorphic base classes as well ๐ง.
Heads up, bestie: the standard library headers don't obey all of these guidelines ๐ญ. When you select this option, use grep -v to filter out those warnings.
-Wno-exceptions(C++ and Objective-C++ only) โ disables the warning for when an exception handler is shadowed by another handler, which can point out a wrong ordering of exception handlers ๐.-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about using an uncastedNULLas a sentinel ๐ง. When compiling only with GCC, this is 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 ๐.-Wno-non-template-friend(C++ and Objective-C++ only) โ disables warnings when non-template friend functions are declared within a template ๐ฆ. Very old versions of GCC, from before the ISO standard was implemented, could interpret declarations likefriend int foo(int)(where the friend's name is an unqualified-id) as a particular specialization of a template function. The warning exists to diagnose those compatibility problems, and it's enabled by default ๐ฐ๏ธ.-Wold-style-cast(C++ and Objective-C++ only) โ warns if an old-style (C-style) cast to a non-void type is used in a C++ program ๐ โโ๏ธ. The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are less vulnerable to unintended effects and way easier to search for ๐.-Woverloaded-virtual(C++ and Objective-C++ only) โ warns when a function declaration hides virtual functions from a base class ๐ซฃ. For example:
struct A {
virtual void f();
};
struct B: public A {
void f(int);
};
The A class version of f is hidden in B, so code like this:
B* b;
b->f();
fails to compile ๐.
-Wno-pmf-conversions(C++ and Objective-C++ only) โ disables the diagnostic for converting a bound pointer to member function 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 ๐.-Wtemplates(C++ and Objective-C++ only) โ warns when a primary template declaration is encountered ๐งฉ. Some coding rules disallow templates, and this can be used to enforce that rule ๐. The warning is inactive inside a system header file, such as the STL, so you can still use the STL ๐. You're also still allowed to instantiate or specialize templates โจ.-Wno-mismatched-new-delete(C++ and Objective-C++ only) โ okay bestie, this one is all about catching mismatchednewanddeletecalls ๐ฅ It warns whenoperator neworoperator deletegets paired with the wrong corresponding allocation or deallocation call ๐ That includes C++operator deletebeing used on pointers from mismatched forms ofoperator new, or from other functions that allocate objects whereoperator deleteisn't a suitable deallocator ๐ญ It also covers other deallocation functions being called on pointers returned fromoperator newwhen that deallocation function isn't suitable.
Check out this example ๐ The delete expression in the function below gets flagged because it doesn't match the array form of the new expression its pointer came from. The free call gets flagged too:
void f ()
{
int *a = new int[n];
delete a; // warning: mismatch in array forms of expressions
char *p = new char[n];
free (p); // warning: mismatch between new and free
}
The related option -Wmismatched-dealloc handles mismatches involving allocation and deallocation functions other than operator new and operator delete ๐ธ
-Wmismatched-new-delete is enabled by default โจ
-Wmismatched-tags(C++ and Objective-C++ only) โ this one yells at you if you declare a struct, class, or class template (or one of its specializations) using a class-key that doesn't match the definition, or the first declaration when no definition exists ๐ง
For example, the declaration of struct Object in the argument list of draw sets it off. To make it stop, either drop the extra class-key struct or swap it for class so it matches the definition ๐
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
Using struct to declare a class is totally not wrong, as the example shows ๐ฆ -Wmismatched-tags is really about keeping your class declarations looking consistent. If you're writing code meant to be portable to Windows-based compilers, this warning helps you avoid unresolved references caused by different class-keys mangling symbols differently ๐ซถ You can use the option on its own or alongside -Wredundant-tags.
-Wmultiple-inheritance(C++ and Objective-C++ only) โ warns when a class is defined with multiple direct base classes ๐ Some coding rules ban multiple inheritance, and this can enforce that rule. The warning goes quiet inside system header files like the STL, so you can still use the STL ๐ You can also define classes that use multiple inheritance indirectly.-Wvirtual-inheritanceโ warns when a class is defined with a virtual direct base class ๐ Some coding rules ban multiple inheritance, and this can enforce that rule. It's also inactive inside system header files like the STL, so the STL is still fair game ๐ง You can still define classes that use virtual inheritance indirectly.-Wno-virtual-move-assignโ suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator ๐
โ ๏ธ This is dangerous, bestie! If the virtual base is reachable along more than one path, it gets moved multiple times, which can leave both objects in the moved-from state. If your move assignment operator is written so it avoids moving from a moved-from object, you can safely disable this warning.
-Wnamespacesโ warns when a namespace definition is opened โญ Some coding rules ban namespaces, and this can enforce that rule. The warning is inactive inside system header files like the STL, so the STL still works ๐ซถ You can also use using directives and qualified names.-Wno-terminate(C++ and Objective-C++ only) โ turns off the warning about a throw-expression that will immediately lead to 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++ says it has to be read as a function declaration. For instance:
void f(double a) {
int i(); // extern int i (void);
int n(int(a)); // extern int n (int);
}
Another example:
struct S { S(int); };
void f(double a) {
S x(int(a)); // extern struct S x (int);
S y(int()); // extern struct S y (int (*) (void));
S z(); // extern struct S z (void);
}
The warning will suggest ways to deal with the ambiguity, like removing the parentheses or using braces instead ๐ธ
This warning is enabled by default ๐
-Wno-class-conversion(C++ and Objective-C++ only) โ don't warn when a conversion function converts an object to the same type, to a base class of that type, or tovoid๐ฆ Such a conversion function will never be called anyway.-Wvolatile(C++ and Objective-C++ only) โ warns about deprecated uses of thevolatilequalifier ๐ฅ This covers postfix and prefix++and--expressions onvolatile-qualified types, simple assignments where the left operand is avolatile-qualified non-class type (for their value), compound assignments where the left operand is avolatile-qualified non-class type, avolatile-qualified function return type, avolatile-qualified parameter type, and structured bindings of avolatile-qualified type. This usage was deprecated in C++20 ๐
Enabled by default with -std=c++20 ๐
-Wzero-as-null-pointer-constant(C++ and Objective-C++ only) โ warns when a literal0is used as a null pointer constant ๐ This can be handy for moving over tonullptrin C++11.-Waligned-newโ warns about a new-expression of a type that needs greater alignment thanalignof(std::max_align_t)but uses an allocation function without an explicit alignment parameter ๐ This option is enabled by-Wall.
Normally this only warns about global allocation functions, but -Waligned-new=all also warns about class member allocation functions โจ
-Wno-placement-new,-Wplacement-new=nโ warns about placement new expressions with undefined behavior, like constructing an object in a buffer that's smaller than the object's type ๐ For example, the placement new expression below gets flagged because it tries to construct an array of 64 integers in a buffer only 64 bytes large:
char buf [64];
new (buf) int[64];
This warning is enabled by default ๐
-Wplacement-new=1
This is the default warning level for -Wplacement-new ๐ง At this level, the warning isn't issued for some strictly undefined constructs that GCC allows as extensions for compatibility with legacy code. For example, the following new expression isn't diagnosed at this level, even though it has undefined behavior according to the C++ standard, because it writes past the end of the one-element array:
struct S { int n, a[1]; };
S *s = (S *)malloc (sizeof *s + 31 * sizeof s->a[0]);
new (s->a)int [32]();
-Wplacement-new=2
At this level you get all the same diagnostics as level 1, plus a diagnostic for placement new expressions that construct an object in the last member of a structure, where that member is an array of a single element and the size is less than the size of the object being constructed ๐ฅ The previous example would be diagnosed here, but the following construct uses the flexible member array extension to avoid the warning at level 2:
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ warns about catch handlers that don't catch via reference ๐ With-Wcatch-value=1(or-Wcatch-valuefor short), you get warnings about polymorphic class types caught by value. With-Wcatch-value=2, you get warnings about all class types caught by value. With-Wcatch-value=3, you get warnings about all types that aren't caught by reference.-Wcatch-valueis enabled by-Wall๐-Wconditionally-supported(C++ and Objective-C++ only) โ warns for conditionally-supported (C++11 [intro.defs]) constructs ๐ฆ-Wno-delete-incomplete(C++ and Objective-C++ only) โ don't warn when deleting a pointer to an incomplete type, which may cause undefined behavior at runtime ๐ This warning is enabled by default.-Wextra-semi(C++, Objective-C++ only) โ warns about redundant semicolons after in-class function definitions ๐ซถ-Wno-inaccessible-base(C++, Objective-C++ only) โ controls warnings when a base class is inaccessible in a derived class because of ambiguity ๐ง The warning is enabled by default. Note that the warning for ambiguous virtual bases is enabled by the-Wextraoption. Here's the example:
struct A { int a; };
struct B : A { };
struct C : B, A { };
-Wno-inherited-variadic-ctorโ suppresses warnings about using C++11 inheriting constructors when the base class has a C variadic constructor ๐ธ This warning is on by default because the ellipsis isn't inherited.-Wno-invalid-offsetof(C++ and Objective-C++ only) โ suppresses warnings from applying theoffsetofmacro to a non-POD type ๐ According to the 2014 ISO C++ standard, applyingoffsetofto a non-standard-layout type is undefined. In existing C++ implementations, though,offsetofusually gives meaningful results. This flag is for folks who know they're writing nonportable code and have deliberately chosen to ignore the warning ๐
The restrictions on offsetof may be relaxed in a future version of the C++ standard โจ
-Wsized-deallocation(C++ and Objective-C++ only) โ warns about a definition of an unsized deallocation function
Okay so this one's about mismatched deallocators ๐ GCC gets suspicious when you write one of these unsized operator delete versions and skip the sized bestie that goes with it:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
...without a matching sized deallocation function defined right next to it. โจ The sized ones look like this:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
Or it's the other way around, so you've got the sized one and no unsized one. Either way GCC's gonna flag it ๐
Enabled by -Wextra along with -fsized-deallocation. ๐
-Wsuggest-final-typesโ Okay this one is giving "glow up your class hierarchy" ๐ฆ It warns about types with virtual methods that would be cleaner if they were declared with the C++11"final"specifier, or, if it's possible, put inside an anonymous namespace. Doing that lets GCC devirtualize the polymorphic calls more aggressively, which is so iconic ๐ This warning hits harder with link-time optimization, because that's when GCC has the full class hierarchy graph and knows way more about what's going on.-Wsuggest-final-methodsโ Same energy, but at the method level ๐ It warns about virtual methods that would be better off declared with the C++11"final"specifier. If it's possible, the method's type could go into an anonymous namespace or get the"final"specifier instead. Like the previous one, this is more effective with link-time optimization, since the class hierarchy graph is more complete then. Bestie tip from the original: consider the-Wsuggest-final-typessuggestions first, then rebuild with the new annotations ๐ธ-Wsuggest-overrideโ GCC will side-eye any virtual function you override without marking it with the"override"keyword ๐ Add that keyword, it's literally free slay โจ-Wuseless-cast(C++ and Objective-C++ only) โ Warns when an expression gets cast to its own type. Like, why are we even doing that ๐-Wno-conversion-null(C++ and Objective-C++ only) โ Turns off warnings for conversions betweenNULLand non-pointer types. Heads up though,-Wconversion-nullis already on by default, so this is you saying "chill, I got this" ๐ซถ
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
NOTE: This manual does not describe the Objective-C and Objective-C++ languages themselves. ๐
This section is all about the command-line options that only matter for Objective-C and Objective-C++ programs ๐ You can also use most of the language-independent GNU compiler options too. For example, you could compile a file called some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
In this example, -fgnu-runtime is an Objective-C-only option ๐ You can use the other options with any language GCC supports.
Objective-C is basically an extension of C, so Objective-C compilations can also use options specific to the C front end (e.g., -Wtraditional). Same deal for Objective-C++, which can use C++-specific options (e.g., -Wabi) ๐ง
Here's the list of options that are only for compiling Objective-C and Objective-C++ programs:
-fconstant-string-class=class-nameโ This picks the class that gets instantiated for each literal string written with the@"..."syntax. The default isNXConstantStringwhen the GNU runtime is in use, andNSConstantStringwhen the NeXT runtime is in use (more on that below) ๐ On Darwin (macOS, MacOS X) platforms, if-fconstant-cfstringsis also present, it overrides-fconstant-string-classand makes@"..."literals get laid out as constant CoreFoundation strings. Also,-fconstant-cfstringsis an alias for the target-specific-mconstant-cfstringsequivalent.-fgnu-runtimeโ Generates object code that's compatible with the standard GNU Objective-C runtime. This is the default for most systems ๐-fnext-runtimeโ Generates output compatible with the NeXT runtime. This is the default for NeXT-based systems, including Darwin and Mac OS X. The macro__NEXT_RUNTIME__is predefined if, and only if, this option is used ๐ฆ-fno-nil-receiversโ Tells the compiler to assume every Objective-C message dispatch ([receiver message:arg]) in this translation unit makes sure the receiver is notnil. That lets the runtime use more efficient entry points โก This option is only available together with the NeXT runtime and ABI version 0 or 1.-fobjc-abi-version=nโ Uses version n of the Objective-C ABI for the selected runtime. Right now this is only supported for the NeXT runtime ๐ธ In that case, Version 0 is the traditional (32-bit) ABI without support for properties and other Objective-C 2.0 additions. Version 1 is the traditional (32-bit) ABI with support for properties and other Objective-C 2.0 additions. Version 2 is the modern (64-bit) ABI. If you don't specify anything, the default is Version 0 on 32-bit target machines, and Version 2 on 64-bit target machines.-fobjc-call-cxx-cdtorsโ For each Objective-C class, GCC checks whether any of its instance variables is a C++ object with a non-trivial default constructor. If so, it synthesizes a special- (id) .cxx_constructinstance method that runs those non-trivial default constructors on the instance variables, in order, and then returnsself. It also checks whether any instance variable is a C++ object with a non-trivial destructor, and if so, synthesizes a special- (void) .cxx_destructmethod that runs all those default destructors in reverse order ๐
The - (id) .cxx_construct and - (void) .cxx_destruct methods generated this way only operate on instance variables declared in the current Objective-C class, not the ones inherited from superclasses. It's the Objective-C runtime's job to call all of these methods across an object's inheritance hierarchy. The runtime invokes - (id) .cxx_construct right after a new object instance is allocated, and - (void) .cxx_destruct right before it deallocates an object instance ๐
As of this writing, only the NeXT runtime on Mac OS X 10.4 and later can invoke the - (id) .cxx_construct and - (void) .cxx_destruct methods. ๐
-fobjc-direct-dispatchโ Allows fast jumps to the message dispatcher. On Darwin, this is done via the comm page โก-fobjc-exceptionsโ Turns on syntactic support for structured exception handling in Objective-C, kinda like what C++ has ๐ซถ You need this option to use the Objective-C keywords@try,@throw,@catch,@finallyand@synchronized. It works with both the GNU runtime and the NeXT runtime, but it's not available with the NeXT runtime on Mac OS X 10.2 and earlier.-fobjc-gcโ Enables garbage collection (GC) in Objective-C and Objective-C++ programs. This is only available with the NeXT runtime. The GNU runtime has its own, different garbage collection implementation that doesn't need any special compiler flags ๐งน-fobjc-nilcheckโ For the NeXT runtime with version 2 of the ABI, GCC checks for anilreceiver in method invocations before doing the actual method call. This is the default, and you can turn it off with-fno-objc-nilcheck. Class methods and super calls are never checked fornilthis way, no matter what this flag is set to. Right now this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is used ๐-fobjc-std=objc1โ Conforms to the language syntax of Objective-C 1.0, the language GCC 4.0 recognized. This only affects the Objective-C additions to the C/C++ language. It doesn't change conformance to C/C++ standards, which is controlled by the separate C/C++ dialect option flags. When you use this with the Objective-C or Objective-C++ compiler, any Objective-C syntax that GCC 4.0 didn't recognize gets rejected. This is handy if you need to make sure your Objective-C code can compile with older versions of GCC ๐ฐ๏ธ-freplace-objc-classesโ Emits a special marker that tellsld(1)not to statically link the resulting object file, and letsdyld(1)load it at run time instead. This is used with the Fix-and-Continue debugging mode, where the object file might get recompiled and dynamically reloaded while the program is running, no restart needed ๐ฅ For now, Fix-and-Continue only works with the NeXT runtime on Mac OS X 10.3 and later.-fzero-linkโ When compiling for the NeXT runtime, the compiler normally swaps calls toobjc_getClass("...")(when the class name is known at compile time) for static class references that get initialized at load time, which makes run-time performance better ๐ This flag stops that and keeps theobjc_getClass("...")calls. It's useful in Zero-Link debugging mode, since you can modify individual class implementations while the program runs. The GNU runtime always keeps calls toobjc_get_class("...")no matter what command-line options you pass.-fno-local-ivarsโ By default, instance variables in Objective-C can be accessed as if they were local variables inside the methods of the class they're declared in. That can cause shadowing between instance variables and other variables declared locally inside a class method, or globally, with the same name. Passing-fno-local-ivarsturns this off and avoids those shadowing issues ๐-fivar-visibility=[public|protected|private|package]โ Sets the default instance variable visibility to the option you pick, so instance variables declared outside the scope of any access modifier directives default to that visibility ๐-gen-declsโ Dumps interface declarations for all classes seen in the source file to a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ Warns whenever an Objective-C assignment is being intercepted by the garbage collector ๐๏ธ-Wno-property-assign-default(Objective-C and Objective-C++ only) โ Doesn't warn if a property for an Objective-C object has noassignsemantics specified. It's giving "I trust you" energy ๐ซถ-Wno-protocol(Objective-C and Objective-C++ only) โ okay so if a class says it implements a protocol, GCC warns about every protocol method the class doesn't implement ๐ โโ๏ธ. The default is even stricter: it warns about every method not explicitly implemented in the class, even when the superclass already has it ๐. With-Wno-protocol, inherited methods count as implemented, so no warning for them โจ.-Wobjc-root-class(Objective-C and Objective-C++ only) โ warns if a class interface has no superclass ๐. Most classes inherit from"NSObject"(or"Object"), so this is for the rare case. If you're intentionally making a root class, mark its interface with__attribute__((objc_root_class))and the warning gets suppressed ๐ซถ.-Wselector(Objective-C and Objective-C++ only) โ warns if multiple methods with different types share the same selector during compilation ๐. This check runs on the method list at the very end of compilation. It also checks each selector used in a@selector(...)expression, if a matching method was found during compilation. Since these checks only happen at the end, the warnings won't show up if the final stage never runs, like when an error stops compilation early or when-fsyntax-onlyis being used ๐ฅฒ.-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if a selector has several methods with different argument and/or return types, when you send a message with that selector to a receiver of typeidorClass๐ง. This flag is off by default. When it's off, the compiler skips these warnings if the only differences are between types that share the same size and alignment ๐.-Wundeclared-selector(Objective-C and Objective-C++ only) โ warns if you use a@selector(...)expression for a selector that was never declared ๐ฃ. A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, either explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection. This option checks right away when it hits a@selector(...)expression, while-Wselectorwaits until the final stage of compilation. It also enforces the vibe that methods and selectors must be declared before they're used ๐ .-print-objc-runtime-infoโ generates a C header describing the largest structure that gets passed by value, if there is one ๐งพ.
๐ Options to Control Diagnostic Messages Formatting ๐
Traditionally, diagnostic messages were formatted without caring what the output device looked like (its width and stuff) ๐บ. These options let you control the formatting, like how many characters fit on a line and how often the source location gets reported ๐ธ. Heads up that some language front ends might not respect these options ๐.
-fmessage-length=nโ tries to format error messages so they fit on lines about n characters long โ๏ธ. If n is zero, no line-wrapping happens and each error message sits on a single line. This is the default for all front ends ๐.
Note: this option also affects the display of the #error and #warning preprocessor directives, and the deprecated function/type/variable attribute ๐. It does not affect pragma GCC warning and pragma GCC error ๐
โโ๏ธ.
-fdiagnostics-plain-outputโ makes diagnostic output look as plain as possible ๐ค. This is handy when you're running dejagnu or other tools that parse the diagnostics and need them to stay stable over time ๐ง. Right now,-fdiagnostics-plain-outputis the same as all of these together:-fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never -fdiagnostics-urls=never -fdiagnostics-path-format=separate-events. If GCC ever changes the default look of its diagnostics, the matching option to turn off that new behavior will get added to this list ๐ฎ.-fdiagnostics-show-location=onceโ only matters in line-wrapping mode ๐. It tells the reporter to show source location information just once. So if a message is too long and gets wrapped, the location doesn't get repeated as a prefix on every continuation line ๐. This is the default behavior โ .-fdiagnostics-show-location=every-lineโ also only matters in line-wrapping mode ๐. It tells the reporter to put the same source location prefix on every physical line that comes from breaking up a message that's too long ๐.-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ turns color on in diagnostics ๐. WHEN can benever,always, orauto๐จ. The default depends on how the compiler was configured. It can be any of thoseWHENoptions, orneverif theGCC_COLORSenvironment variable isn't in the environment, andautootherwise ๐ง .autoonly uses color when standard error is a terminal, and when you're not running in an emacs shell ๐ฅ๏ธ.-fdiagnostics-colorand-fno-diagnostics-colorare just aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively ๐.
The colors come from the environment variable GCC_COLORS ๐จ. Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings ๐ช. SGR commands get interpreted by your terminal or terminal emulator. (Check the section in your text terminal's documentation for the permitted values and what they mean as character attributes ๐.) These substring values are decimal integers, and you can join them with semicolons ๐ข. Common values people combine include 1 for bold, 4 for underline, 5 for blink, 7 for inverse, 39 for default foreground color, 30 to 37 for foreground colors, 90 to 97 for 16-color mode foreground colors, 38;5;0 to 38;5;255 for 88-color and 256-color mode foreground colors, 49 for default background color, 40 to 47 for background colors, 100 to 107 for 16-color mode background colors, and 48;5;0 to 48;5;255 for 88-color and 256-color mode background colors ๐ท.
The default GCC_COLORS is:
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
Here, 01;31 is bold red, 01;35 is bold magenta, 01;36 is bold cyan, 32 is green, 34 is blue, 01 is bold, and 31 is red ๐. Setting GCC_COLORS to the empty string turns colors off ๐ซ. These are the capabilities you can set ๐:
"error="โ SGR substring forerror:markers โ."warning="โ SGR substring forwarning:markers โ ๏ธ."note="โ SGR substring fornote:markers ๐."path="โ SGR substring for coloring paths of control-flow events printed via-fdiagnostics-path-format=, like the identifiers of individual events and the lines showing interprocedural calls and returns ๐ค๏ธ."range1="โ SGR substring for the first additional range 1๏ธโฃ."range2="โ SGR substring for the second additional range 2๏ธโฃ."locus="โ SGR substring for location information, likefile:lineorfile:line:column๐."quote="โ SGR substring for information printed within quotes ๐ฌ."fixit-insert="โ SGR substring for fix-it hints suggesting text to insert or replace โ."fixit-delete="โ SGR substring for fix-it hints suggesting text to delete โ."diff-filename="โ SGR substring for filename headers in generated patches ๐."diff-hunk="โ SGR substring for the starts of hunks in generated patches ๐งฉ."diff-delete="โ SGR substring for deleted lines in generated patches ๐๏ธ."diff-insert="โ SGR substring for inserted lines in generated patches ๐ฑ."type-diff="โ SGR substring for highlighting mismatched types within template arguments in the C++ front end ๐.
-fdiagnostics-urls[=WHEN]โ uses escape sequences to embed URLs in diagnostics ๐. For example, when-fdiagnostics-show-optionshows the command-line option that controls a diagnostic, it can embed a URL pointing to that option's docs ๐.
WHEN can be never, always, or auto ๐. auto makes GCC use URL escape sequences only when standard error is a terminal, and when you're not running in an emacs shell or any graphical terminal known to be incompatible with this feature (more on that below) ๐
โโ๏ธ.
The default depends on how the compiler was configured, and it can be any of the WHEN options above ๐ ๏ธ. GCC can also be configured with the --with-diagnostics-urls=auto-if-env configure-time option, so the default depends on environment variables ๐. In that setup, GCC defaults to auto if either the GCC_URLS or TERM_URLS environment variables are present and non-empty in the compiler's environment, and never if neither is ๐ง.
Even with -fdiagnostics-urls=always, the behavior still depends on those environment variables ๐คฏ. If GCC_URLS is set to empty or no, URLs don't get 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 turns the feature on ๐. If GCC_URLS isn't set, GCC falls back to TERM_URLS ๐.
Quick glossary, bestie ๐: ST is an ANSI escape sequence whose string terminator is ESC \. BEL is an ASCII character, CTRL-G, which usually makes a beep ๐.
So GCC also tries to sniff out a few terminals that don't play nice with URL escapes ๐. These are terminals that don't implement the URL feature, or that have bugs (or had bugs in versions people still use) where the escapes misbehave and print garbage all over your screen ๐. Right now that list is xfce4-terminal, certain known-buggy gnome-terminal versions, the linux console, and mingw. If you're sure your terminal is fine, you can skip this check with -fdiagnostics-urls=always. ๐ฆ
๐
-fno-diagnostics-show-option
By default, every diagnostic includes a little note naming the command-line option that directly controls it, as long as the diagnostic machinery knows which option that is ๐. Add -fno-diagnostics-show-option and that note gets suppressed โจ.
๐ฏ -fno-diagnostics-show-caret
By default, each diagnostic comes with the original source line and a caret ^ pointing at the column ๐. This option suppresses all of that. If you also pass -fmessage-length=n, the source line gets truncated to n characters. When the output goes to the terminal, the width is limited by the COLUMNS environment variable or, if that isn't set, the actual terminal width ๐.
๐ท๏ธ -fno-diagnostics-show-labels
By default, when GCC prints source code (via -fdiagnostics-show-caret), diagnostics can label ranges of code with pertinent info, like the types of expressions ๐:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses the labels ๐
โโ๏ธ, so the vertical bars and the "char *" and "long int" text in the example above disappear.
๐ -fno-diagnostics-show-cwe
Diagnostics can optionally have an associated CWE identifier, which links to https://cwe.mitre.org/index.html ๐งฉ. GCC itself only provides this metadata for some of the -fanalyzer diagnostics, and GCC plugins may also provide diagnostics with it. By default, if this info is present, it gets printed with the diagnostic. This option suppresses that metadata ๐ค.
๐ข -fno-diagnostics-show-line-numbers
By default, when printing source code (via -fdiagnostics-show-caret), a left margin gets printed showing line numbers ๐ข. This option suppresses that left margin.
๐ -fdiagnostics-minimum-margin-width=width
This controls the minimum width of the left margin printed by -fdiagnostics-show-line-numbers. It defaults to 6 ๐ธ.
๐ค -fdiagnostics-parseable-fixits
This emits fix-it hints in a machine-parseable format, so IDEs can gobble them right up ๐ซถ. 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 things like this ๐งผ: backslash becomes "\\", tab becomes "\t", newline becomes "\n", double quotes become "\"", and non-printable characters come out as octal, so a vertical tab shows up as "\013".
An empty replacement string means the given range is removed ๐๏ธ. An empty range (for example "45:3-45:3") means the string gets inserted at that position โจ.
๐ -fdiagnostics-generate-patch
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
In the C++ frontend, when diagnostics show mismatching template types, like this ๐:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
the -fdiagnostics-show-template-tree flag turns on a tree-like structure showing the common and differing parts of the types, like so ๐ฒ:
map<
[...],
vector<
[double != float]>>
The parts that differ are highlighted with color ("double" and "float" in this case) ๐จ.
๐งน -fno-elide-type
By default, when the C++ frontend prints diagnostics showing mismatching template types, the common parts get printed as "[...]" to keep the error message simple ๐งน. For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying -fno-elide-type suppresses that behavior ๐
. This flag also affects the output of -fdiagnostics-show-template-tree.
๐ค๏ธ -fdiagnostics-path-format=KIND
This specifies how to print paths of control-flow events for diagnostics that have one associated with them โจ.
KIND is none, separate-events, or inline-events, the default.
none means don't print diagnostic paths at all ๐ซ.
separate-events means print a separate "note" diagnostic for each event within the diagnostic ๐. For example:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-events means print the events "inline" within the source code ๐งต. This view tries to consolidate the events into runs of sufficiently-close events, printing them as labelled ranges within the source. For example, the same events as above might be printed as:
'test': events 1-3
|
| 25 | list = PyList_New(0);
| | ^~~~~~~~~~~~~
| | |
| | (1) when 'PyList_New' fails, returning NULL
| 26 |
| 27 | for (i = 0; i < count; i++) {
| | ~~~
| | |
| | (2) when 'i < count'
| 28 | item = PyLong_FromLong(random());
| 29 | PyList_Append(list, item);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
|
Interprocedural control flow is shown by grouping the events by stack frame, and using indentation to show how stack frames are nested, pushed, and popped ๐ง . For example:
'test': events 1-2
|
| 133 | {
| | ^
| | |
| | (1) entering 'test'
| 134 | boxed_int *obj = make_boxed_int (i);
| | ~~~~~~~~~~~~~~~~~~
| | |
| | (2) calling 'make_boxed_int'
|
+--> 'make_boxed_int': events 3-4
|
| 120 | {
| | ^
| | |
| | (3) entering 'make_boxed_int'
| 121 | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (4) calling 'wrapped_malloc'
|
+--> 'wrapped_malloc': events 5-6
|
| 7 | {
| | ^
| | |
| | (5) entering 'wrapped_malloc'
| 8 | return malloc (size);
| | ~~~~~~~~~~~~~
| | |
| | (6) calling 'malloc'
|
<-------------+
|
'test': event 7
|
| 138 | free_boxed_int (obj);
| | ^~~~~~~~~~~~~~~~~~~~
| | |
| | (7) calling 'free_boxed_int'
|
(etc)
๐ง -fdiagnostics-show-path-depths
This option adds extra info when printing control-flow paths associated with a diagnostic ๐. If it's provided, the stack depth gets printed for each run of events within -fdiagnostics-path-format=separate-events. It's intended for GCC developers and plugin developers debugging diagnostics that report interprocedural control flow ๐งโ๐ป.
๐ -fno-show-column
This stops column numbers from being printed in diagnostics ๐. It may be necessary if diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu ๐ค.
๐ -fdiagnostics-column-unit=UNIT
This selects the units for the column number ๐. It affects traditional diagnostics (in the absence of -fno-show-column), as well as JSON format diagnostics if requested ๐งพ.
โจ OPTIONS โจ
Okay so the default UNIT is display ๐, which counts the number of display columns each character actually takes up on screen. That can be bigger than the bytes needed to encode it (hello, tab characters ๐) or smaller (hello, multibyte characters ๐ฆ). For example, "GREEK SMALL LETTER PI (U+03C0)" takes up one display column but needs two bytes in UTF-8 ๐
. Meanwhile "SLIGHTLY SMILING FACE (U+1F642)" takes up two display columns and needs four bytes in UTF-8 ๐.
Setting UNIT to byte ๐ง switches the column number to the raw byte count in every case. That's how GCC used to output it before version 11.1.0, so if you're nostalgic, this is your move โจ.
-fdiagnostics-column-origin=ORIGINโ Picks where column numbering starts, aka the number given to the very first column ๐. The default of1is the classic GCC behavior and matches the GNU style guide, so it's the iconic choice. Some utilities may vibe better with an origin of0, and honestly any non-negative value works ๐.-fdiagnostics-format=FORMATโ Lets you switch up how diagnostics get printed ๐.FORMATis eithertextorjson, and the default istext, no cap ๐ .
When you go with json, you get a top-level JSON array full of JSON objects, one for each diagnostic ๐ซถ. It's emitted all on one line with zero formatting, so it looks kinda messy, but the examples below have been prettified so you can actually read them ๐ญ.
Diagnostics can also have child diagnostics ๐. Check out this error and its 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;
| ^
In JSON form (after formatting, obviously) it might look like this ๐ฆ:
[
{
"kind": "warning",
"locations": [
{
"caret": {
"display-column": 3,
"byte-column": 3,
"column": 3,
"file": "misleading-indentation.c",
"line": 15
},
"finish": {
"display-column": 4,
"byte-column": 4,
"column": 4,
"file": "misleading-indentation.c",
"line": 15
}
}
],
"message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"display-column": 5,
"byte-column": 5,
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"message": "...this statement, but the latter is ..."
}
]
"column-origin": 1,
},
...
]
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 telling you which command-line option is controlling the warning ๐ฅ.
A diagnostic can hold zero or more locations ๐ธ. Each location can have an optional "label" string and up to three positions: a "caret" position plus optional "start" and "finish" positions. Every position is described by a "file" name, a "line" number, and three numbers for the column position ๐
:
"display-column"counts display columns, accounting for tabs and multibyte characters ๐."byte-column"counts raw bytes ๐ง."column"is equal to one of the previous two, depending on what the-fdiagnostics-column-unitoption says ๐.
All three columns are relative to the origin set by -fdiagnostics-column-origin, which is usually 1 but could be set to 0 for compatibility with utilities that count columns from zero ๐. The origin gets recorded in the JSON output under the "column-origin" tag โญ. In the rest of the examples, the extra column outputs got left out to keep things short ๐ซถ.
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 ๐ญ. The primary one is at the + token, column 23 ๐. It also has two secondary locations, one for the left-hand side and one for the right-hand side of the expression, and both of those come with labels ๐. It might be printed in JSON form as:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"message": "invalid operands to binary + ..."
}
If a diagnostic has fix-it hints, it gets a "fixits" array ๐ ๏ธโจ. Those are half-open intervals, kinda like what you'd get from -fdiagnostics-parseable-fixits ๐ฆ. Here's a diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
It might come out in JSON form like this ๐ :
{
"children": [],
"fixits": [
{
"next": {
"column": 21,
"file": "demo.c",
"line": 8
},
"start": {
"column": 15,
"file": "demo.c",
"line": 8
},
"string": "color"
}
],
"kind": "error",
"locations": [
{
"caret": {
"column": 15,
"file": "demo.c",
"line": 8
},
"finish": {
"column": 20,
"file": "demo.c",
"line": 8
}
}
],
"message": "\u2018struct s\u2019 has no member named ..."
}
So the fix-it hint says to replace the text from "start" up to, but not including, "next" with the value of "string" ๐ธ. Deletions are written as an empty "string" value, and insertions are written by making "start" equal "next" ๐.
If the diagnostic has a path of control-flow events attached to it ๐ง, it gets a "path" array of event objects ๐. Each event has a "description" string, a "location" object, a "function" string, and a "depth" number, which is how interprocedural paths get represented ๐. The "function" tells you the current function at that event, and the "depth" shows the stack depth compared to some baseline: the higher the number, the more frames are sitting 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
}
}
]
๐ Options to Request or Suppress Warnings ๐
okay so warnings are GCC going "hmm, sus ๐ง" about stuff that isn't technically broken, but is risky or might mean you messed up somewhere ๐
these next few are language-independent, so they work across the board ๐ they don't switch on any specific warning, they just control what kind of diagnostics GCC spits out ๐
-fsyntax-onlyโ checks your code for syntax errors and then stops there. no extra nonsense ๐ซถ-fmax-errors=nโ caps the number of error messages atn. once it hits that number, GCC bails instead of trying to keep going through your source code ๐ญ ifnis0(the default), there's no limit on how many errors it'll print. if-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option ๐-wโ inhibits all warning messages. silence is golden โจ-Werrorโ turns every single warning into an error ๐ฅ-Werror=โ turns one specific warning into an error. you just tack on the warning's name, so for example-Werror=switchmakes the warnings controlled by-Wswitchinto errors ๐ this one also has a negative form, which negates-Werrorfor specific warnings. for example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐- every controllable warning message includes the option that controls it, and you can use that option with
-Werror=and-Wno-error=like we just talked about. (printing the option in the warning message can be disabled using the-fno-diagnostics-show-optionflag ๐) - note that specifying
-Werror=fooautomatically implies-Wfoo. however,-Wno-error=foodoes not imply anything ๐
- every controllable warning message includes the option that controls it, and you can use that option with
-Wfatal-errorsโ makes the compiler abort compilation on the very first error it hits, instead of trying to keep going and printing more error messages ๐
you can request a bunch 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 them off, like -Wno-implicit. this manual only lists one of the two forms, whichever one isn't the default ๐ง for further language-specific options, also refer to C++ Dialect Options and Objective-C and Objective-C++ Dialect Options. additional warnings can be produced by enabling the static analyzer;
okay so some options, like -Wall and -Wextra, turn on other options, like -Wunused, which may then turn on even more options, like -Wunused-value. the combined effect of positive and negative forms is that more specific options have priority over less specific ones, no matter where they sit on the command line ๐ธ for options of the same specificity, the last one takes effect. options enabled or disabled via pragmas take effect as if they appeared at the end of the command line ๐
when you request an unrecognized warning option (e.g., -Wunknown-warning), GCC emits a diagnostic saying the option isn't recognized. but if the -Wno- form is used, it's a little different: no diagnostic is produced for -Wno-unknown-warning unless other diagnostics are being produced. this lets you use new -Wno- options with old compilers, but if something goes wrong, the compiler warns that an unrecognized option is present ๐ซถ
the effectiveness of some warnings depends on optimizations also being enabled. for example, -Wsuggest-final-types is more effective with link-time optimization, and -Wmaybe-uninitialized does not warn at all unless optimization is enabled ๐ญ
-Wpedantic,-pedanticโ issues all the warnings demanded by strict ISO C and ISO C++, rejects all programs that use forbidden extensions, and rejects some other programs that don't follow ISO C and ISO C++ ๐ for ISO C, it follows the version of the ISO C standard specified by any-stdoption used.- valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few require
-ansior a-stdoption specifying the required version of ISO C). however, without this option, certain GNU extensions and traditional C and C++ features are supported too. with this option, they get rejected ๐ โโ๏ธ -Wpedanticdoes not cause warning messages for use of the alternate keywords whose names begin and end with__. this alternate format can also be used to disable warnings for non-ISO__intNtypes, i.e.__intN__. pedantic warnings are also disabled in the expression that follows"__extension__". however, only system header files should use these escape routes; application programs should avoid them ๐ซ- some users try to use
-Wpedanticto check programs for strict ISO C conformance. they soon find that it doesn't quite do what they want: it finds some non-ISO practices, but not all---only the ones for which ISO C requires a diagnostic, plus some others that have had diagnostics added ๐ฅฒ - a feature to report any failure to conform to ISO C might be useful in some instances, but it would require a ton of additional work and would be quite different from
-Wpedantic. there are no plans to support such a feature in the near future ๐ง - where the standard specified with
-stdrepresents a GNU extended dialect of C, such asgnu90orgnu99, there's a corresponding base standard: the version of ISO C that the GNU extended dialect is based on. warnings from-Wpedanticare given where they're required by the base standard. (it doesn't make sense for those warnings to only cover features that aren't in the specified GNU C dialect, since by definition the GNU dialects of C include all features the compiler supports with the given option, and there would be nothing to warn about ๐คทโโ๏ธ)
- valid ISO C and ISO C++ programs should compile properly with or without this option (though a rare few require
-pedantic-errorsโ gives an error whenever the base standard (see-Wpedantic) requires a diagnostic, 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 equivalent to-Werror=pedantic, since there are errors enabled by this option that the latter doesn't enable, and vice versa ๐-Wallโ enables all the warnings about constructions that some users consider questionable and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros ๐ this also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
-Wall turns on the following warning flags:
-Waddress -Warray-bounds=1 (only with -O2) -Warray-parameter=2 (C
and Objective-C only) -Wbool-compare -Wbool-operation -Wc++11-compat
-Wc++14-compat -Wcatch-value (C++ and Objective-C++ only)
-Wchar-subscripts -Wcomment -Wduplicate-decl-specifier (C and
Objective-C only) -Wenum-compare (in C/ObjC; this is on by default
in C++) -Wformat -Wformat-overflow -Wformat-truncation
-Wint-in-bool-context -Wimplicit (C and Objective-C only)
-Wimplicit-int (C and Objective-C only)
-Wimplicit-function-declaration (C and Objective-C only) -Winit-self
(only for C++) -Wlogical-not-parentheses -Wmain (only for C/ObjC and
unless -ffreestanding) -Wmaybe-uninitialized -Wmemset-elt-size
-Wmemset-transposed-args -Wmisleading-indentation (only for C/C++)
-Wmissing-attributes -Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros -Wnarrowing (only for C++) -Wnonnull
-Wnonnull-compare -Wopenmp-simd -Wparentheses -Wpessimizing-move
(only for C++) -Wpointer-sign -Wrange-loop-construct (only for C++)
-Wreorder -Wrestrict -Wreturn-type -Wsequence-point -Wsign-compare
(only in C++) -Wsizeof-array-div -Wsizeof-pointer-div
-Wsizeof-pointer-memaccess -Wstrict-aliasing -Wstrict-overflow=1
-Wswitch -Wtautological-compare -Wtrigraphs -Wuninitialized
-Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value
-Wunused-variable -Wvla-parameter (C and Objective-C only)
-Wvolatile-register-var -Wzero-length-bounds
note that some warning flags are not implied by -Wall ๐ some of them warn about constructions that users generally don't consider questionable, but which 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 modify the code to suppress the warning. some of them are enabled by -Wextra, but many of them have to be enabled individually ๐
-Wextraโ enables some extra warning flags that are not enabled by-Wall. (this option used to be called-W. the older name is still supported, but the newer name is more descriptive ๐ง)
the extra flags it turns on are:
-Wclobbered -Wcast-function-type -Wdeprecated-copy (C++ only)
-Wempty-body -Wenum-conversion (C only) -Wignored-qualifiers
-Wimplicit-fallthrough=3 -Wmissing-field-initializers
-Wmissing-parameter-type (C only) -Wold-style-declaration (C only)
-Woverride-init -Wsign-compare (C only) -Wstring-compare
-Wredundant-move (only for C++) -Wtype-limits -Wuninitialized
-Wshift-negative-value (in C++11 to C++17 and in C99 and newer)
-Wunused-parameter (only with -Wunused or -Wall)
-Wunused-but-set-parameter (only with -Wunused or -Wall)
Okay so -Wextra is lowkey not done yet ๐ it also yells about these bad boys ๐ฅ:
- A pointer compared against integer zero with
<,<=,>, or>=๐ - (C++ only) An enumerator and a non-enumerator both showing up in a conditional expression
- (C++ only) Ambiguous virtual bases
- (C++ only) Subscripting an array that's been declared
register - (C++ only) Taking the address of a variable that's been declared
register - (C++ only) A base class that isn't initialized in the copy constructor of a derived class
-Wabi (C, Objective-C, C++ and Objective-C++ only)
Ohh, this one is all about ABI changes ๐ซถ It warns about code that's affected by ABI changes, including code that might not be compatible with the vendor-neutral C++ ABI, and code that might not match the psABI for your particular target.
Since G++ now defaults to updating the ABI with each major release, normally -Wabi only warns about C++ ABI compatibility problems if there's a check added later in a release series for an ABI issue that was discovered after the initial release. -Wabi warns about more things if an older ABI version is selected with -fabi-version=n. ๐ธ
You can also give -Wabi an explicit version number to warn about C++ ABI compatibility with a particular -fabi-version level, like -Wabi=2 to warn about changes relative to -fabi-version=2.
If an explicit version number is provided and -fabi-compat-version isn't specified, the version number from this option is used for compatibility aliases. If there's no explicit version number with this option, but -fabi-compat-version is specified, that version number gets used for C++ ABI warnings.
GCC tried really hard to warn about every case ๐ญ but there are probably some cases that go unwarned, even though G++ is generating incompatible code. There may also be cases where warnings pop up even though the generated code is actually compatible.
You should rewrite your code to avoid these warnings if you're worried that code generated by G++ might not be binary compatible with code generated by other compilers. ๐
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 didn't allow for overloading of functions taking vectors of different sizes. The mangling was changed in -fabi-version=4.
๐ __attribute ((const)) and noreturn were mangled as type qualifiers, and decltype of a plain declaration got folded away. These mangling issues were fixed in -fabi-version=5.
๐ Scoped enumerators passed as arguments to a variadic function get promoted like unscoped enumerators, which makes va_arg complain. On most targets this doesn't actually affect the parameter passing ABI, since there's no way to pass an argument smaller than int. The ABI also changed the mangling of template argument packs, const_cast, static_cast, prefix increment/decrement, and a class scope function used as a template argument. These issues were corrected in -fabi-version=6.
๐ Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of nullptr_t. These issues were corrected in -fabi-version=7.
๐ Function types with function-cv-qualifiers: when mangling one, the un-qualified function type was incorrectly treated as a substitution candidate. This was fixed in -fabi-version=8, the default for GCC 5.1.
๐ decltype(nullptr) incorrectly had an alignment of 1, leading to unaligned accesses. This didn't affect the ABI of a function with a nullptr_t parameter, since parameters have a minimum alignment. This was fixed in -fabi-version=9, the default for GCC 5.2.
๐ Target-specific attributes that affect the identity of a type, like ia32 calling conventions on a function type (stdcall, regparm, etc.), didn't affect the mangled name. That caused name collisions when function pointers were used as template arguments. This was fixed in -fabi-version=10, the default for GCC 6.1.
This option also enables warnings about psABI-related changes. The known psABI changes at this point include:
- For SysV/x86-64, unions with
long doublemembers are passed in memory as specified in psABI. Prior to GCC 4.4, this was not the case. For example:
union U {
long double ld;
int i;
};
union U is now always passed in memory. ๐
-Wchar-subscripts
Warns if an array subscript has type char. This is a common cause of errors, because programmers often 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 using the -fprofile-use option. If a source file is changed between compiling with -fprofile-generate and with -fprofile-use, the files with the profile feedback can fail to match the source file, and GCC can't use the profile feedback information. By default, this warning is enabled and is treated as an error. -Wno-coverage-mismatch can be used to disable the warning, or -Wno-error=coverage-mismatch can be used to disable the error. Disabling the error for this warning can result in poorly optimized code, and it's only useful for very minor changes, like bug fixes to an existing code-base. Completely disabling the warning is not recommended. ๐จ
-Wno-cpp (C, Objective-C, C++, Objective-C++ and Fortran only)
Suppresses warning messages emitted by #warning directives. ๐ง
-Wdouble-promotion (C, C++, Objective-C and Objective-C++ only)
Gives a warning when a value of type float is implicitly promoted to double. CPUs with a 32-bit single-precision floating-point unit implement float in hardware, but emulate double in software. On a machine like that, doing computations with double values is much more expensive because of the overhead required for software emulation. ๐ค
It's super easy to accidentally do computations with double, 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 duplicate const, volatile, restrict or _Atomic specifier. This warning is enabled by -Wall. โจ
-Wformat, -Wformat=n
Checks calls to printf and scanf, etc., to make sure the arguments supplied have types that fit 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 the printf, scanf, strftime and strfmon (an X/Open extension, not in the C standard) families, or other target-specific families. Which functions get checked without format attributes depends on the standard version you've selected, and those checks are disabled by -ffreestanding or -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, as well as features from the Single Unix Specification and some BSD and GNU extensions. Other library implementations may not support all of these, and GCC doesn't warn about features that go beyond a particular library's limitations. However, if -Wpedantic is used with -Wformat, warnings are given 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
-Wformat is equivalent to -Wformat=1, and -Wno-format is equivalent to -Wformat=0. Since -Wformat also checks for null format arguments for several functions, it also implies -Wnonnull. Some aspects of this level of format checking can be disabled with these options: -Wno-format-contains-nul, -Wno-format-extra-args, and -Wno-format-zero-length. -Wformat is enabled by -Wall. ๐
-Wformat=2
Enables -Wformat plus additional format checks. Currently equivalent to -Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k. ๐
-Wno-format-contains-nul
If -Wformat is specified, don't warn about format strings that contain NUL bytes.
-Wno-format-extra-args
If -Wformat is specified, don't warn about excess arguments to a printf or scanf format function. The C standard says such arguments are ignored. ๐
Where the unused arguments lie between used arguments that are specified with $ operand number specifications, warnings are normally still given, since the implementation couldn't know what type to pass to va_arg to skip the unused arguments. However, for scanf formats, this option suppresses the warning if the unused arguments are all pointers, since the Single Unix Specification says such unused arguments are allowed.
-Wformat-overflow, -Wformat-overflow=level
Warns about calls to formatted input/output functions, such as sprintf and vsprintf, 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. Enabling optimization will in most cases improve the accuracy of the warning, but it may also result in false positives. Watch out for those false alarms ๐ฅ
-Wformat-overflow,-Wformat-overflow=1โ okay bestie, this is the chill level ๐ Level 1 is switched on by-Wformatand it's super conservative, so it only yells about calls that most likely overflow the buffer ๐ Numeric arguments with unknown values get treated as1, and strings of unknown length get treated as empty. Numeric arguments known to be bounded to a subrange of their type, or string arguments whose output is bounded by the directive's precision or by a finite set of string literals, are assumed to take whatever value in that range gives the most bytes of output. So thesprintfcall below gets flagged because even withaandbboth zero, the terminating NUL character ('\0') that the function tacks onto the destination buffer gets written past its end ๐ญ Making the buffer just one byte bigger is enough to dodge the warning โจ, though that might not be enough to actually stop 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 is the "okay but what if" level ๐ฅ It warns about calls that might overflow the destination buffer if an argument is long enough or big enough in magnitude. At level 2, unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments that can't be assumed bounded (by the directive's precision, 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 size of the buffer in an informational note after the warning, so you don't have to guess ๐ซถ
An alternative to making the buffer bigger is to constrain 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 can be assumed to be bounded by less than the precision of their type, picking an appropriate length modifier for the format specifier will shrink the 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 size of the buffer to 24 bytes.
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
-Wno-format-zero-lengthโ if-Wformatis specified, don't warn about zero-length formats ๐ธ The C standard says zero-length formats are allowed, so no drama needed.-Wformat-nonliteralโ if-Wformatis specified, also warn if the format string isn't a string literal and therefore can't be checked ๐ง The exception is when the format function takes its format arguments as ava_list.-Wformat-securityโ if-Wformatis specified, also warn about format function uses that could be security problems ๐จ Right now it warns about calls toprintfandscanfwhere the format string isn't a string literal and there are no format arguments, likeprintf (foo);. That can be a security hole if the format string came from untrusted input and contains%n. (This is currently a subset of what-Wformat-nonliteralwarns about, but future warnings may be added to-Wformat-securitythat aren't included in-Wformat-nonliteral.)-Wformat-signednessโ if-Wformatis specified, also warn if the format string requires an unsigned argument and the argument is signed, and vice versa ๐ข-Wformat-truncation,-Wformat-truncation=levelโ warn about calls to formatted input/output functions likesnprintfandvsnprintfthat might result in output truncation โ๏ธ When the exact number of bytes written by a format directive can't be figured out at compile time, it's estimated using heuristics that depend on the level argument and on optimization. Turning on optimization will usually make the warning more accurate, but it can also cause false positives. Except where noted otherwise, this option uses the same logic as-Wformat-overflow.-Wformat-truncation,-Wformat-truncation=1โ level 1 of-Wformat-truncationis enabled by-Wformatand is conservative ๐ซง It only warns about calls to bounded functions whose return value is unused and that will most likely result in output truncation.-Wformat-truncation=2โ level 2 also warns about calls to bounded functions whose return value is used and that might result in truncation, given an argument of sufficient length or magnitude ๐
-Wformat-y2kโ if-Wformatis specified, also warn aboutstrftimeformats that may yield only a two-digit year ๐ Y2K vibes, not it ๐-Wnonnullโ warn about passing a null pointer for arguments marked as requiring a non-null value by thenonnullfunction attribute ๐ซ-Wnonnullis included in-Walland-Wformat, and it can be disabled with the-Wno-nonnulloption.-Wnonnull-compareโ warn when comparing an argument marked with thenonnullfunction attribute against null inside the function ๐-Wnonnull-compareis included in-Wall, and it can be disabled with the-Wno-nonnull-compareoption.-Wnull-dereferenceโ warn if the compiler detects paths that trigger erroneous or undefined behavior due to dereferencing a null pointer ๐ณ๏ธ This option is only active when-fdelete-null-pointer-checksis active, which is enabled by optimizations on most targets. How precise the warnings are depends on the optimization options you use.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ warn about uninitialized variables that get initialized with themselves ๐ช Note this option can only be used together with the-Wuninitializedoption.
For example, GCC warns about i being uninitialized in the following snippet only when -Winit-self has been specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++ โจ
-Wno-implicit-int(C and Objective-C only) โ this option controls warnings when a declaration doesn't specify a type ๐งฉ The 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) โ this option controls warnings when a function is used before it's declared ๐ฃ The warning is enabled by default in C99 and later dialects of C, and also by-Wall. It gets upgraded to an error by-pedantic-errors, so be careful ๐-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declaration๐ This warning is enabled by-Wall.-Wimplicit-fallthroughโ same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0๐ฆ-Wimplicit-fallthrough=nโ warn 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, like ifs, into account, and only warns when it's appropriate. E.g.
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a switch case falling through is actually desirable ๐ซ For that, GCC provides an attribute, __attribute__ ((fallthrough)), which is used along with a null statement to suppress the warning that would normally happen:
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 gives you a standard way to suppress the -Wimplicit-fallthrough warning using [[fallthrough]]; instead of the GNU attribute ๐ In C++11 or C++14, you can use [[gnu::fallthrough]];, which is a GNU extension. Instead of these attributes, you can also add a fallthrough comment to silence the warning ๐ฌ The whole body of the C or C++ style comment has to match the regular expressions listed below. The option argument n specifies what kind of comments are accepted:
-Wimplicit-fallthrough=0โ disables the warning altogether ๐ โโ๏ธ-Wimplicit-fallthrough=1โ matches the".*"regular expression, so any comment is used as a fallthrough comment ๐-Wimplicit-fallthrough=2โ case insensitively matches the".*falls?[ \t-]*thr(ough|u).*"regular expression ๐ธ-Wimplicit-fallthrough=3โ case sensitively matches one of the following regular expressions:
Okay so the =3 lineup keeps going, and these are all the comment patterns GCC will accept as a fallthrough note ๐
"-fallthrough"
"@fallthrough@"
"lint -fallthrough[ \t]*"
"[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?"
"[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?"
"[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
The -Wimplicit-fallthrough=4 level is way pickier ๐ It's case sensitive and only matches one of these four patterns:
"-fallthrough"
"@fallthrough@"
"lint -fallthrough[ \t]*"
"[ \t]*FALLTHR(OUGH|U)[ \t]*"
And -Wimplicit-fallthrough=5 is the no-nonsense one ๐ฅ It doesn't recognise any comments as fallthrough comments. Only attributes can shut the warning up.
The comment has to be followed, after optional whitespace and other comments, by a case or default keyword, or by a user label that sits in front of a case or default label. Like this:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is turned on by -Wextra โจ
-Wno-if-not-aligned(C, C++, Objective-C and Objective-C++ only) โ lets you decide whether warnings triggered by thewarn_if_not_alignedattribute actually get issued. They're on by default ๐ธ-Wignored-qualifiers(C and C++ only) โ warns if a function's return type has a qualifier likeconst. In ISO C that qualifier does nothing, since a function's return value isn't an lvalue. In C++ the warning only fires for scalar types orvoid. ISO C bans qualifiedvoidreturn types on function definitions, so those always get a warning, even without this option. This one's also enabled by-Wextra๐-Wno-ignored-attributes(C and C++ only) โ controls warnings for when an attribute gets ignored. It's different from-Wattributes, because this one speaks up whenever the compiler decides to drop an attribute.-Wattributescares about whether the attribute is unknown or in the wrong spot. It's on by default ๐ฆ-Wmainโ warns if the type ofmainis sus.mainshould be a function with external linkage that returnsint, and takes either zero arguments, two, or three arguments of the appropriate types. It's enabled by default in C++, and by either-Wallor-Wpedantic๐-Wmisleading-indentation(C and C++ only) โ warns when the indentation doesn't match the real block structure. Specifically, it fires forif,else,while, andforclauses with a guarded statement that has no braces, followed by an unguarded statement at the same indent. Look at the call tobarbelow. It looks guarded by theif, but it totally isn't ๐
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
If you mix tabs and spaces, the warning uses -ftabstop= to figure out whether the statements line up. That defaults to 8.
It won't warn about multiline preprocessor logic like this:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
It also skips anything after a #line directive, because that usually means autogenerated code, and you can't make any assumptions about the layout of the file that directive points to. This one's enabled by -Wall in C and C++ โจ
-Wmissing-attributesโ warns when a function declaration is missing one or more attributes that a related function is declared with, and that absence could hurt the correctness or efficiency of the generated code. A classic example is an alias declaration that uses attributes to ask for less strict requirements than its target. That's usually a potential optimisation opportunity ๐ By contrast,-Wattribute-alias=2warns when the alias is more restrictive than the target, which could lead to incorrect code generation. The attributes it checks arealloc_align,alloc_size,cold,const,hot,leaf,malloc,nonnull,noreturn,nothrow,pure,returns_nonnull, andreturns_twice.
In C++, the warning fires when an explicit specialisation of a primary template declared with alloc_align, alloc_size, assume_aligned, format, format_arg, malloc, or nonnull is declared without it. The deprecated, error, and warning attributes suppress the warning.
You can use the copy attribute to apply the same set of attributes to a declaration as another declaration has, without listing them all out. It works on declarations of functions, variables, or types ๐ง
-Wmissing-attributes is enabled by -Wall.
For example, the primary function template below uses both the malloc and alloc_size attributes. That means the explicit specialisation is flagged, because it's missing one of them:
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
-Wmissing-bracesโ warns if an aggregate or union initialiser isn't fully bracketed. In the example below, the initialiser foraisn't fully bracketed, but the one forbis ๐
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall.
-Wmissing-include-dirs(C, C++, Objective-C and Objective-C++ only) โ warns if a user-supplied include directory doesn't exist ๐-Wno-missing-profileโ controls warnings when feedback profiles are missing while you're using-fprofile-use. It catches the cases where a new function or a new file got added between compiling with-fprofile-generateand 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 information at all. In every one of these cases, you get warnings telling you a profile generation step is due ๐ญ Ignoring them can result in poorly optimised code. You can use-Wno-missing-profileto switch the warning off, but that's not recommended, and it should only happen when non-existent profile data is actually justified.-Wno-mismatched-deallocโ warns for calls to deallocation functions with pointer arguments that came from allocation functions the deallocator isn't suitable for. You can link a pair of functions as matching allocator and deallocator with themallocattribute. Unless-fno-builtinturns it off, the standard functionscalloc,malloc,realloc, andfree, along with the matching C++ forms ofoperator newandoperator delete, are implicitly treated as matching allocators and deallocators. In the example,mydeallocis the deallocator for pointers returned frommyalloc๐
void mydealloc (void*);
__attribute__ ((malloc (mydealloc, 1))) void*
myalloc (size_t);
void f (void)
{
void *p = myalloc (32);
// ...use p...
free (p); // warning: not a matching deallocator for myalloc
mydealloc (p); // ok
}
In C++, the related option -Wmismatched-new-delete diagnoses mismatches involving either operator new or operator delete.
Option -Wmismatched-dealloc is enabled by default.
-Wmultistatement-macrosโ warns about unsafe multi-statement macros that look guarded by a clause likeif,else,for,switch, orwhile, when only the first statement is actually guarded once the macro expands ๐
For example:
#define DOIT x++; y++
if (c)
DOIT;
This will increment y unconditionally, not just when c holds. You can usually fix it by wrapping the macro in a do-while loop:
#define DOIT do { x++; y++; } while (0)
if (c)
DOIT;
This warning is enabled by -Wall in C and C++.
-Wparenthesesโ warns if parentheses are left out in certain spots, like when there's an assignment where a truth value is expected, or when operators are nested in a way people often mix up the precedence of ๐
It also warns if you write a comparison like x<=y<=z. That's equivalent to (x<=y ? 1 : 0) <= z, which is a different reading from normal maths notation ๐ญ
It also warns about dangerous uses of the GNU extension to ?: with the middle operand omitted. When the condition in the ?: operator is a boolean expression, the omitted value is always 1. Programmers often expect it to be a value computed inside the conditional expression instead.
For C++, this also warns about some unnecessary parentheses in declarations, which can mean you meant to make a function call instead of a declaration:
{
// Declares a local variable called mymutex.
std::unique_lock<std::mutex> (mymutex);
// User meant std::unique_lock<std::mutex> lock (mymutex);
}
This warning is enabled by -Wall.
-Wsequence-pointโ warns about code that might have undefined semantics because it breaks the sequence point rules in the C and C++ standards. Be careful with this one, bestie ๐ซถ
The C and C++ standards define the order that expressions run in using sequence points ๐. Think of them as checkpoints in your program: everything before a checkpoint is finished, and nothing after it has started yet. A sequence point happens after a full expression (one that isn't part of a bigger expression) โจ, after the first operand of a &&, ||, ? :, or , (comma) operator ๐
, before a function is called (but after its arguments and the expression naming the function are evaluated) ๐ฆ, and in a few other spots too. Apart from what the sequence point rules say, the order in which subexpressions get evaluated is unspecified ๐. The rules only give a partial order, not a total one. For example, if two functions get called inside one expression with no sequence point between them, the order of those calls is unspecified. The standards committee did rule that function calls never overlap, though ๐.
It's also unspecified when, between sequence points, changes to an object's value actually take effect ๐ญ. Programs that depend on this have undefined behavior. The standards say: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.". If your program breaks these rules, the results on any given implementation are totally unpredictable ๐. Bestie, don't do that.
Examples of code with undefined behavior include a = a++;, a[n] = b[n++], and a[i++] = i; ๐. Some trickier cases won't get caught by this option, and it might occasionally give a false positive โ ๏ธ. Overall though, it's been pretty effective at catching this kind of problem ๐ฅ.
The C++17 standard defines 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 ๐. This option will still warn about them anyway ๐ซถ, to help people avoid writing code that's undefined in C and in earlier revisions of C++.
The standard is worded super confusingly, so people genuinely debate the exact meaning of the sequence point rules in subtle cases ๐ญ. Links to discussions of the problem, including proposed formal definitions, can be found on the GCC readings page at http://gcc.gnu.org/readings.html ๐.
This warning is enabled by -Wall for C and C++ ๐.
-Wno-return-local-addrโ Don't warn about returning a pointer (or, in C++, a reference) to a variable that goes out of scope once the function returns ๐ง.-Wreturn-typeโ Warn whenever a function gets defined with a return type that defaults toint๐. It also warns about anyreturnstatement with no return value inside a function whose return type isn'tvoid(falling off the end of the function body counts as returning without a value ๐).- For C only, it warns about a
returnstatement with an expression inside a function whose return type isvoid, unless the expression's type is alsovoid. As a GNU extension, that latter case is accepted without a warning unless-Wpedanticis used ๐ค. - Using the return value of a non-
voidfunction (other thanmain) that flows off the end by reaching the closing curly brace is undefined behavior ๐. - Unlike C, in C++ flowing off the end of a non-
voidfunction (other thanmain) results in undefined behavior even if the function's value never gets used ๐ญ. - This warning is enabled by default in C++ and by
-Wallotherwise โจ.
- For C only, it warns about a
-Wno-shift-count-negativeโ Controls warnings for when a shift count is negative ๐ธ. This warning is enabled by default ๐.-Wno-shift-count-overflowโ Controls warnings for when a shift count is greater than or equal to the bit width of the type ๐ฆ. This warning is enabled by default ๐.-Wshift-negative-valueโ Warn if you left shift a negative value ๐ซฃ. This warning is enabled by-Wextrain C99 (and newer) and in C++11 through C++17 modes ๐.-Wno-shift-overflow,-Wshift-overflow=nโ These options control warnings about left shift overflows ๐.-Wshift-overflow=1โ This is the warning level of-Wshift-overflow, and it's enabled by default in C99 and C++11 modes (and newer) โจ. This level doesn't warn about left-shifting 1 into the sign bit. (However, in C, that kind of overflow is still rejected in contexts where an integer constant expression is required ๐ .) No warning is emitted in C++20 mode (and newer), since signed left shifts always wrap ๐.-Wshift-overflow=2โ This level also warns about left-shifting 1 into the sign bit, unless C++14 mode (or newer) is active ๐ฅ.
-Wswitchโ Warn whenever aswitchstatement has an index of enumerated type and is missing acasefor one or more of that enumeration's named codes ๐ . (Having adefaultlabel stops this warning from firing ๐.)caselabels outside the enumeration's range also set off warnings with this option, even if there's adefaultlabel ๐ซถ. This warning is enabled by-Wallโจ.-Wswitch-defaultโ Warn whenever aswitchstatement doesn't have adefaultcase ๐ง.-Wswitch-enumโ Warn whenever aswitchstatement has an index of enumerated type and is missing acasefor one or more of that enumeration's named codes ๐ฆ.caselabels outside the enumeration's range also trigger warnings with this option ๐. The only difference between-Wswitchand this option is that this one warns about an omitted enumeration code even when there's adefaultlabel ๐.-Wno-switch-boolโ Don't warn when aswitchstatement has an index of boolean type and thecasevalues fall outside the range of a boolean type ๐. You can suppress this warning by casting the controlling expression to a type other thanbool๐. For example:
switch ((int) (a == 4))
{
...
}
This warning is enabled by default for C and C++ programs ๐.
-Wno-switch-outside-rangeโ Controls warnings when aswitchcasehas a value outside its respective type range ๐ธ. This warning is enabled by default for C and C++ programs โจ.-Wno-switch-unreachableโ Don't warn when aswitchstatement contains statements between the controlling expression and the firstcaselabel, since those statements will never run ๐. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
-Wswitch-unreachable doesn't warn if the statement between the controlling expression and the first case label is just a declaration ๐งธ:
switch (cond)
{
int i;
...
case 5:
i = 5;
...
}
This warning is enabled by default for C and C++ programs ๐ .
-Wsync-nand(C and C++ only) โ Warn when the__sync_fetch_and_nandand__sync_nand_and_fetchbuilt-in functions are used ๐จ. These functions changed semantics in GCC 4.4 ๐ญ.-Wunused-but-set-parameterโ Warn whenever a function parameter gets assigned to but is otherwise unused (aside from its declaration) ๐ฅบ. To suppress this warning, use theunusedattribute ๐ซถ. This warning is also enabled by-Wunusedtogether with-Wextra๐.-Wunused-but-set-variableโ Warn whenever a local variable gets assigned to but is otherwise unused (aside from its declaration) ๐. This warning is enabled by-Wallโจ. To suppress it, use theunusedattribute ๐. This warning is also enabled by-Wunused, which is itself enabled by-Wall๐.-Wunused-functionโ Warn whenever astaticfunction is declared but not defined, or a non-inlinestaticfunction goes unused ๐ฆ. This warning is enabled by-Wall๐.-Wunused-labelโ Warn whenever a label is declared but never used ๐ท๏ธ. This warning is enabled by-Wallโจ. To suppress it, use theunusedattribute ๐ซถ.-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ Warn when atypedefdefined locally inside a function isn't used ๐. This warning is enabled by-Wall๐ธ.-Wunused-parameterโ Warn whenever a function parameter is unused, aside from its declaration ๐ง. To suppress this warning, use theunusedattribute ๐ซถ.-Wno-unused-resultโ Don't warn if a caller of a function marked with the attributewarn_unused_resultdoesn't use its return value ๐. The default is-Wunused-result๐ .-Wunused-variableโ Warn whenever a local orstaticvariable is unused, aside from its declaration ๐. For C, this option implies-Wunused-const-variable=1, but for C++ it doesn't ๐. This warning is enabled by-Wallโจ. To suppress it, use theunusedattribute ๐.-Wunused-const-variable,-Wunused-const-variable=nโ Warn whenever a constantstaticvariable is unused, aside from its declaration ๐.-Wunused-const-variable=1is enabled by-Wunused-variablefor C, but not for C++ ๐ซถ. In C this declares variable storage, but in C++ it isn't an error, sinceconstvariables take the place of#defines ๐ค. To suppress this warning, use theunusedattribute ๐.-Wunused-const-variable=1โ This is the warning level that-Wunused-variableenables for C ๐. It only warns about unusedstatic constvariables defined in the main compilation unit, not aboutstatic constvariables declared in any included header ๐งธ.-Wunused-const-variable=2โ This warning level also warns about unused constantstaticvariables in headers (excluding system headers) ๐. This is the warning level of-Wunused-const-variable, and it must be explicitly requested, since in C++ this isn't an error and in C it can be harder to clean up every header that gets included ๐ญ.
-Wunused-valueโ ๐ Warns whenever a statement computes a result that's explicitly not used. Rude. To shut it up, cast the unused expression tovoid. This also covers an expression-statement or the left-hand side of a comma expression that has no side effects. Sox[i,j]gets flagged, butx[(void)i,j]is totally fine ๐ซถ
This warning is enabled by -Wall. โจ
-Wunusedโ the whole squad of-Wunusedoptions combined ๐
To get a warning about an unused function parameter, you have to either specify -Wextra -Wunused (note that -Wall already implies -Wunused), or specify -Wunused-parameter separately. ๐
-Wuninitializedโ ๐ฅบ Warns if an object with automatic or allocated storage duration gets used without having been initialized. In C++, it also warns if a non-static reference or non-staticconstmember shows up in a class that has no constructors.
Passing a pointer (or in C++, a reference) to an uninitialized object into a const-qualified argument of a built-in function known to read that object gets diagnosed by this warning too. (-Wmaybe-uninitialized is the one for ordinary functions.)
If you want to warn about code that uses the uninitialized value of a variable inside its own initializer, use the -Winit-self option. ๐
These warnings pop up for individual uninitialized elements of structure, union, or array variables, as well as for variables that are uninitialized as a whole. They do not 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 version of GCC you're using. ๐
โ ๏ธ Heads up: there may be no warning about a variable that's only used to compute a value that's never used itself, because those computations can get deleted by data flow analysis before the warnings are printed. ๐
-Wno-invalid-memory-modelโ This one controls warnings for invocations of__atomicBuiltins,__syncBuiltins, 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, the__atomic_storeand__atomic_store_nbuilt-ins are only defined for the relaxed, release, and sequentially consistent memory orders, so the following code gets diagnosed:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
-Winvalid-memory-model is enabled by default. ๐
-Wmaybe-uninitializedโ ๐ธ For an object with automatic or allocated storage duration, if there's a path from the function entry to a use of the object where it is initialized, but some other paths leave it uninitialized, 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 is also diagnosed by this warning. (-Wuninitialized is issued for built-in functions known to read the object.) Annotating the function with attribute access (none) says the argument isn't used to access the object, and that avoids the warning. โจ
These warnings are only possible in optimizing compilation, because otherwise GCC doesn't keep track of the state of variables. ๐ง
These warnings are optional because GCC may not be able to tell when code is correct even though it looks like an error. Here's one example of how that can happen:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know that. To suppress the warning, you need to provide a default case with assert(0) or similar code. ๐ซถ
This option also warns when a non-volatile automatic variable might be changed by a call to longjmp. The compiler only sees the calls to setjmp. It can't know where longjmp will be called; in fact, a signal handler could call it at any point in the code. As a result, you may get a warning even when there's really no problem, because longjmp can't actually be called at the place that would cause one.
Some spurious warnings can be avoided if you declare all the functions you use that never return as noreturn.
This warning is enabled by -Wall or -Wextra. ๐
-Wunknown-pragmasโ ๐ฎ Warns when a#pragmadirective shows up that GCC doesn't understand. If this command-line option is used, warnings are even issued for unknown pragmas in system header files. That's not the case if the warnings are only enabled by the-Wallcommand-line option.-Wno-pragmasโ ๐ โโ๏ธ Don't warn about misuses of pragmas, like incorrect parameters, invalid syntax, or conflicts between pragmas. See also-Wunknown-pragmas.-Wno-prio-ctor-dtorโ Don't warn if a priority from 0 to 100 is used for a constructor or destructor. Constructor and destructor attributes let you assign a priority to control their order of execution beforemainis called or after it returns. The priority values must be greater than 100, because the compiler reserves priority values between0--100for the implementation. ๐-Wstrict-aliasingโ ๐ฆ This option is only active when-fstrict-aliasingis active. It warns about code that might break the strict aliasing rules the compiler uses for optimization. It doesn't catch every case, but it does try to catch the more common pitfalls. It's included in-Wall. It's equivalent to-Wstrict-aliasing=3.-Wstrict-aliasing=nโ Same deal: only active when-fstrict-aliasingis active, and it warns about code that might break those strict aliasing rules. Higher levels mean higher accuracy (fewer false positives), and they also take more effort, kind of like how-Oworks.-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3. Here are the levels:- Level 1 โ the most aggressive, quick, and least accurate option ๐โโ๏ธ. It's possibly useful when higher levels don't warn but
-fstrict-aliasingstill breaks the code, since it has very few false negatives. However, it has many false positives. It warns for all pointer conversions between possibly incompatible types, even if 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) โ ๐ 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. It does not warn about incomplete types.
- Level 1 โ the most aggressive, quick, and least accurate option ๐โโ๏ธ. It's possibly useful when higher levels don't warn but
-Wstrict-overflow,-Wstrict-overflow=nโ ๐ง This option is only active when signed overflow is undefined. It warns about cases where the compiler optimizes based on the assumption that signed overflow doesn't occur. It doesn't warn about every case where 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 happen is perfectly safe if the values involved are such that overflow never actually occurs. That means this warning can easily give a false positive, which is a warning about code that isn't actually a problem. To help you focus on the important stuff, several warning levels are defined. No warnings are issued for uses of undefined signed overflow when estimating how many iterations a loop requires, in particular when determining whether a loop will be executed at all. ๐
-Wstrict-overflow=1โ Warns about cases that are both questionable and easy to avoid. For example, the compiler simplifiesx + 1 > xto1. This level is enabled by-Wall; higher levels aren't, and must be explicitly requested. ๐ธ-Wstrict-overflow=2โ Also warns about other cases where a comparison is simplified to a constant. For example:abs (x) >= 0. This can only be simplified when signed integer overflow is undefined, becauseabs (INT_MIN)overflows toINT_MIN, which is less than zero.-Wstrict-overflow(with no level) is the same as-Wstrict-overflow=2. โจ-Wstrict-overflow=3โ Also warns about other cases where a comparison is simplified. For example:x + 1 > 1is simplified tox > 0. ๐ฆ-Wstrict-overflow=4โ Also warns about other simplifications not covered by the above cases. For example:(x * 10) / 5is simplified tox * 2. ๐ฅ-Wstrict-overflow=5โ Also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison. For example:x + 2 > yis simplified tox + 1 >= y. This is only reported at the highest warning level, because this simplification applies to many comparisons, so this level gives a very large number of false positives. ๐
โจ -Wstring-compare โจ
okay so bestie, this one watches strcmp and strncmp ๐ซถ It warns when a comparison result is basically decided before it even starts, because one argument is longer than the array the other one lives in (or the bound, for strncmp). Like, the answer is already locked in ๐ and those calls could be mistakes, so GCC flags them. no cap, it's a lifesaver ๐ธ
Here's the example: the strcmp call below gets flagged because its result is necessarily non-zero no matter what's inside the array a ๐ฅ
extern char a[4];
void f (char *d)
{
strcpy (d, "string");
...
if (0 == strcmp (a, d)) // cannot be true
puts ("a and d are the same");
}
-Wstring-compare comes on automatically with -Wextra โจ
๐ -Wno-stringop-overflow, -Wstringop-overflow, -Wstringop-overflow=type ๐
this one is all about catching string functions like memcpy and strcpy when they're about to overflow the destination buffer ๐ญ The optional number you pass is one bigger than the Object Size Checking type GCC uses to figure out how big the destination is. That number only matters for functions that work on character arrays. Raw memory functions like memcpy always use Object Size type-0, so no vibe shift there ๐ฆ
It also warns when a call asks for a size bigger than the largest possible object, or more than SIZE_MAX / 2 bytes. The best results happen with optimization turned on, but it can still catch a small set of simple overflows without optimization, in calls to GCC built-ins like __builtin_memcpy that match the standard functions ๐ง Either way, it only catches a subset of what the matching overflow checking built-ins can find, so don't get too comfy ๐
Check this one out: the strcpy below gets a warning because it copies at least 5 characters ("blue" plus the terminating NUL) into a buffer of size 4 ๐
enum Color { blue, purple, yellow };
const char* f (enum Color clr)
{
static char buf [4];
const char *str;
switch (clr)
{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
}
return strcpy (buf, str); // warning here
}
Option -Wstringop-overflow=2 is the default setting โจ
-Wstringop-overflow,-Wstringop-overflow=1โ this setting uses type-zero Object Size Checking to size destinations ๐ At this level it doesn't warn about writes past the end of subobjects inside larger objects accessed through pointers, unless the size of the largest surrounding object is known. If the destination could be one of several objects, GCC assumes it's the biggest one. On Linux, when optimization is on at this level, it warns for the same code that would be flagged when_FORTIFY_SOURCEis defined to a non-zero value ๐ซถ-Wstringop-overflow=2โ this one uses type-one Object Size Checking ๐ฅ It warns about overflows when writing to members of the largest complete objects whose exact size is known. It won't warn about excessive writes to the same members of unknown objects reached through pointers, since those might point to arrays with an unknown number of elements. This is the default setting, so you're already on it ๐-Wstringop-overflow=3โ type-two Object Size Checking, and it's the strictest setting that might warn about safe code ๐ญ It warns about overflowing the smallest object or data member.-Wstringop-overflow=4โ type-three Object Size Checking ๐ It warns about overflowing any data members. When the destination could be one of several objects, it uses the size of the largest one to decide whether to warn. Just like-Wstringop-overflow=3, this setting may produce warnings for benign code ๐
๐ธ -Wno-stringop-overread ๐ธ
this one warns about string functions like memchr or strcpy that get determined to read past the end of the source sequence ๐ it's on by default, so you get this protection for free โจ
Option -Wstringop-overread is enabled by default โจ
๐ฆ -Wno-stringop-truncation ๐ฆ
okay so this flag tells GCC to not warn about bounded string functions like strncat, strncpy, and stpncpy that might truncate the copied string or leave the destination unchanged ๐ Not warning is the whole point of -Wno-, so yeah, babe, it's a choice ๐
Here, the strncat call gets flagged because its bound is smaller than the length of the source string. That means the copy gets truncated ๐ To dodge the warning, use bufsize - strlen (buf) - 1) as the bound.
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Next up, the strncpy below only copies the characters before the terminating NUL, so the NUL never gets added to the end of d ๐ญ Assuming the result is always NUL-terminated is a super common mistake, so this one gets diagnosed. If you're not expecting a NUL-terminated result, call memcpy instead ๐ซถ
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
Last one! Here the bound for strncpy is the size of the destination buffer. If the source is equal to or longer than that size, the result won't be NUL-terminated, so it gets flagged too ๐ To avoid the warning, use 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);
...
}
Sometimes a character array is meant to hold bytes with no terminating NUL. In that case you can annotate the array with the attribute nonstring to skip this warning โจ Heads up though, those arrays aren't suitable for functions that expect NUL-terminated strings ๐ To help catch accidental misuse, GCC still warns about them unless it can prove the use is safe ๐ฅ
๐ง -Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc] ๐ง
this is GCC giving you friendly attribute suggestions ๐ It warns when 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โ this part warns about functions that might be candidates for the attributespure,const,noreturn, ormalloc๐ GCC only warns about functions visible in other compilation units, or (forpureandconst) if it can't prove the function returns normally. A function returns normally if it doesn't contain an infinite loop or return abnormally by throwing, callingabort, or trapping. This analysis needs the option-fipa-pure-const, which is enabled by default at-Oand higher. Higher optimization levels make the analysis more accurate ๐-Wsuggest-attribute=format,-Wmissing-format-attributeโ this warns about function pointers that might be candidates forformatattributes ๐ These are only possible candidates, not 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. So the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function, respectively, should also have aformatattribute to avoid the warning. GCC also warns about function definitions that might be candidates forformatattributes, again just as possible candidates ๐ฆ It guesses that aformatattribute might fit any function that calls something likevprintforvscanf, but that might not always be true, and some functions that really do wantformatattributes may not get detected ๐-Wsuggest-attribute=coldโ this warns about functions that might be candidates for thecoldattribute ๐ง It's based on static detection, and it usually only warns about functions that always lead to a call to anothercoldfunction, like wrappers of C++throwor fatal error reporting functions that lead toabort๐
๐ -Walloc-zero ๐
this one warns about calls to allocation functions decorated with the attribute alloc_size that ask for zero bytes ๐ญ That includes the built-in forms of aligned_alloc, alloca, calloc, malloc, and realloc.
Heads up, bestie: how these functions behave 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 ๐
this one warns about calls to functions decorated with alloc_size that try to allocate objects bigger than the number of bytes you specify ๐
It also catches cases where the size computation, done in an integer type with infinite precision, would go over the value of PTRDIFF_MAX on the target ๐ฅ -Walloc-size-larger-than=PTRDIFF_MAX is enabled by default โจ
To turn these warnings off, you can either specify a byte-size of SIZE_MAX or more, or use -Wno-alloc-size-larger-than ๐ซถ
-Wno-alloc-size-larger-thanโ okay bestie, this one switches off the-Walloc-size-larger-than=warnings ๐ Doing it is the same as-Walloc-size-larger-than=SIZE_MAXor anything bigger, so you're basically telling GCC to chill โจ-Wallocaโ warns on every single use ofallocain your source. Literally all of them ๐-Walloca-larger-than=byte-sizeโ the big one ๐ฅ It warns on calls toallocawhere the integer argument is zero, or where it isn't bounded by a controlling predicate that caps it at byte-size. It also yells when the bound is unknown. Heads up: arguments of non-integer types count as unbounded, even if they look like they're in range ๐
For example, a bounded case of alloca could be:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
In the above example, passing -Walloca-larger-than=1000 would not issue a warning because the call to alloca is known to be at most 1000 bytes. However, if -Walloca-larger-than=500 were passed, the compiler would emit a warning โจ
Unbounded uses, on the other hand, are uses of alloca with no controlling predicate constraining its integer argument. For example:
void func ()
{
void *p = alloca (n);
f (p);
}
If -Walloca-larger-than=500 were passed, the above would trigger a warning, but this time because of the lack of bounds checking ๐
Note, that even seemingly correct code involving signed integers could cause a warning:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
Watch out! In the above example,ncould be negative, causing a larger than expected argument to be implicitly cast into theallocacall ๐ญ
This option also warns when alloca is used in a loop ๐
-Walloca-larger-than=PTRDIFF_MAX is enabled by default but is usually only effective when -ftree-vrp is active (default for -O2 and above).
See also -Wvla-larger-than=byte-size.
-Wno-alloca-larger-thanโ disables the-Walloca-larger-than=warnings. It's the same as-Walloca-larger-than=SIZE_MAXor larger, so it's a full mute ๐-Warith-conversionโ main character energy ๐ This one makes sure GCC warns about implicit conversions coming from arithmetic operations, even when converting the operands to the same type can't actually change their values. It affects warnings from-Wconversion,-Wfloat-conversion, and-Wsign-conversion.
void f (char c, int i)
{
c = c + i; // warns with B<-Wconversion>
c = c + 1; // only warns with B<-Warith-conversion>
}
-Warray-bounds,-Warray-bounds=nโ only active when-ftree-vrpis active (default for-O2and above) ๐ง It warns about subscripts to arrays that are always out of bounds. This warning is enabled by-Wall.-Warray-bounds=1โ this is the warning level of-Warray-boundsand it's on with-Wall. The higher levels aren't, so you have to explicitly ask for them ๐โโ๏ธ-Warray-bounds=2โ also warns about out of bounds access for arrays at the end of a struct and for arrays accessed through pointers. It can give way more false positives, so it's deactivated by default ๐ฅด
-Warray-parameter,-Warray-parameter=nโ warns about redeclarations of functions where the array or pointer arguments are inconsistent in kind or form. It also turns on the detection of out-of-bounds accesses to those parameters through warnings like-Warray-bounds๐ฆ
If the first function declaration uses the array form, the bound in the array is assumed to be the minimum number of elements expected in calls to the function and the maximum number of elements it accesses. Not passing enough elements or touching more than the max can get flagged by warnings like -Warray-bounds. At level 1, the warning diagnoses inconsistencies involving array parameters declared with the T[static N] form.
For example, the warning triggers for the following redeclarations, because the first one allows an array of any size to be passed to f, while the second one, with the keyword static, says the array argument must have at least four elements:
void f (int[static 4]);
void f (int[]); // warning (inconsistent array form)
void g (void)
{
int *p = (int *)malloc (4);
f (p); // warning (array too small)
...
}
At level 2, the warning also triggers for redeclarations involving any other inconsistency in array or pointer argument forms that denote array sizes. Pointers and arrays of unspecified bound are considered equivalent and do not trigger a warning ๐ซถ
void g (int*);
void g (int[]); // no warning
void g (int[8]); // warning (inconsistent array bound)
-Warray-parameter=2 is included in -Wall. The -Wvla-parameter option triggers warnings for similar inconsistencies involving Variable Length Array arguments.
-Wattribute-alias=n,-Wno-attribute-aliasโ warns about declarations using thealiasand similar attributes whose target is incompatible with the type of the alias ๐ธ-Wattribute-alias=1โ the default level. It diagnoses incompatibilities between the type of the alias declaration and the type of its target. These are usually signs of bugs ๐-Wattribute-alias=2โ at this level,-Wattribute-aliasalso diagnoses cases where the alias declaration's attributes are more restrictive than the attributes on its target. Those mismatches can potentially lead to incorrect code generation. In other cases they may be harmless and could be fixed by simply adding the missing attribute to the target. For comparison, see the-Wmissing-attributesoption, which controls diagnostics when the alias declaration is less restrictive than the target, rather than more restrictive ๐
Attributes considered include alloc_align, alloc_size, cold, const, hot, leaf, malloc, nonnull, noreturn, nothrow, pure, returns_nonnull, and returns_twice.
-Wattribute-alias is equivalent to -Wattribute-alias=1. This is the default. You can disable these warnings with either -Wno-attribute-alias or -Wattribute-alias=0 ๐
โโ๏ธ
-Wbool-compareโ warns about a boolean expression being compared with an integer value that's different fromtrue/false. For instance, this comparison is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
This warning is enabled by -Wall ๐
-Wbool-operationโ warns about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program ๐คจ For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++17, and deprecated otherwise.)
This warning is enabled by -Wall.
-Wduplicated-branchesโ warns when an if-else has identical branches. This catches cases like:
if (p != NULL)
return 0;
else
return 0;
It doesn't warn when both branches contain just a null statement. This warning also warns for conditional operators:
int i = x ? *p : *p;
-Wduplicated-condโ warns about duplicated conditions in an if-else-if chain. For instance, it'll warn for this code:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ warns when__builtin_frame_addressor__builtin_return_addressis called with an argument greater than 0. Such calls may return indeterminate values or crash the program ๐ This warning is included in-Wall.-Wno-discarded-qualifiers(C and Objective-C only) โ stops the warning about type qualifiers on pointers being discarded. Usually GCC complains if aconst char *variable gets passed to a function that takes achar *parameter. Use this option to mute that ๐คซ-Wno-discarded-array-qualifiers(C and Objective-C only) โ same vibe, but for arrays that are pointer targets. Usually GCC complains if aconst int (*)[]variable is passed to a function that takes anint (*)[]parameter. This option lets you suppress that warning ๐-Wno-incompatible-pointer-types(C and Objective-C only) โ no warning when there's a conversion between pointers with incompatible types. This is for cases not covered by-Wno-pointer-sign, which warns about pointer argument passing or assignment with different signedness ๐ง-Wno-int-conversion(C and Objective-C only) โ stops the warnings about incompatible integer-to-pointer and pointer-to-integer conversions. This warning is about implicit conversions. For explicit conversions, you can use-Wno-int-to-pointer-castand-Wno-pointer-to-int-castinstead ๐-Wzero-length-boundsโ warns about accesses to elements of zero-length array members that might overlap other members of the same object ๐ Declaring interior zero-length arrays is discouraged, because accesses to them are undefined. See
Undefined behaviour alert! ๐จ Interior zero-length arrays are undefined territory, so don't go poking around in them.
For example, the first two stores in function bad are diagnosed because the array elements overlap the subsequent members b and c. The third store is diagnosed by -Warray-bounds because it is beyond the bounds of the enclosing object.
struct X { int a[0]; int b, c; };
struct X x;
Okay so this is the rest of the -Wzero-length-bounds vibe check ๐
void bad (void)
{
x.a[0] = 0; // -Wzero-length-bounds
x.a[1] = 1; // -Wzero-length-bounds
x.a[2] = 2; // -Warray-bounds
}
Option -Wzero-length-bounds is enabled by -Warray-bounds ๐
โจ
-Wno-div-by-zeroโ Bestie, this one tells GCC to chill ๐ โโ๏ธ and stop warning about compile-time integer division by zero. Floating-point division by zero doesn't get flagged either, because it can be a legit way to get infinities and NaNs ๐-Wsystem-headersโ This one prints warnings for constructs in system header files ๐งน. Normally those get muted, because they usually aren't real problems and would just make your compiler output harder to read. Turning this on makes GCC treat system header warnings like they came from your own code ๐. Heads up though: using-Wallwith this doesn't warn about unknown pragmas in system headers. For that, you also need-Wunknown-pragmas๐-Wtautological-compareโ Warns if a self-comparison is always true or always false. It catches mistakes like this one ๐:
int i = 1;
...
if (i > i) { ... }
Bitwise comparisons that always come out true or false get flagged too. Check this one out:
if ((a & 16) == 10) { ... }
That if will always be false, so it's giving nothing ๐ญ This warning is enabled by -Wall ๐
-Wtrampolinesโ Warns about trampolines generated for pointers to nested functions ๐ง. A trampoline is a small piece of data or code that gets created at run time on the stack when the address of a nested function is taken. It's used to call that nested function indirectly. On some targets it's just data and needs no special treatment. On most targets, though, it's made of code, so the stack has to be made executable for the program to work properly ๐ฌ-Wfloat-equalโ Warns when floating-point values are used in equality comparisons ๐ซ . The thinking is that sometimes it's convenient to treat floats as approximations of infinitely precise real numbers. If you're doing that, you need to figure out the maximum or likely maximum error the computation introduces (by analyzing the code, or some other way) and allow for it in comparisons. Output is a different problem, too ๐. Instead of testing for equality, 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. It's a whole vibe, so here's what it catches:- Macro parameters that show up inside string literals in the macro body. Traditional C does macro replacement inside string literals, but ISO C doesn't ๐ โโ๏ธ
- In traditional C, some preprocessor directives didn't exist. Traditional preprocessors only treated a line as a directive if the
#was in column 1. So-Wtraditionalwarns about directives that traditional C understands but ignores, because the#isn't the first character on the line. It also suggests hiding directives like#pragma(which traditional C doesn't understand) by indenting them. Some traditional implementations don't recognize#elif, so this option suggests avoiding it altogether ๐ธ - A function-like macro that appears without arguments
- The unary plus operator
- The
Uinteger constant suffix, or theForLfloating-point constant suffixes. (Traditional C does support theLsuffix on integer constants.) These suffixes show up in macros defined in the system headers of most modern systems, like the_MIN/_MAXmacros in<limits.h>. Using those macros in user code might normally lead to spurious warnings, but GCC's integrated preprocessor has enough context to avoid warning in these cases โจ - A function declared external in one block and then used after the end of that block
- A
switchstatement with an operand of typelong - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this ๐ - The ISO type of an integer constant has a different width or signedness from its traditional type. This warning is only issued if the base of the constant is ten. Hexadecimal or octal values, which usually represent bit patterns, aren't warned about ๐ข
- ISO string concatenation usage gets detected ๐งต
- Initialization of automatic aggregates
- Identifier conflicts with labels. Traditional C doesn't have a separate namespace for labels ๐ท๏ธ
- Initialization of unions. If the initializer is zero, the warning gets skipped. This is done on the assumption that a zero initializer in user code is conditioned on something like
__STDC__to avoid missing-initializer warnings, and it relies on default initialization to zero in the traditional C case ๐ซถ - Conversions by prototypes between fixed-point and floating-point values, and vice versa. Leaving these prototypes out when compiling with traditional C causes serious problems ๐. This is only a subset of the possible conversion warnings. For the full set, use
-Wtraditional-conversion - Use of ISO C style function definitions. This warning intentionally isn't issued for prototype declarations or variadic functions, because those ISO C features show up in your code when you use libiberty's traditional C compatibility macros,
PARAMSandVPARAMS. It's also skipped for nested functions, since that's already a GCC extension and 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 ๐. That includes conversions of fixed-point to floating-point and vice versa, and conversions that change the width or signedness of a fixed-point argument, except when that matches the default promotion.-Wdeclaration-after-statement(C and Objective-C only) โ Warns when a declaration shows up after a statement in a block ๐. This construct comes from C++, was introduced with ISO C99, and is allowed by default in GCC. It isn't supported by ISO C90.-Wshadowโ Warns whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C). It also warns whenever a built-in function gets shadowed ๐ญ. In C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows astruct/class/enum. When this warning is enabled, it also includes all instances of local shadowing. That means-Wno-shadow=localand-Wno-shadow=compatible-localare ignored when-Wshadowis used. Same as-Wshadow=global๐-Wno-shadow-ivar(Objective-C only) โ Don't warn when a local variable shadows an instance variable in an Objective-C method ๐ โโ๏ธ-Wshadow=globalโ Warns for any shadowing. Same as-Wshadow๐-Wshadow=localโ Warns when a local variable shadows another local variable or parameter ๐-Wshadow=compatible-localโ Warns when a local variable shadows another local variable or parameter whose type is compatible with the type of the shadowing variable. In C++, type compatibility here means the shadowing variable's type can be converted to the shadowed variable's type ๐ง . This flag exists (on top of-Wshadow=local) because when a local variable shadows another one of incompatible type, it's most likely on purpose, not a bug or typo. Here's an example:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two i variables in the example above have incompatible types, enabling only -Wshadow=compatible-local doesn't 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 reduce the number of warnings triggered by intentional shadowing. Note that this also means shadowing const char *i with char *i doesn't emit a warning ๐คซ
This warning is also enabled by -Wshadow=local โจ
-Wlarger-than=byte-sizeโ Warns whenever an object is defined whose size exceedsbyte-size๐ฆ.-Wlarger-than=PTRDIFF_MAXis enabled by default. Warnings controlled by this option can be disabled either by specifying abyte-sizeofSIZE_MAXor more, or by-Wno-larger-than. It also warns for calls to bounded functions such asmemchrorstrnlenthat specify a bound greater than the largest possible object, which isPTRDIFF_MAXbytes by default ๐งฎ. These 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โ okay so this one is bestie's personal bodyguard ๐ It warns you if a function's stack frame gets bigger than byte-size โจ BUT the math used to guess the frame size is rough and not conservative, so the real needs might be a little bigger than byte-size even when you get zero warnings ๐ Also, any space grabbed byalloca, variable-length arrays, or related constructs is NOT counted when the compiler decides whether to warn ๐-Wframe-larger-than=PTRDIFF_MAXis on by default ๐ธ To shut these warnings up, give it a byte-size ofSIZE_MAXor more, or just use-Wno-frame-larger-than.-Wno-frame-larger-thanโ the lazy-girl-but-make-it-iconic option ๐ It turns off the-Wframe-larger-than=warnings, and it's the same thing as-Wframe-larger-than=SIZE_MAXor bigger.-Wno-free-nonheap-objectโ okay this one is giving "why is free() yelling at me" ๐ญ It warns when you try to deallocate an object that either wasn't allocated on the heap, or was reached through a pointer that didn't come back from a previous call to the matching allocation function. Like,stpcpyhands you back a pointer to the terminating nul character instead of the start of your object, so callingfreeon it gets flagged ๐ Check it out:
void f (char *p)
{
p = stpcpy (p, "abc");
// ...
free (p); // warning
}
-Wfree-nonheap-object is enabled by default ๐ฆ
-Wstack-usage=byte-sizeโ the stack-usage detective ๐ต๏ธโโ๏ธโจ It warns if a function's stack usage might go over byte-size. This one is conservative, so it's way more careful than the frame one. Any space fromalloca, variable-length arrays, or related constructs DOES get counted when it decides whether to warn ๐
The message is totally in line with what -fstack-usage spits out ๐ Here's how the vibes change:
- If the stack usage is fully static but goes over the amount you set, it's:
warning: stack usage is 1120 bytes
- If the stack usage is (partly) dynamic but bounded, it's:
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
-Wstack-usage=PTRDIFF_MAX is enabled by default ๐ฅ You can disable these warnings by giving a byte-size of SIZE_MAX or more, or by using -Wno-stack-usage.
-Wno-stack-usageโ the off switch for-Wstack-usage=warnings ๐ซถ It's the same as-Wstack-usage=SIZE_MAXor larger.-Wunsafe-loop-optimizationsโ this one watches your loops ๐ง It warns if a loop can't be optimized because the compiler can't assume anything about the bounds of the loop indices. And with-funsafe-loop-optimizationsturned on, it warns when the compiler makes those assumptions anyway ๐-Wno-pedantic-ms-format(MinGW targets only) โ for my Windows bestie ๐ When you use it together with-Wformatand-pedantic(without GNU extensions), this kills the warnings about the non-ISOprintf/scanfformat width specifiersI32,I64, andIthat get used on Windows targets. Those depend on the MS runtime, so they're not really a crime ๐ธ-Wpointer-arithโ warns about anything that depends on the "size of" a function type or ofvoid๐ GNU C gives these types a size of 1, which is super handy for math withvoid *pointers and pointers to functions. In C++, it also warns when an arithmetic operation involvesNULL๐ This warning is also enabled by-Wpedantic.-Wno-pointer-compareโ don't warn if a pointer gets compared with a zero character constant โจ That usually means the pointer was supposed to be dereferenced, so the comparison is kinda sus. For example:
const char *p = foo ();
if (p == '\0')
return 42;
Heads up bestie: the code above is invalid in C++11 ๐
This warning is enabled by default ๐
-Wtsanโ the ThreadSanitizer check-in ๐งต It warns about features ThreadSanitizer doesn't support. Like, it doesn't supportstd::atomic_thread_fence, and it can report false positives, so it's giving "I can't be trusted here" ๐ญ This warning is enabled by default โจ-Wtype-limitsโ the "wait, that's literally impossible" warning ๐ฆ It 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 warns if an unsigned variable gets compared against zero with<or>=๐ This warning is also enabled by-Wextra.-Wabsolute-value(C and Objective-C only) โ the "you picked the wrong math function, sis" warning ๐ It warns on calls to standard functions that compute the absolute value of an argument when there's a better standard function for the job. For example, callingabs(3.14)gets flagged, becausefabsis the right one for a double argument ๐ It also fires when the argument in a call like that has an unsigned type. You can suppress it with an explicit type cast, and it's also enabled by-Wextra๐ซถ-Wcomment,-Wcommentsโ warns whenever a comment-start sequence/*shows up inside a/*comment, or whenever a backslash-newline shows up in a//comment ๐ This warning is enabled by-Wall.-Wtrigraphsโ warns if any trigraphs get encountered that might change what the program means ๐ Trigraphs inside comments don't get warned about, except the ones that would form escaped newlines. This option is implied by-Wall. If you don't give-Wall, it's still enabled unless trigraphs are enabled. Want trigraph conversion without the warnings but still get the other-Wallwarnings? Use-trigraphs -Wall -Wno-trigraphs๐-Wundefโ warns if an undefined identifier gets evaluated in an#ifdirective ๐ง Those identifiers get replaced with zero, so keep an eye out โจ-Wexpansion-to-definedโ warns wheneverdefinedshows up in the expansion of a macro, including when the macro is expanded by an#ifdirective ๐ That usage isn't portable, so it's a major no-no. This warning is also enabled by-Wpedanticand-Wextra.-Wunused-macrosโ warns about macros that are defined in the main file but never used ๐ฆ A macro counts as used if it's expanded or tested for existence at least once. The preprocessor also warns if the macro hasn't been used by the time it gets redefined or undefined ๐ Built-in macros, macros defined on the command line, and macros defined in include files don't get warned about.
Note: if a macro is actually used, but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐ To dodge the warning, you could improve the scope of the macro's definition, like moving it into the first skipped block. Or you could give it a dummy use with something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ no warning when an#elseor an#endifhas text after it ๐ธ This happens sometimes in older programs with code like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO should be in comments, bestie ๐ซถ This warning is on by default.
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a non-matching type ๐ For example, it 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 aren't in ISO C90 but do show up in ISO C99 โจ Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. This option doesn't care about the standards mode. Warnings get turned off in the expression that follows__extension__.-Wc99-c11-compat(C and Objective-C only) โ warns about features that aren't in ISO C99 but are in ISO C11 ๐ฆ Like anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. Again, it doesn't care about the standards mode, and warnings are turned off in the expression that follows__extension__.-Wc11-c2x-compat(C and Objective-C only) โ warns about features that aren't in ISO C11 but are in ISO C2X ๐ For instance, omitting the string in_Static_assert, using[[]]syntax for attributes, using decimal floating-point types, and so on. It's independent of the standards mode, and warnings are disabled in the expression that follows__extension__.-Wc++-compat(C and Objective-C only) โ warns about ISO C constructs that live outside the common subset of ISO C and ISO C++ ๐ For example, requesting an implicit conversion fromvoid *to a pointer to a non-voidtype.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning is different between ISO C++ 1998 and ISO C++ 2011 ๐ง For example, identifiers in ISO C++ 1998 that are keywords in ISO C++ 2011. This warning turns on-Wnarrowingand is enabled by-Wall.-Wc++14-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning is different 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 is different 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 is different between ISO C++ 2017 and ISO C++ 2020 ๐ This warning is enabled by-Wall.-Wcast-qualโ warns whenever a pointer gets cast so it 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. Castingchar **toconst char **is unsafe, as in this example:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ warns whenever a pointer gets cast so the required alignment of the target goes up ๐ธ For example, it warns if achar *gets cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries.-Wcast-align=strictโ ๐ Okay so this one warns whenever a pointer cast makes the target's required alignment stricter, no matter what machine you're on. Like casting achar *to anint *is giving trouble, bestie ๐ญโจ.-Wcast-function-typeโ ๐ฆ This one side-eyes you when a function pointer gets cast to an incompatible function pointer type. Here's the tea ๐ต:- When the function type has a variable argument list, only the types of the initial arguments you actually pass get checked ๐ .
- Any pointer-type parameter matches any other pointer-type ๐.
- Benign integral differences get ignored, like
intvs.longon ILP32 targets ๐ธ. - Type qualifiers get ignored too, no judgment ๐ซถ.
- The function type
void (*) (void)is super special because it matches everything, so you can use it to shut this warning up ๐คซ๐. - For casts involving pointer to member types, it warns whenever the cast changes the pointer to member type ๐ฅ.
- This warning is enabled by
-Wextraโญ.
-Wwrite-stringsโ ๐ When you're compiling C, string constants get the typeconst char[length], so copying one's address into a non-constchar *pointer gets flagged. This is super useful for catching code at compile time that might try to write into a string constant ๐, but only if you've been really careful withconstin your declarations and prototypes. Otherwise it's just a nuisance ๐, which is exactly why-Walldoesn't ask for these warnings ๐ซ. When you're compiling C++, it warns about the deprecated conversion from string literals tochar *๐. This warning is enabled by default for C++ programs ๐ง.-Wclobberedโ ๐ Warns for variables that might get changed bylongjmporvfork. Also enabled by-Wextra๐.-Wconversionโ ๐ Warns for implicit conversions that might alter a value. That includes:- conversions between real and integer, like
abs (x)whenxis adouble๐ข, - conversions between signed and unsigned, like
unsigned ui = -1๐, - and conversions to smaller types, like
sqrtf (M_PI)๐. It does not warn for explicit casts likeabs ((int) x)andui = (unsigned) -1, or when the value doesn't actually change, likeabs (2.0)โจ. Warnings about signed/unsigned conversions can be turned off with-Wno-sign-conversion๐ซถ. For C++, it also warns about confusing overload resolution for user-defined conversions ๐, and about conversions that never use a type conversion operator: conversions tovoid, to the same type, to a base class, or to a reference to them ๐ง. Signed/unsigned conversion warnings are disabled by default in C++ unless you explicitly turn on-Wsign-conversion๐ . Warnings about conversion from arithmetic on a small type back to that same type only show up with-Warith-conversion๐ฆ.
- conversions between real and integer, like
-Wdangling-elseโ ๐ญ Warns about constructions where it's unclear whichifanelsebranch belongs to. Here's an example of the drama:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C/C++, every else branch belongs to the innermost possible if statement, which in this example is if (b). That's often not what the programmer expected, as the indentation in the example above shows ๐. When there's potential for this confusion, GCC issues a warning if you specify this flag ๐จ. To get rid of the warning, add explicit braces around the innermost if statement so there's no way the else can belong to the enclosing if ๐ซถ. The resulting code looks like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses ๐.
-Wdate-timeโ โฐ Warns when the macros__TIME__,__DATE__, or__TIMESTAMP__show up, since they might prevent bit-wise-identical reproducible compilations ๐.-Wempty-bodyโ ๐ซฅ Warns if an empty body shows up in anif,else, ordo whilestatement. Also enabled by-Wextra๐ธ.-Wno-endif-labelsโ ๐ โโ๏ธ Tells GCC to chill and not warn about stray tokens after#elseand#endif๐.-Wenum-compareโ ๐งฉ Warns about a comparison between values of different enumerated types. In C++, enumerated type mismatches in conditional expressions get diagnosed too, and this warning is enabled by default there ๐ . In C, it's enabled by-Wallโจ.-Wenum-conversionโ ๐ Warns when a value of one enumerated type gets implicitly converted to a different enumerated type. This warning is enabled by-Wextrain C ๐.-Wjump-misses-init(C, Objective-C only) โ ๐ฆ Warns if agotoorswitchstatement jumps forward across the initialization of a variable, or jumps backward to a label after the variable has already been initialized. It only cares about variables that are initialized when they're declared ๐ฏ. This warning is only supported for C and Objective-C. In C++, this sort of branch is an error anyway ๐ โโ๏ธ.-Wjump-misses-initis included in-Wc++-compat๐. You can turn it off with the-Wno-jump-misses-initoption ๐ซถ.-Wsign-compareโ โ๏ธ Warns when a comparison between signed and unsigned values could give an incorrect result because the signed value gets converted to unsigned. In C++, this warning is also enabled by-Wall๐. In C, it's also enabled by-Wextra๐ธ.-Wsign-conversionโ ๐ซ Warns for implicit conversions that may change the sign of an integer value, like assigning a signed integer expression to an unsigned integer variable ๐. An explicit cast silences the warning ๐คซ. In C, this option is also enabled by-Wconversion๐ฅ.-Wfloat-conversionโ ๐ Warns for implicit conversions that reduce the precision of a real value. That includes conversions from real to integer, and from higher precision real to lower precision real values ๐. This option is also enabled by-Wconversionโจ.-Wno-scalar-storage-orderโ ๐ Tells GCC not to warn on suspicious constructs involving reverse scalar storage order ๐ .-Wsizeof-array-divโ ๐งฎ Warns about divisions of twosizeofoperators when the first one is applied to an array and the divisor doesn't equal the size of the array element. In that case, the computation won't give you the number of elements in the array, which is probably not what you meant ๐ฌ. This warning goes off for stuff like this:
int fn ()
{
int arr[10];
return sizeof (arr) / sizeof (short);
}
This warning is enabled by -Wall ๐.
-Wsizeof-pointer-divโ ๐ฉ Warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size. That's the usual way to compute an array size, but it won't work out correctly with pointers ๐. For example, it warns aboutsizeof (ptr) / sizeof (ptr[0])ifptris not an array but a pointer ๐ง. 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. For example, it triggers onmemset (ptr, 0, sizeof (ptr));ifptris a pointer rather than an array, and suggests a possible fix ๐ง. It also triggers on things likememcpy (&foo, ptr, sizeof (&foo));๐ต. On top of that, it warns about calls to bounded string copy functions likestrncatorstrncpythat use asizeofexpression of the source array as the bound. In the example below, the call tostrncatuses the size of the source string as its bound. That's almost certainly a mistake, so the call gets diagnosed ๐จ.
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall ๐.
-Wno-sizeof-array-argumentโ ๐ Tells GCC not to warn when thesizeofoperator is applied to a parameter that's declared as an array in a function definition. This warning is enabled by default for C and C++ programs ๐ธ.-Wmemset-elt-sizeโ ๐ช Warns about suspicious calls to thememsetbuilt-in function. It goes off 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 means you probably forgot to multiply by the element size ๐. This warning is enabled by-Wall๐ .-Wmemset-transposed-argsโ ๐ Warns about suspiciousmemsetcalls where the second argument isn't zero and the third argument is zero ๐ณ. For example,memset (buf, sizeof buf, 0)gets diagnosed, becausememset (buf, 0, sizeof buf)was what was meant ๐ก. The diagnostic is only emitted if the third argument is a literal zero ๐ข. If it's an expression that folds to zero, or a cast of zero to some type, the arguments are far less likely to have been mixed up by mistake, so no warning is emitted ๐ซถ. This warning is enabled by-Wallโจ.-Waddressโ ๐ Warns about suspicious uses of memory addresses. These include using the address of a function in a conditional expression, likevoid func(void); if (func), and comparisons against the memory address of a string literal, likeif (x == "abc")๐ง. These uses usually point to a programmer error. The address of a function always evaluates to true, so using it in a conditional usually means you forgot the parentheses in a function call ๐คฆโโ๏ธ. Comparisons against string literals give unspecified behavior and aren't portable in C, so they usually mean you meant to usestrcmp๐ . This warning is enabled by-Wall๐.-Wno-address-of-packed-memberโ ๐ฆ Tells GCC not to warn when the address of a packed member of a struct or union is taken, which usually results in an unaligned pointer value ๐. This is enabled by default ๐.-Wlogical-opโ ๐ง Warns about suspicious uses of logical operators in expressions. That includes using logical operators in contexts where a bit-wise operator is likely expected ๐. It also warns when the operands of a logical operator are the same:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ okay so this one warns when you use logical not on the left side of a comparison ๐. It stays quiet if the right operand is a boolean expression. The whole point is catching sus code like this:
int a;
...
if (!a > 1) { ... }
You can keep the warning from firing by wrapping the left side in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall. โจ
-Waggregate-returnโ warns if any functions that return structures or unions are defined or called. (In languages where you can return an array, this also triggers a warning ๐ )-Wno-aggressive-loop-optimizationsโ warns if, inside a loop with a constant number of iterations, the compiler spots undefined behavior in some statement during one or more of those iterations ๐ฅ-Wno-attributesโ no warning if an unexpected__attribute__shows up, like unrecognized attributes, function attributes slapped onto variables, etc. ๐ This does not stop errors for incorrect use of supported attributes, so don't get it twisted.-Wno-builtin-declaration-mismatchโ this one catches built-in functions declared with an incompatible signature, or declared as a non-function. It also warns when a built-in function declared without a prototype gets called with arguments whose promoted types don't match what the function expects. With-Wextra, it also warns when a built-in function that takes arguments is declared without a prototype. The-Wbuiltin-declaration-mismatchwarning is enabled by default. To dodge it, include the right header so the built-in prototypes are in scope ๐
Take memset below. The call gets flagged because the function expects a value of type size_t as its argument, but the type of 32 is int. With -Wextra, the declaration gets flagged too:
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ no warning if certain built-in macros get redefined. This silences the warnings for redefining__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__๐ฆ-Wstrict-prototypes(C and Objective-C only) โ warns if a function is declared or defined without specifying its argument types. (An old-style function definition gets a pass with no 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. It warns even if there's a previous prototype. A definition using()is not considered old-style in C2X mode, since it's equivalent to(void)there, but it is considered old-style for older standards ๐-Wmissing-parameter-type(C and Objective-C only) โ warns when a function parameter is declared without a type specifier in K&R-style functions:
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 fires even if the definition itself provides a prototype. Use this to catch global functions that don't have a matching prototype declaration in a header file. This option is not valid for C++, because all function declarations provide prototypes there, and a non-matching declaration declares an overload rather than conflicting with an earlier one. For missing declarations in C++, use-Wmissing-declarationsinstead ๐-Wmissing-declarationsโ warns if a global function is defined without a previous declaration, even if the definition itself provides a prototype. Use this to catch global functions that aren't declared in header files. In C, no warnings are issued for functions with previous non-prototype declarations, so use-Wmissing-prototypesfor those. In C++, no warnings are issued for function templates, inline functions, or functions in anonymous namespaces ๐-Wmissing-field-initializersโ warns if a structure's initializer is missing some fields. In this example,x.his implicitly zero, so it triggers a warning:
struct s { int f, g, h; };
struct s x = { 3, 4 };
This option does not warn about designated initializers, so this version is fine:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, this option also doesn't warn about the universal zero initializer { 0 }:
struct s { int f, g, h; };
struct s x = { 0 };
Likewise, in C++ it 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-multicharโ no warning if a multicharacter constant ('FOOF') is used. These usually point to a typo in your code, since they have implementation-defined values and shouldn't be used in portable code ๐ โโ๏ธ-Wnormalized=[none|id|nfc|nfkc]โ okay this one is lowkey deep ๐ง In ISO C and ISO C++, two identifiers are different if they're different sequences of characters. But when you use characters outside basic ASCII, you can end up with two different character sequences that look exactly the same. To stop that confusion, the ISO 10646 standard sets normalization rules that turn look-alike sequences into the same sequence. GCC can warn you if your identifiers haven't been normalized, and this option controls that warning.
There are four levels:
- The default is
-Wnormalized=nfc, which warns about any identifier that isn't in the ISO 10646 "C" normalized form, NFC. NFC is the recommended form for most uses. It's equivalent to-Wnormalized. - Some characters allowed in identifiers by ISO C and ISO C++ stop being allowed once they're turned into NFC. So there's no way to use these symbols in portable ISO C or C++ and keep all your identifiers in NFC.
-Wnormalized=idsuppresses the warning for these characters. Future versions of the standards may fix this, which is why this isn't the default. - You can switch the warning off for all characters with
-Wnormalized=noneor-Wno-normalized. Only do this if you're using some other normalization scheme (like "D"), because otherwise you can easily create bugs that are literally impossible to see ๐ญ -Wnormalized=nfkcgoes further. Some characters in ISO 10646 have distinct meanings but look identical in some fonts or display methods, especially once formatting is applied. For instance,"\u207F"(SUPERSCRIPT LATIN SMALL LETTER N) displays just like a regular "n" placed in a superscript. ISO 10646 defines the NFKC normalization scheme to convert all of these into a standard form too, and GCC warns if your code isn't in NFKC when you use-Wnormalized=nfkc. This warning is comparable to warning about every identifier that contains the letter O because it might be confused with the digit 0. So it isn't the default, but it can be a useful local coding convention if your programming environment can't be fixed to display these characters distinctly ๐
-Wno-attribute-warningโ no warning about using functions declared with thewarningattribute. By default this warning is enabled. Use-Wno-attribute-warningto disable the warning, or-Wno-error=attribute-warningto disable the error when compiling with the-Werrorflag ๐ซถ-Wno-deprecatedโ no warning about using deprecated features ๐ฅ-Wno-deprecated-declarationsโ no warning about uses of functions, variables, and types marked as deprecated with thedeprecatedattribute ๐-Wno-overflowโ no warning about compile-time overflow in constant expressions โจ-Wno-odrโ warns about One Definition Rule violations during link-time optimization. Enabled by default. Yes, the name says-Wno-, but it's the warning itself ๐ญ iykyk-Wopenmp-simdโ warns if the vectorizer cost model overrides the OpenMP simd directive set by the user. The-fsimd-cost-model=unlimitedoption can be used to relax the cost model ๐ธ-Woverride-init(C and Objective-C only) โ warns if an initialized field without side effects gets overridden when using designated initializers.
This warning is included in -Wextra. To get the other -Wextra warnings without this one, use -Wextra -Wno-override-init ๐ง
-Wno-override-init-side-effects(C and Objective-C only) โ no warning if an initialized field with side effects gets overridden when using designated initializers. This warning is enabled by default ๐-Wpackedโ warns if a structure is given thepackedattribute, but that attribute has no effect on the layout or size of the structure. These structures may end up misaligned for little benefit. For instance, in this code, the variablef.xinstruct baris misaligned, even thoughstruct bardoesn't itself have thepackedattribute ๐
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wnopacked-bitfield-compatโ okay so the 4.1, 4.2, and 4.3 series of GCC just ignored thepackedattribute oncharbit-fields ๐. That got fixed in GCC 4.4, but the fix can shift your struct layout around, so GCC will tell you when the offset of one of these fields changes ๐ซถ. Like in this struct, the 4-bit padding betweenaandbis just gone now โจ:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This one is on by default ๐ธ. If you want it quiet, use -Wno-packed-bitfield-compat to shush it ๐คซ.
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ this one warns you if a struct field has an explicitly set alignment inside a packed struct or union, and that field ends up misaligned ๐. Like, you'll getwarning: alignment 1 of 'struct S' is less than 8for this code ๐:
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
It's enabled by -Wall ๐
.
-Wpaddedโ warns when padding gets slipped into a struct, whether that's to line up one element or to line up the whole struct ๐ง. Sometimes you can shuffle the fields around to cut down on the padding and make the struct smaller, which is literally the dream ๐.-Wredundant-declsโ warns if something gets declared more than once in the same scope. This happens even when multiple declarations are allowed and don't change anything, so it's giving "why are you doing this" energy ๐๐.-Wrestrictโ warns when an object that arestrict-qualified parameter points to (or a__restrict-qualified one in C++) gets aliased by another argument, or when copies between those objects overlap ๐จ. Check out thisstrcpycall, which tries to chop the string by overwriting its start with its last four characters. Because it 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 can catch some simple overlap even without optimization, but it works best at -O2 and above โญ. It's included in -Wall โจ.
-Wnested-externs(C and Objective-C only) โ warns if anexterndeclaration shows up inside a function ๐ โโ๏ธ.-Winlineโ warns if a function declared asinlinecan't actually be inlined ๐ฆ. Even with this on, the compiler won't warn about failed inlining for functions in system headers ๐ค. GCC uses a bunch of heuristics to decide whether to inline something, like how big the function is and how much inlining has already happened in the current function ๐ง . So tiny changes in your source can make-Winlinewarnings show up or disappear, which is chaotic but iykyk ๐.-Wint-in-bool-contextโ warns about sketchy uses of integer values where booleans are expected ๐. Examples are conditional expressions (?:) with 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++);. It also covers all kinds of multiplications, no matter the data type ๐. This warning is enabled by-Wall๐.-Wno-int-to-pointer-castโ suppresses warnings for casts to a pointer type from an integer of a different size ๐. In C++, casting to a pointer type of smaller size is an error, so this one is not a vibe ๐ซ. TheWint-to-pointer-castwarning is enabled by default ๐.-Wno-pointer-to-int-cast(C and Objective-C only) โ suppresses warnings for casts from a pointer to an integer type of a different size ๐.-Winvalid-pchโ warns if a precompiled header shows up in the search path but can't be used ๐.-Wlong-longโ warns if thelong longtype gets used ๐ฃ. This is enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. To make the warning messages go away, use-Wno-long-long๐ซง.-Wvariadic-macrosโ warns if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode ๐ธ. This is enabled by either-Wpedanticor-Wtraditional. To silence it, use-Wno-variadic-macros๐คซ.-Wno-varargsโ tells GCC to stop warning about questionable usage of the macros that handle variable arguments, likeva_start๐ง. These warnings are enabled by default, so this is the opt-out ๐ฆ.-Wvector-operation-performanceโ warns if a vector operation isn't implemented using the SIMD capabilities of the architecture ๐ฅ. It's mainly useful for performance tuning ๐. A vector operation can be done three ways: "piecewise", meaning the scalar operation runs on every vector element; "in parallel", meaning it's implemented with scalars of a wider type, which is usually more performance efficient; and "as a single scalar", meaning the vector fits into a scalar type ๐ .-Wvlaโ warns if a variable-length array shows up in the code ๐.-Wno-vlastops the-Wpedanticwarning about variable-length arrays ๐ โโ๏ธ.-Wvla-larger-than=byte-sizeโ if you use this, GCC warns about variable-length array declarations whose size is either unbounded, or bounded by an argument that lets the array exceedbyte-sizebytes ๐. It works like-Walloca-larger-than=byte-size, just for variable-length arrays ๐. Heads up though, GCC may optimize small variable-length arrays of a known value into plain arrays, so this warning might not trigger for those ๐.-Wvla-larger-than=PTRDIFF_MAXis enabled by default but usually only does anything when-ftree-vrpis active, which is the default for-O2and above ๐. See also-Walloca-larger-than=byte-size๐.-Wno-vla-larger-thanโ disables the-Wvla-larger-than=warnings ๐ . It's the same as-Wvla-larger-than=SIZE_MAXor larger ๐.-Wvla-parameterโ warns about redeclarations of functions that have arguments of Variable Length Array types with inconsistent kinds or forms ๐. It also turns on detection of out-of-bounds accesses to those parameters through warnings like-Warray-bounds๐. If the first function declaration uses the VLA form, the bound in the array is assumed to be the minimum number of elements expected in calls to the function, and also the maximum number of elements it accesses ๐ง . If you don't pass enough elements, or it accesses more than that maximum, you may get a diagnostic ๐.
In this example, the warning triggers on those redeclarations because the first one lets any size of array get passed to f, while the second one says the array argument must have at least n elements. Calling f with the associated VLA bound parameter larger than the actual VLA bound also triggers a warning ๐ญ:
void f (int n, int[n]);
void f (int, int[]); // warning: argument 2 previously declared as a VLA
void g (int n)
{
if (n > 4)
return;
int a[n];
f (sizeof a, a); // warning: access to a by f may be out of bounds
...
}
-Wvla-parameter is included in -Wall ๐. The -Warray-parameter option does the same kind of thing for regular array arguments ๐ฆ.
-Wvolatile-register-varโ warns if a register variable is declaredvolatile๐ โโ๏ธ. Thevolatilemodifier doesn't stop every optimization that might eliminate reads or writes to register variables, so it's not the safety net you think it is ๐ซ . This warning is enabled by-Wall๐.-Wdisabled-optimizationโ warns if a requested optimization pass gets disabled ๐ ๏ธ. This doesn't usually mean your code is wrong, just that GCC's optimizers can't handle it effectively ๐คทโโ๏ธ. Often the issue is that your code is too big or too complex, and GCC refuses to optimize programs when the optimization would likely take an absurd amount of time ๐ข.-Wpointer-sign(C and Objective-C only) โ warns for pointer argument passing or assignment with different signedness ๐ง. This option is only supported for C and Objective-C. It's implied by-Walland by-Wpedantic, and you can turn it off with-Wno-pointer-sign๐ .-Wstack-protectorโ this one is only active when-fstack-protectoris active ๐ก๏ธ. It warns about functions that aren't protected against stack smashing ๐ฑ.-Woverlength-stringsโ warns about string constants longer than the "minimum maximum" length the C standard specifies ๐. Modern compilers usually allow string constants way longer than that minimum, but very portable programs should 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 raised to 4095 ๐. C++98 doesn't specify a normative minimum maximum, so GCC doesn't diagnose overlength strings in C++ ๐. This option is implied by-Wpedantic, and you can disable it with-Wno-overlength-strings๐ซถ.-Wunsuffixed-float-constants(C and Objective-C only) โ warns about any floating constant that doesn't have a suffix ๐ข. When you use it together with-Wsystem-headers, it also warns about those constants in system header files ๐งพ. This is super useful 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 GCC from warning about type mismatches in global declarations from different compilation units ๐. It requires-fltoto be enabled ๐ฌ. Enabled by default ๐.-Wno-designated-init(C and Objective-C only) โ suppresses warnings when a positional initializer is used to initialize a struct that's been marked with thedesignated_initattribute ๐.
โจ Options That Control Static Analysis โจ
-fanalyzerโ enables a static analysis of program flow ๐. It looks for "interesting" interprocedural paths through the code, and issues warnings for problems it finds on them ๐ต๏ธโโ๏ธ๐.
This analysis is lowkey expensive compared to other GCC warnings, so heads up ๐ธ๐
Turning this on also switches on all of these warnings ๐:
-Wanalyzer-double-fclose-Wanalyzer-double-free-Wanalyzer-exposure-through-output-file-Wanalyzer-file-leak-Wanalyzer-free-of-non-heap-Wanalyzer-malloc-leak-Wanalyzer-mismatching-deallocation-Wanalyzer-possible-null-argument-Wanalyzer-possible-null-dereference-Wanalyzer-null-argument-Wanalyzer-null-dereference-Wanalyzer-shift-count-negative-Wanalyzer-shift-count-overflow-Wanalyzer-stale-setjmp-buffer-Wanalyzer-tainted-array-index-Wanalyzer-unsafe-call-within-signal-handler-Wanalyzer-use-after-free-Wanalyzer-use-of-pointer-in-stale-stack-frame-Wanalyzer-write-to-const-Wanalyzer-write-to-string-literal
This only works if GCC was configured with analyzer support enabled ๐ซถ
-Wanalyzer-too-complex
When -fanalyzer is on, the analyzer uses a bunch of heuristics to poke around the control flow and data flow in your program. Honestly though, sufficiently complicated code can totally outsmart it ๐ญ
By default, the analysis quietly gives up if the code is too complicated and it hits an internal limit. -Wanalyzer-too-complex is the one that actually warns you when that happens โจ
-Wno-analyzer-double-fclose
This one needs -fanalyzer to turn it on, and you can use -Wno-analyzer-double-fclose to turn it off ๐
It warns about code paths where a FILE * can have fclose called on it more than once.
-Wno-analyzer-double-free
This one needs -fanalyzer to turn it on, and -Wno-analyzer-double-free turns it off ๐ฆ
It warns about code paths where a pointer can have a deallocator called on it more than once. That deallocator is either free, or one referenced by attribute malloc.
-Wno-analyzer-exposure-through-output-file
This one needs -fanalyzer to turn it on, and -Wno-analyzer-exposure-through-output-file turns it off ๐
It warns about code paths where a security-sensitive value gets written to an output file, like writing a password to a log file. Yikes ๐
-Wno-analyzer-file-leak
This one needs -fanalyzer to turn it on, and -Wno-analyzer-file-leak turns it off ๐ธ
It warns about code paths where a FILE * stream object from <stdio.h> gets leaked.
-Wno-analyzer-free-of-non-heap
This one needs -fanalyzer to turn it on, and -Wno-analyzer-free-of-non-heap turns it off ๐ง
It warns about code paths where free gets called on a non-heap pointer. For example, an on-stack buffer or a global.
-Wno-analyzer-malloc-leak
This one needs -fanalyzer to turn it on, and -Wno-analyzer-malloc-leak turns it off ๐ง
It warns about code paths where a pointer allocated through an allocator gets leaked. The allocator is either malloc, or a function marked with attribute malloc.
-Wno-analyzer-mismatching-deallocation
This one needs -fanalyzer to turn it on, and -Wno-analyzer-mismatching-deallocation turns it off ๐
It warns about code paths where the wrong deallocation function gets called on a pointer value. The check depends on which function allocated that pointer in the first place. It'll flag mismatches between free, scalar delete, and vector delete[], plus anything marked as an allocator/deallocator pair using attribute malloc.
-Wno-analyzer-possible-null-argument
This one needs -fanalyzer to turn it on, and -Wno-analyzer-possible-null-argument turns it off ๐
It warns about code paths where a possibly-NULL value gets passed to a function argument marked with __attribute__((nonnull)), which means that argument needs a non-NULL value.
-Wno-analyzer-possible-null-dereference
This one needs -fanalyzer to turn it on, and -Wno-analyzer-possible-null-dereference turns it off ๐ซง
It warns about code paths where a possibly-NULL value gets dereferenced.
-Wno-analyzer-null-argument
This one needs -fanalyzer to turn it on, and -Wno-analyzer-null-argument turns it off ๐ซ
It warns about code paths where a value known to be NULL gets passed to a function argument marked with __attribute__((nonnull)), which needs a non-NULL value.
-Wno-analyzer-null-dereference
This one needs -fanalyzer to turn it on, and -Wno-analyzer-null-dereference turns it off ๐
It warns about code paths where a value known to be NULL gets dereferenced.
-Wno-analyzer-shift-count-negative
This one needs -fanalyzer to turn it on, and -Wno-analyzer-shift-count-negative turns it off ๐
It warns about code paths where a shift is attempted with a negative count. It's the analyzer's cousin of -Wshift-count-negative, which lives in the C/C++ front ends. The difference is that this one works by analyzing interprocedural paths instead of just parsing the syntax tree. Still, the analyzer doesn't prioritize catching these, so false negatives are more likely compared to other warnings ๐ฅฒ
-Wno-analyzer-shift-count-overflow
This one needs -fanalyzer to turn it on, and -Wno-analyzer-shift-count-overflow turns it off โญ
It warns about code paths where a shift is attempted with a count greater than or equal to the precision of the operand's type. It's analogous to -Wshift-count-overflow in the C/C++ front ends, but it's based on analyzing interprocedural paths rather than merely parsing the syntax tree. The analyzer doesn't prioritize detecting these paths, so false negatives are more likely relative to other warnings.
-Wno-analyzer-stale-setjmp-buffer
This one needs -fanalyzer to turn it on, and -Wno-analyzer-stale-setjmp-buffer turns it off ๐งธ
It warns about code paths where longjmp is called to rewind to a jmp_buf tied to a setjmp call in a function that has already returned.
Here's the tea: when setjmp is called on a jmp_buf to record a rewind location, it records the stack frame. That stack frame becomes invalid once the function containing the setjmp call returns. Trying to rewind to it via longjmp would reference a stack frame that no longer exists, and that's likely to lead to a crash (or worse) ๐
Rewinding with longjmp into a stale stack frame can lead to a crash (or worse). Don't do it bestie ๐
โโ๏ธ
-Wno-analyzer-tainted-array-index
This warning needs both -fanalyzer and -fanalyzer-checker=taint to turn it on. Use -Wno-analyzer-tainted-array-index to turn it off ๐ก๏ธ
It warns about code paths where a value that could be under an attacker's control gets used as the index of an array access without being sanitized.
-Wno-analyzer-unsafe-call-within-signal-handler
This one needs -fanalyzer to turn it on, and -Wno-analyzer-unsafe-call-within-signal-handler turns it off ๐จ
It warns about code paths where a function known to be async-signal-unsafe (like fprintf) gets called from a signal handler.
-Wno-analyzer-use-after-free
This one needs -fanalyzer to turn it on, and -Wno-analyzer-use-after-free turns it off ๐๏ธ
It warns about code paths where a pointer gets used after a deallocator has been called on it. That deallocator is either free, or one referenced by attribute malloc.
-Wno-analyzer-use-of-pointer-in-stale-stack-frame
This one needs -fanalyzer to turn it on, and -Wno-analyzer-use-of-pointer-in-stale-stack-frame turns it off ๐ฐ๏ธ
It warns about code paths where a pointer gets dereferenced while pointing to a variable in a stale stack frame.
-Wno-analyzer-write-to-const
This one needs -fanalyzer to turn it on, and -Wno-analyzer-write-to-const turns it off ๐
It warns about code paths where the analyzer detects an attempt to write through a pointer to a const object. The analyzer doesn't prioritize catching these, so false negatives are more likely relative to other warnings.
-Wno-analyzer-write-to-string-literal
This one needs -fanalyzer to turn it on, and -Wno-analyzer-write-to-string-literal turns it off ๐
It warns about code paths where the analyzer detects an attempt to write through a pointer to a string literal. Same deal: the analyzer doesn't prioritize these, so false negatives are more likely relative to other warnings.
Pertinent parameters for controlling the exploration are these four โจ:
--param analyzer-bb-explosion-factor=value--param analyzer-max-enodes-per-program-point=value--param analyzer-max-recursion-depth=value--param analyzer-min-snodes-for-call-summary=value
The following options control the analyzer ๐
-fanalyzer-call-summaries
This one simplifies interprocedural analysis by computing the effect of certain calls, instead of exploring every path through the function from the callsite to each possible return. Iconic efficiency ๐ง
If it's enabled, call summaries only get used for functions with more than one call site, and that are sufficiently complicated (as per --param analyzer-min-snodes-for-call-summary=value).
-fanalyzer-checker=name
This one restricts the analyzer to run just the named checker, and enables it ๐ฏ
Some checkers are disabled by default, even with -fanalyzer. The taint checker is one of them. It's the one that implements -Wanalyzer-tainted-array-index, and you need this option to turn it on.
-fno-analyzer-feasibility
This option is intended for analyzer developers ๐งโ๐ป
By default, the analyzer checks that there's a feasible control flow path for each diagnostic it emits. In other words, the conditions that hold can't be mutually exclusive. Diagnostics with no feasible path get rejected. You can suppress this filtering with -fno-analyzer-feasibility, which is handy for debugging issues in this code ๐ง
-fanalyzer-fine-grained
This option is intended for analyzer developers ๐งโ๐ป
Okay bestie, so internally the analyzer builds this "exploded graph" ๐ธ๏ธโจ that mashes control flow graphs together with data flow info. It's giving main character energy ๐
By default, an edge in this graph can hold the effects of a whole run of statements inside one basic block ๐ง . With -fanalyzer-fine-grained, every single statement gets its own edge ๐ (so much more detail, no cap).
-fanalyzer-show-duplicate-countโ ๐ฏ Dev-only vibes! If a bunch of diagnostics get flagged as duplicates of each other, GCC drops a note on the best one saying how many extra diagnostics the dedup logic quietly suppressed ๐คซ.-fno-analyzer-state-mergeโ ๐ซ Dev-only! By default the analyzer keeps things simple by merging states that are similar enough at each program point while it builds the "exploded graph." With-fno-analyzer-state-merge, that merging gets switched off so you can debug state-handling issues ๐ง.-fno-analyzer-state-purgeโ ๐งน Dev-only! Normally the analyzer tidies up by purging bits of state at a program point that seem irrelevant anymore, like the values of locals that never get touched later in the function and don't matter for leak analysis. With-fno-analyzer-state-purge, that purging is suppressed, which is handy for debugging state-handling issues ๐.-fanalyzer-transitivityโ ๐ Enables transitivity of constraints within the analyzer.-fanalyzer-verbose-edgesโ ๐ Dev-only! Turns on more verbose, lower-level detail in the descriptions of control flow inside diagnostic paths.-fanalyzer-verbose-state-changesโ ๐ข Dev-only! Turns on more verbose, lower-level detail in the descriptions of state machine events inside diagnostic paths.-fanalyzer-verbosity=levelโ ๐๏ธ Controls how complex the control flow paths are that get emitted for analyzer diagnostics. Thelevelcan be one of:0โ ๐ Shows interprocedural call and return events, plus the most pertinent state-change events for a diagnostic. For example, for a double-"free" diagnostic, both calls tofreeget shown.1โ ๐ช Same as level0, but also shows events for the entry to each function.2โ ๐ Same as level1, but also shows control flow events that are significant to triggering the issue (like "true path taken" at a conditional). This is the default!3โ ๐ Same as level2, but shows all control flow events, not just the significant ones.4โ ๐งช Dev-only! Adds various other events meant for debugging the analyzer.
-fdump-analyzerโ ๐๏ธ Dumps internal details about what the analyzer is doing tofile.analyzer.txt. This option gets overridden by-fdump-analyzer-stderr.-fdump-analyzer-stderrโ ๐ฅ๏ธ Dumps internal details about what the analyzer is doing to stderr. This option overrides-fdump-analyzer.-fdump-analyzer-callgraphโ ๐ณ Dumps a representation of the call graph that's suitable for viewing with GraphViz tofile.callgraph.dot.-fdump-analyzer-exploded-graphโ ๐จ Dumps a representation of the "exploded graph" suitable for viewing with GraphViz tofile.eg.dot. The nodes are color-coded based on state-machine states so state changes pop out ๐.-fdump-analyzer-exploded-nodesโ ๐ Emits diagnostics showing where nodes in the "exploded graph" sit in relation to the program source.-fdump-analyzer-exploded-nodes-2โ ๐ Dumps a textual representation of the "exploded graph" tofile.eg.txt.-fdump-analyzer-exploded-nodes-3โ ๐ Dumps a textual representation of the "exploded graph" with one dump file per node, namedfile.eg-id.txt. Heads up, this is typically a large number of dump files ๐ญ.-fdump-analyzer-feasibilityโ ๐ Dumps internal details about the analyzer's search for feasible paths. The details are written in a form suitable for viewing with 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. The precise format is subject to change, so don't build your whole life around it ๐ซถ.-fdump-analyzer-state-purgeโ ๐บ๏ธ Same vibe as-fdump-analyzer-supergraph: dumps a "supergraph" representation suitable for GraphViz, but annotates the graph with info on what state will be purged at each node. The graph gets written tofile.state-purge.dot.-fdump-analyzer-supergraphโ ๐ธ๏ธ Dumps representations of the "supergraph" suitable for GraphViz tofile.supergraph.dotand tofile.supergraph-eg.dot. These show all of the control flow graphs in the program, with interprocedural edges for calls and returns. The second dump has annotations showing nodes in the "exploded graph" and any diagnostics tied to them ๐.
๐ Options for Debugging Your Program
Okay so if you want GCC to emit extra info for a debugger, you almost always just need to add -g to your other options ๐.
GCC lets you use -g with -O too ๐ฅ. Fair warning though, the shortcuts optimized code takes can be lowkey 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 execute in different places because they got moved out of loops. Even so, it's totally possible to debug optimized output โจ. That makes it reasonable to use the optimizer for programs that might have bugs.
If you aren't using some other optimization option, consider using -Og with -g ๐ง. With no -O option at all, some compiler passes that collect info useful for debugging don't run at all, so -Og may give you a better debugging experience ๐.
-gโ ๐ธ Produces debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information.- On most systems that use stabs format,
-gturns on extra debugging info that only GDB can use. That makes debugging better in GDB but probably makes other debuggers crash or refuse to read the program ๐. If you want to be certain whether the extra info gets generated, use-gstabs+,-gstabs,-gxcoff+,-gxcoff, or-gvms(see below).
- On most systems that use stabs format,
-ggdbโ ๐งธ Produces debugging information for use by GDB. This means using the most expressive format available (DWARF, stabs, or the native format if neither of those are supported), including GDB extensions if at all possible ๐.-gdwarf,-gdwarf-versionโ ๐ฆ Produces debugging information in DWARF format (if that's supported). The value ofversioncan be 2, 3, 4 or 5. The default version for most targets is 5, except VxWorks, TPF and Darwin/Mac OS X, which default to version 2, and AIX, which defaults to version 4.- With DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables.
- Version 4 may require GDB 7.0 and
-fvar-tracking-assignmentsfor 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)keep a reference to DWARF Version 2 in their names, but they apply to all currently-supported versions of DWARF ๐ฅน.
-gstabsโ ๐ง Produces debugging information in stabs format (if that's supported), without GDB extensions. This is the format DBX uses on most BSD systems. On MIPS, Alpha and System V Release 4 systems, this option produces stabs debugging output that DBX doesn't understand. On System V Release 4 systems, this option requires the GNU assembler.-gstabs+โ ๐ง Produces debugging information in stabs format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands.
โ ๏ธ Using these extensions is likely to make other debuggers crash or refuse to read the program.
-gxcoffโ ๐ Produces debugging information in XCOFF format (if that's supported). This is the format DBX uses on IBM RS/6000 systems.-gxcoff+โ ๐ญ Produces debugging information in XCOFF format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands.
โ ๏ธ Using these extensions is likely to make other debuggers crash or refuse to read the program, and may cause assemblers other than the GNU assembler (GAS) to fail with an error.
-gvmsโ ๐ธ Produces debugging information in Alpha/VMS debug format (if that's supported). This is the format DEBUG uses on Alpha/VMS systems.-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ ๐๏ธ Requests debugging information and also useslevelto decide how much info you get. The default level is 2.- Level
0produces no debug information at all. So-g0negates-g๐ . - Level
1produces minimal information, enough for making backtraces in parts of the program you don't plan to debug. This includes descriptions of functions and external variables, and line number tables, but no information about local variables. - Level
3includes extra information, like all the macro definitions present in the program. Some debuggers support macro expansion when you use-g3๐. - If you use multiple
-goptions, with or without level numbers, the last one is the one that's effective ๐ซถ. -gdwarfdoesn't accept a concatenated debug level, to avoid confusion with-gdwarf-level. Instead, use an additional-gleveloption to change the debug level for DWARF.
- Level
-fno-eliminate-unused-debug-symbolsโ ๐งน By default, no debug information is produced for symbols that aren't actually used. Use this option if you want debug information for all symbols ๐.-femit-class-debug-always: okay so instead of dropping the debug info for a C++ class into just one object file, this one puts it in every object file that uses the class ๐ . Only reach for it if your debugger literally can't handle the normal way GCC emits class debug info ๐ญ, because it can make the debug info up to a factor of two bigger ๐ซ .-fno-merge-debug-strings: tells the linker to NOT squish together identical strings in the debug info across different object files ๐ โโ๏ธ. Not every assembler or linker can merge, btw. Merging shrinks the output's debug info but makes linking take longer โณ. Merging is on by default โจ.-fdebug-prefix-map=old=new: when you compile files that live in directoryold, the debug info will describe them as if they lived innewinstead ๐บ๏ธ. Use it to swap a build-time path for an install-time path, or turn an absolute path into a relative one by using.asnew. It can give more reproducible, location-independent builds ๐ธ, but you might need an extra command to tell GDB where the source files are ๐. See also-ffile-prefix-map.-fvar-tracking: runs the variable tracking pass ๐ต๏ธโโ๏ธ, which figures out where variables are stored at each position in the code. The result is better debug info, as long as your debug format supports it ๐. It's enabled by default when you optimize (-Os,-O,-O2, ...) and have debug info (-g) and the format supports it.-fvar-tracking-assignments: annotates assignments to user variables early in compilation and tries to carry those annotations all the way to the end ๐, all to improve debug info while optimizing. Using-gdwarf-4alongside it is recommended. It can be enabled even if var-tracking is disabled, in which case the annotations get created and maintained but tossed at the end. By default this is enabled together with-fvar-tracking, except when selective scheduling is enabled.-gsplit-dwarf: if DWARF debug info is enabled, it shoves as much of that info as possible into a separate output file with the extension.dwo๐ฆ. This lets the build system skip linking files that have debug info ๐. To be useful, you need a debugger that can read.dwofiles.-gdwarf32,-gdwarf64: if DWARF debug info is enabled,-gdwarf32picks the 32-bit DWARF format and-gdwarf64picks the 64-bit one ๐งฎ. The default is target specific, though on most targets it's-gdwarf32๐คทโโ๏ธ. The 32-bit format is smaller but can't support more than 2GiB of debug info in any of the DWARF debug info sections ๐ฌ. The 64-bit format allows larger debug info, but not all consumers support it well yet.-gdescribe-dies: adds description attributes to some DWARF DIEs that have no name attribute, like artificial variables, external references, and call site parameter DIEs ๐ง.-gpubnames: generates the DWARF.debug_pubnamesand.debug_pubtypessections ๐.-ggnu-pubnames: generates.debug_pubnamesand.debug_pubtypesin a format that's suitable for converting into a GDB index ๐ฅ. This is only useful with a linker that can produce GDB index version 7.-fdebug-types-section: when using DWARF Version 4 or higher, type DIEs can get their own.debug_typessection instead of living in.debug_info๐๏ธ. It's more efficient to put them in a separate comdat section, since the linker can then remove duplicates. BUT not all DWARF consumers support.debug_typesyet, and on some objects it actually produces larger debug info instead of smaller ๐.-grecord-gcc-switches,-gno-record-gcc-switches: the command-line options used to invoke the compiler that may affect code generation get appended to theDW_AT_producerattribute in DWARF debug info ๐. The options are joined with spaces, separating them from each other and from the compiler version. It's enabled by default. See also-frecord-gcc-switchesfor another way to store compiler options in the object file.-gstrict-dwarf: disallows using extensions from a later DWARF standard version than the one picked with-gdwarf-version๐ซ. On most targets, though, using non-conflicting DWARF extensions from later standard versions is allowed anyway.-gno-strict-dwarf: allows using extensions from a later DWARF standard version than the one selected with-gdwarf-version๐ฆ.-gas-loc-support: tells the compiler that the assembler supports.locdirectives, so it may use them to have the assembler generate DWARF2+ line number tables ๐. This is generally desirable, because assembler-generated line-number tables are a lot more compact than the ones the compiler can make itself. It's enabled by default if, at GCC configure time, the assembler was found to support these directives.-gno-as-loc-support: forces GCC to generate DWARF2+ line number tables internally, if DWARF2+ line number tables are to be generated at all ๐ โโ๏ธ.-gas-locview-support: tells the compiler that the assembler supports "view" assignment and reset assertion checking in.locdirectives ๐. It's enabled by default if, at GCC configure time, the assembler was found to support them.-gno-as-locview-support: forces GCC to assign view numbers internally, if-gvariable-location-viewsis explicitly requested ๐ง.-gcolumn-info,-gno-column-info: emits location column info into DWARF debug info, instead of just file and line ๐. This option is enabled by default.-gstatement-frontiers,-gno-statement-frontiers: makes GCC create markers in the internal representation at the beginning of statements, keep them roughly in place throughout compilation ๐, and use them to guide the output of "is_stmt" markers in the line number table. It's enabled by default when you optimize (-Os,-O,-O2, ...) and output DWARF 2 debug info at the normal level ๐ .-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-views: augments variable location lists with progressive view numbers implied by the line number table โจ. This lets debug info consumers inspect state at certain points of the program, even if no instructions for the matching source locations exist there. If the assembler lacks view number support in line number tables, the compiler will emit the line number table itself, which makes them somewhat less compact. The augmented tables and lists are fully backward-compatible, so consumers that don't know about the augmentations can still read them, but they won't get any benefit from them either.
This is enabled by default when outputting DWARF 2 debug info at the normal level, as long as there's assembler support, -fvar-tracking-assignments is enabled, and -gstrict-dwarf is not. When assembler support isn't available it may still be enabled, but it 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 view number representation 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 a reference implementation of the proposed representation. Debug info consumers aren't expected to support this extended format, so they'd be unable to decode location lists that use it.
-ginternal-reset-location-views,-gno-internal-reset-location-views: attempts to figure out which location views can be omitted from location view lists ๐ง . This requires the compiler to have very accurate insn length estimates, which isn't always the case, and it may silently generate incorrect view lists when 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 the capabilities of the assembler and linker used. type may be one ofnone(don't compress debug sections),zlib(use zlib compression in ELF gABI format), orzlib-gnu(use zlib compression in traditional GNU format). If the linker doesn't support writing compressed debug sections, the option is rejected. Otherwise, if the assembler doesn't support them,-gzis 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 one substantially shrinks debug info, but the debugger can lose a significant amount of type information. For a less aggressive option, see-femit-struct-debug-reduced, and for more detailed control, see-femit-struct-debug-detailed. It only works with DWARF debug output.
Okay so bestie, the -femit-struct-debug-* flags are all about keeping your debug info lean ๐งนโจ. Here's the rest of that gang:
-femit-struct-debug-reducedโ ๐ฆ Only emit debug info for struct-like types when the base name of your compile source matches the base name of the file where the type lives. The exceptions are templates and anything defined in a system header, which get skipped. This makes your debug info way smaller, but the debugger might lose a bit of type info. For something more aggressive, check out-femit-struct-debug-baseonly, and for finer control,-femit-struct-debug-detailed. This one only works with DWARF debug output ๐-femit-struct-debug-detailed[=spec-list]โ ๐ This is the power-user version. You tell the compiler exactly which struct-like types get debug info, so you don't get the same struct duplicated across different object files in one program. It's a detailed version of-femit-struct-debug-reducedand-femit-struct-debug-baseonly, and honestly it covers most needs ๐ฅ
A spec looks like this:
[dir:|ind:][ord:|gen:](any|sys|base|none)
The first word is optional and narrows things down to structs used directly (dir:) or indirectly (ind:). A struct is used directly when it's the type of a variable, member. Indirect use happens through pointers to structs, so when using an incomplete struct is valid, the use counts as indirect. For example, struct one direct; is direct and struct two * indirect; is indirect ๐ง
The second word is optional too and picks ordinary structs (ord:) or generic structs (gen:). Generic structs are a little tricky ngl. In C++, these are non-explicit specializations of template classes, or non-template classes within the above. Other languages have generics, but -femit-struct-debug-detailed doesn't implement them yet ๐
The third word is the one that picks the source files. none and any mean what you'd expect. base means the base name of the file where the type is declared has to match the base name of the main compilation file. 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 satisfy base or are declared in system or compiler headers ๐ธ
You might need to experiment a bit to find the best settings for your app, no shame in that ๐ซถ
The default is -femit-struct-debug-detailed=all. This one also only works with DWARF debug output.
-fno-dwarf2-cfi-asmโ ๐ Instead of using GAS.cfi_*directives, this puts the DWARF unwind info into a compiler-generated.eh_framesection.-fno-eliminate-unused-debug-typesโ ๐ง Normally, when making DWARF output, GCC skips debug symbols for types that never get used in the file being compiled. Sometimes you want debug info for every type declared in a compilation unit, even unused ones. Like, if you want to cast a value to a type that's declared but never actually used in your program while you're debugging. But honestly, most of the time this just wastes a ton of space ๐ญ
โก Options That Control Optimization ๐
These options control different kinds of optimization, and they're the main vibe for making your code faster or smaller ๐
Without any optimization option, the compiler's main goal is to keep compile time low and make debugging behave the way you'd 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 another 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 compile time and might make debugging less predictable ๐ฅ
The compiler optimizes based on what it knows about the program. Compiling multiple files at once into a single output file lets the compiler use info from all of those files when compiling each one ๐
Not every optimization has its own 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. Similarly, -Og suppresses a lot of optimization passes ๐
Depending on the target and how GCC was configured, the set of optimizations enabled at each -O level might be a bit different from what's listed here. To see the exact set enabled at each level, run -Q --help=optimizers ๐
-O,-O1โ โจ Optimize. Optimizing compilation takes a bit more time, and a lot more memory for a large function.
With -O, the compiler tries to shrink code size and speed up execution, but it skips any optimizations that take a long time to compile ๐
-O turns on the following optimization flags:
-fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments
-fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdelayed-branch
-fdse -fforward-propagate -fguess-branch-probability -fif-conversion
-fif-conversion2 -finline-functions-called-once -fipa-modref
-fipa-profile -fipa-pure-const -fipa-reference
-fipa-reference-addressable -fmerge-constants -fmove-loop-invariants
-fomit-frame-pointer -freorder-blocks -fshrink-wrap
-fshrink-wrap-separate -fsplit-wide-types -fssa-backprop
-fssa-phiopt -ftree-bit-ccp -ftree-ccp -ftree-ch
-ftree-coalesce-vars -ftree-copy-prop -ftree-dce
-ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre
-ftree-phiprop -ftree-pta -ftree-scev-cprop -ftree-sink -ftree-slsr
-ftree-sra -ftree-ter -funit-at-a-time
-O2โ ๐ฅ Optimize even more. GCC runs nearly every supported optimization that doesn't involve a space-speed tradeoff. Compared to-O, this increases both compile time and the performance of the generated code ๐
-O2 turns on every optimization flag that -O does. It also turns on these:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fcaller-saves -fcode-hoisting -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize
-fdevirtualize-speculatively -fexpensive-optimizations
-ffinite-loops -fgcse -fgcse-lm -fhoist-adjacent-loads
-finline-functions -finline-small-functions -findirect-inlining
-fipa-bit-cp -fipa-cp -fipa-icf -fipa-ra -fipa-sra -fipa-vrp
-fisolate-erroneous-paths-dereference -flra-remat
-foptimize-sibling-calls -foptimize-strlen -fpartial-inlining
-fpeephole2 -freorder-blocks-algorithm=stc
-freorder-blocks-and-partition -freorder-functions
-frerun-cse-after-loop -fschedule-insns -fschedule-insns2
-fsched-interblock -fsched-spec -fstore-merging -fstrict-aliasing
-fthread-jumps -ftree-builtin-call-dce -ftree-pre
-ftree-switch-conversion -ftree-tail-merge -ftree-vrp
โ ๏ธ Heads up: please check the warning under-fgcseabout using-O2on programs that use computed gotos. It's important ๐
๐ฃ NOTE: In Ubuntu 8.10 and later,-D_FORTIFY_SOURCE=2is set by default. In Ubuntu 24.04 and later,-D_FORTIFY_SOURCE=3is set by default instead. It turns on when-Ois set to 2 or higher, and it adds extra compile-time and run-time checks for several libc functions. To turn it off, use either-U_FORTIFY_SOURCEor-D_FORTIFY_SOURCE=0๐ก๏ธ
-O3โ ๐ Optimize yet more.-O3turns on everything-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-loop-vectorize -ftree-partial-pre -ftree-slp-vectorize
-funswitch-loops -fvect-cost-model -fvect-cost-model=dynamic
-fversion-loops-for-strides
-O0โ ๐งธ Reduce compile time and keep debugging predictable. This is the default.-Osโ ๐ Optimize for size.-Osenables all the-O2optimizations except the ones that often make code bigger:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, tells the compiler to tune for code size instead of execution speed, and adds more optimizations designed to shrink code size ๐ฆ
-Ofastโ ๐ช๏ธ Disregard strict standards compliance.-Ofastenables all-O3optimizations, plus optimizations that aren't valid for every standard-compliant program. It turns on-ffast-math,-fallow-store-data-races, and the Fortran-specific-fstack-arrays(unless-fmax-stack-var-sizeis specified), and-fno-protect-parens๐-Ogโ ๐ Optimize the debugging experience.-Ogis the go-to level for the standard 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 debuggable code, because some compiler passes that collect debug info are disabled at-O0๐
Like -O0, -Og fully disables a bunch of optimization passes, so the individual options that control them do nothing. Otherwise, -Og enables all the -O1 optimization flags except the ones that could get in the way of debugging:
-fbranch-count-reg -fdelayed-branch -fdse -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fssa-phiopt -ftree-bit-ccp -ftree-dse
-ftree-pta -ftree-sra
If you use multiple -O options, with or without level numbers, the last one is the one that counts ๐ฏ
Options written as -fflag are machine-independent. Most flags come in both positive and negative forms, and the negative form of -ffoo is -fno-foo. The table below only lists one form, the one you'd typically use. To figure out the other, just remove no- or add it ๐ท
The following options control specific optimizations. They're either turned on by -O options or are related to ones that are. You can use these flags in the rare cases when you want to "fine-tune" which optimizations get performed ๐
-fno-defer-popโ ๐ okay bestie, on machines that have to pop arguments after a function call, this makes the compiler pop them right away as each function returns. At levels-O1and higher,-fdefer-popis the default, which lets arguments pile up on the stack across several calls so they can all get popped at once โจ-fforward-propagateโ ๐ฆ this runs a forward propagation pass on RTL. It tries to combine two instructions and then checks whether the result can be simplified. If loop unrolling is active, two passes happen, and the second one gets scheduled after loop unrolling.- Enabled by default at optimization levels
-O,-O2,-O3,-Os.
- Enabled by default at optimization levels
-ffp-contract=*style*โ ๐งฎ this one is giving options, so let's break it down:-ffp-contract=offdisables floating-point expression contraction.-ffp-contract=fastenables contraction, like forming fused multiply-add operations, if the target has native support for them.-ffp-contract=onenables contraction if the language standard allows it. This is currently not implemented and is treated the same as-ffp-contract=off๐- The default is
-ffp-contract=fast.
-fomit-frame-pointerโ ๐ธ omits the frame pointer in functions that don't need one. This skips the instructions for saving, setting up, and restoring the frame pointer, and on many targets it also frees up an extra register.- On some targets this flag has no effect ๐ญ because the standard calling sequence always uses a frame pointer, so it can't be left out.
-fno-omit-frame-pointerdoesn't guarantee the frame pointer is used in every function. Several targets always omit it in leaf functions.- Enabled by default at
-Oand higher.
-foptimize-sibling-callsโ โจ optimizes sibling and tail recursive calls.- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-foptimize-strlenโ ๐ optimizes various standard C string functions (e.g."strlen","strchr"or"strcpy") and their"_FORTIFY_SOURCE"counterparts into faster alternatives.- Enabled at levels
-O2,-O3.
- Enabled at levels
-fno-inlineโ ๐ don't expand any functions inline, except the ones marked with the"always_inline"attribute. This is the default when you're not optimizing.- Single functions can opt out of inlining by marking them with the
"noinline"attribute.
- Single functions can opt out of inlining by marking them with the
-finline-small-functionsโ ๐ฅ integrates functions into their callers when their body is smaller than the function call code, so the overall program gets smaller. The compiler heuristically decides which functions are simple enough, and this applies to all functions, even ones not declared inline.- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-findirect-inliningโ ๐ also inlines indirect calls that are known at compile time thanks to previous inlining. This only does anything when inlining is already turned on by-finline-functionsor-finline-small-functions.- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-finline-functionsโ ๐ considers all functions for inlining, even ones not declared inline. The compiler heuristically decides which ones are worth it.- If every call to a given function gets integrated and the function is declared
"static", it's normally not output as assembler code on its own. - Enabled at levels
-O2,-O3,-Os. Also enabled by-fprofile-useand-fauto-profile.
- If every call to a given function gets integrated and the function is declared
-finline-functions-called-onceโ ๐ง considers all"static"functions called once for inlining into their caller, even if they aren't marked"inline". If a call gets integrated, the function isn't output as assembler code on its own.- Enabled at levels
-O1,-O2,-O3and-Os, but not-Og.
- Enabled at levels
-fearly-inliningโ ๐ฆ inlines functions marked"always_inline", plus functions whose body seems smaller than the function call overhead, early on. This happens before the-fprofile-generateinstrumentation and the real inlining pass. Doing it this way makes profiling significantly cheaper and usually makes inlining faster in programs with large chains of nested wrapper functions.- Enabled by default.
-fipa-sraโ ๐ performs interprocedural scalar replacement of aggregates, removes unused parameters, and swaps parameters passed by reference for parameters passed by value.- Enabled at levels
-O2,-O3and-Os.
- Enabled at levels
-finline-limit=*n*โ ๐ by default GCC limits the size of functions that can be inlined. This flag gives you coarse control over that limit. n is the size of functions that can be inlined, measured in pseudo instructions.- Inlining is actually controlled by a bunch of parameters, which you can set one at a time with
--param name=value. The-finline-limit=noption sets some of them like this:max-inline-insns-singleis set ton/2.max-inline-insns-autois set ton/2.
- See below for documentation of the individual inlining parameters and their defaults.
- Note: there may be no value of
-finline-limitthat results in default behavior. - Note: in this context, a pseudo instruction is an abstract measurement of a function's size. It in no way represents a count of assembly instructions, so its exact meaning might change from one release to another ๐
- Inlining is actually controlled by a bunch of parameters, which you can set one at a time with
-fno-keep-inline-dllexportโ ๐ซถ a more fine-grained version of-fkeep-inline-functions, which only applies to functions declared with the"dllexport"attribute or declspec.-fkeep-inline-functionsโ ๐ in C, emits"static"functions declared"inline"into the object file, even if the function has been inlined into all of its callers. This switch doesn't affect functions using the"extern inline"extension in GNU C90. In C++, it emits any and all inline functions into the object file.-fkeep-static-functionsโ ๐ emits"static"functions into the object file, even if the function is never used.-fkeep-static-constsโ ๐ emits variables declared"static const"when optimization isn't turned on, even if the variables aren't referenced.- GCC enables this by default. If you want the compiler to check whether a variable is referenced regardless of optimization, use
-fno-keep-static-constsinstead.
- GCC enables this by default. If you want the compiler to check whether a variable is referenced regardless of optimization, use
-fmerge-constantsโ ๐งฉ attempts to merge identical constants (string constants and floating-point constants) across compilation units.- This is the default for optimized compilation if the assembler and linker support it. Use
-fno-merge-constantsto inhibit this behavior. - Enabled at levels
-O,-O2,-O3,-Os.
- This is the default for optimized compilation if the assembler and linker support it. Use
-fmerge-all-constantsโ ๐คฏ attempts to merge identical constants and identical variables.- This option implies
-fmerge-constants. On top of that, it considers things like constant initialized arrays or initialized constant variables with integral or floating-point types. Languages like C or C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations, so using this option results in non-conforming behavior.
- This option implies
๐จ Bestie, heads up: -fmerge-all-constants results in non-conforming behavior, so think carefully before you reach for it ๐
-fmodulo-schedโ ๐ข performs swing modulo scheduling immediately before the first scheduling pass. It looks at innermost loops and reorders their instructions by overlapping different iterations.-fmodulo-sched-allow-regmovesโ ๐๏ธ performs more aggressive SMS-based modulo scheduling with register moves allowed. Setting this flag deletes certain anti-dependence edges, which triggers the generation of reg-moves based on life-range analysis. This option is only effective with-fmodulo-schedenabled.-fno-branch-count-regโ ๐ข disables the optimization pass that scans for chances to use "decrement and branch" instructions on a count register, instead of instruction sequences that decrement a register, compare it against zero, and then branch based on the result. This is only meaningful on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390. Note that-fno-branch-count-regdoesn't remove the decrement and branch instructions introduced by other optimization passes.- The default is
-fbranch-count-regat-O1and higher, except for-Og.
- The default is
-fno-function-cseโ ๐ โโ๏ธ doesn't put function addresses in registers. Instead, each instruction that calls a constant function contains the function's address explicitly.- This gives you less efficient code, but some strange hacks that alter the assembler output may get confused by the optimizations performed when this option isn't used.
- The default is
-ffunction-cse
-fno-zero-initialized-in-bssโ ๐๏ธ if the target supports a BSS section, GCC by default puts variables that are initialized to zero into BSS, which can save space in the resulting code. This option turns that off, because some programs explicitly rely on variables going to the data section, e.g. so the resulting executable can find the beginning of that section and/or make assumptions based on that.- The default is
-fzero-initialized-in-bss.
- The default is
-fthread-jumpsโ ๐งต performs optimizations that check whether a jump branches to a location where another comparison, subsumed by the first, is found. If so, the first branch is redirected either to the destination of the second branch or to a point immediately after it, depending on whether the condition is known to be true or false.- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-fsplit-wide-typesโ ๐ฐ when using a type that occupies multiple registers, like"long long"on a 32-bit system, splits the registers apart and allocates them independently. This normally generates better code for those types, but it may make debugging more difficult.- Enabled at levels
-O,-O2,-O3,-Os.
- Enabled at levels
-fsplit-wide-types-earlyโ โฐ fully splits wide types early, instead of very late. This option has no effect unless-fsplit-wide-typesis turned on.- This is the default on some targets.
-fcse-follow-jumpsโ okay so during common subexpression elimination (CSE), GCC peeks through jump instructions as long as no other path reaches the jump's target. Like, when CSE hits anifwith anelseclause, it follows the jump when the tested condition is false ๐- Enabled at levels
-O2,-O3,-Os. ๐
- Enabled at levels
-fcse-skip-blocksโ this is basically-fcse-follow-jumps's bestie ๐ซถ It makes CSE follow jumps that conditionally skip over blocks. So when it sees a simpleifwith noelse, it hops right over the body of theif. Iconic ๐ฆ- Enabled at levels
-O2,-O3,-Os. โจ
- Enabled at levels
-frerun-cse-after-loopโ runs common subexpression elimination again after the loop optimizations are done. Second glow-up, no cap ๐- Enabled at levels
-O2,-O3,-Os. ๐ธ
- Enabled at levels
-fgcseโ turns on a global common subexpression elimination pass. This one also does global constant and copy propagation, so it's doing a lot, periodt ๐ฅ- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
Note: if you're compiling a program that uses computed gotos (a GCC extension), you might get better run-time performance by turning off this global CSE pass. Just add -fno-gcse to your command line. Not every program is gonna love the same vibe, so test it, bestie ๐
-fgcse-lmโ when this is on, global CSE tries to move loads that only get killed by stores into themselves. So a loop with a load/store sequence can get reshaped: the load moves outside the loop, and a copy/store stays inside it. Very main character energy ๐- Enabled by default when
-fgcseis enabled. ๐
- Enabled by default when
-fgcse-smโ after global CSE runs, a store motion pass kicks in. It tries to move stores out of loops. Team it up with-fgcse-lmand loops with a load/store sequence can turn into a load before the loop and a store after it ๐ง- Not enabled at any optimization level. ๐ฅฒ
-fgcse-lasโ the global CSE pass gets rid of redundant loads that come right after stores to the same memory location. It catches both partial and full redundancies. Main character cleanup ๐งนโจ- Not enabled at any optimization level.
-fgcse-after-reloadโ runs a redundant load elimination pass after reload. Its whole job is to tidy up redundant spilling ๐งฝ- Enabled by
-fprofile-useand-fauto-profile. ๐
- Enabled by
-faggressive-loop-optimizationsโ this tells the loop optimizer to lean on language constraints to figure out bounds for how many times a loop runs. It assumes your loop code never triggers undefined behavior, like signed integer overflows or out-of-bound array accesses (so please don't ๐). Those bounds guide loop unrolling, loop peeling, and loop exit test optimizations.- This option is enabled by default. ๐
-funconstrained-commonsโ tells the compiler that variables declared in common blocks (like in Fortran) might get overridden later with longer trailing arrays. This stops certain optimizations that rely on knowing the array bounds, so it's a little bit of a trade-off ๐ฆ-fcrossjumpingโ performs the cross-jumping transformation. It unifies equivalent code and saves code size. The result may or may not perform better than without cross-jumping, so it's a vibe check ๐คทโโ๏ธ- Enabled at levels
-O2,-O3,-Os. ๐
- Enabled at levels
-fauto-inc-decโ combines increments or decrements of addresses with memory accesses. This pass always gets skipped on architectures that don't have instructions to support it.- Enabled by default at
-Oand higher on architectures that support this. ๐ฅ
- Enabled by default at
-fdceโ performs dead code elimination (DCE) on RTL. Bye bye, useless code ๐๐- Enabled by default at
-Oand higher.
- Enabled by default at
-fdseโ performs dead store elimination (DSE) on RTL. Same energy as-fdce, but for stores nobody reads ๐งน- Enabled by default at
-Oand higher.
- Enabled by default at
-fif-conversionโ tries to transform conditional jumps into branch-less equivalents. This includes conditional moves, min, max, set flags and abs instructions, plus some tricks you can do with standard arithmetic ๐งฎ Whether conditional execution gets used on chips that have it is controlled by-fif-conversion2.- Enabled at levels
-O,-O2,-O3,-Os, but not with-Og. ๐
- Enabled at levels
-fif-conversion2โ uses conditional execution (where the chip has it) to turn conditional jumps into branch-less equivalents. Smooth ๐ซง- Enabled at levels
-O,-O2,-O3,-Os, but not with-Og. ๐ธ
- Enabled at levels
-fdeclone-ctor-dtorโ okay this one's a whole saga ๐ญ The C++ ABI needs multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that callsoperator deleteafterwards. For a hierarchy with virtual bases, the base and complete variants are clones, meaning you get two copies of the function. With this option, those base and complete variants become thunks that call a common implementation. Less duplicate code, more slay โจ- Enabled by
-Os. ๐ง
- Enabled by
-fdelete-null-pointer-checksโ assumes programs can't safely dereference null pointers, and that no code or data element lives at address zero. This turns on simple constant folding optimizations at all levels. On top of that, other GCC optimization 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 ๐- Note: in some environments this assumption isn't true. If your program depends on that behavior, use
-fno-delete-null-pointer-checksto turn this optimization off. - This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR, CR16, and MSP430, this option is completely disabled. ๐ซ
- Passes that use the dataflow information are enabled independently at different optimization levels. ๐
- Note: in some environments this assumption isn't true. If your program depends on that behavior, use
-fdevirtualizeโ tries to convert calls to virtual functions into direct calls. This happens both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp).- Enabled at levels
-O2,-O3,-Os. ๐
- Enabled at levels
-fdevirtualize-speculativelyโ tries to convert calls to virtual functions into speculative direct calls. Using 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 one. Speculative calls unlock more optimizations, like inlining. If they seem useless after further optimization, they get converted back to their original form ๐-fdevirtualize-at-ltransโ streams extra information needed for aggressive devirtualization when the link-time optimizer runs in local transformation mode. You get more devirtualization, but the streamed data gets way bigger. So it's disabled by default, bestie ๐ฅฒ-fexpensive-optimizationsโ performs a bunch of minor optimizations that are kinda pricey to run ๐ธ- Enabled at levels
-O2,-O3,-Os. ๐
- Enabled at levels
-freeโ tries to remove redundant extension instructions. This is especially helpful for the x86-64 architecture, which implicitly zero-extends into 64-bit registers after writing to the lower 32-bit half. Clean and tidy ๐งผ- Enabled for Alpha, AArch64 and x86 at levels
-O2,-O3,-Os.
- Enabled for Alpha, AArch64 and x86 at levels
-fno-lifetime-dseโ in C++, an object's value only gets affected by changes made within its lifetime. The object has an indeterminate value when its constructor begins, and any changes during its lifetime are dead once it's destroyed. Normally, dead store elimination takes advantage of that. But if your code relies on the object's storage value sticking around past the object's lifetime, use this flag to disable the optimization. ๐ โโ๏ธ- To keep stores before the constructor starts (say, because your
operator newclears the object storage) but still treat the object as dead after the destructor, use-flifetime-dse=1. - The default behavior can be explicitly selected with
-flifetime-dse=2. -flifetime-dse=0is equivalent to-fno-lifetime-dse. ๐ง
- To keep stores before the constructor starts (say, because your
-flive-range-shrinkageโ tries to lower register pressure by shrinking register live ranges. It's a big help for fast processors with small or moderate-sized register sets ๐๏ธ-fira-algorithm=algorithmโ picks the coloring algorithm for the integrated register allocator. Thealgorithmargument can bepriority, which means Chow's priority coloring, orCB, which means Chaitin-Briggs coloring. Chaitin-Briggs 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โ tells the integrated register allocator which regions to use. Theregionargument should be one of these: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 the ones with small register pressure as 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โ uses IRA to evaluate register pressure in the code hoisting pass when deciding whether to hoist expressions. This usually results in smaller code, but it can slow the compiler down ๐ข- This option is enabled at level
-Osfor all targets.
- This option is enabled at level
-fira-loop-pressureโ uses IRA to evaluate register pressure in loops when deciding whether to move loop invariants. This usually generates faster and smaller code on machines with large register files (>= 32 registers), but it can slow the compiler down too ๐- This option is enabled at level
-O3for some targets. ๐
- This option is enabled at level
-fno-ira-share-save-slots
Okay so this one is about stack slots for saving call-used hard registers that stay alive across a call ๐ง. Turning it off with -fno-ira-share-save-slots means every hard register gets its very own stack slot, and bestie, that makes your function stack frames bigger ๐ฆ๐. Not the vibe, but sometimes you need it.
-fno-ira-share-spill-slots
Same energy, different target ๐ฆ. This one disables sharing of stack slots for pseudo-registers. Any pseudo-register that doesn't get a hard register is given a separate stack slot, so again, the function stack frames end up larger ๐ฅฒ.
-flra-remat
Okay this is giving optimization โจ. It enables CFG-sensitive rematerialization in LRA. Instead of loading the values of spilled pseudos, LRA tries to rematerialize (recalculate) them whenever that's profitable ๐งฎ๐ .
Enabled at levels -O2, -O3, -Os. ๐ธ
-fdelayed-branch
If the target machine supports it, GCC will try to reorder instructions so they fill the instruction slots available after delayed branch instructions ๐. Lowkey clever.
Enabled at levels -O, -O2, -O3, -Os, but not at -Og. ๐ซถ
-fschedule-insns
If the target supports it, GCC attempts to reorder instructions to avoid execution stalls caused by data that isn't ready yet โณ. This is a lifesaver for machines with slow floating point or memory load instructions, because other instructions can get issued while the load or float op is still cooking ๐ฅ.
Enabled at levels -O2, -O3. โจ
-fschedule-insns2
This is basically -fschedule-insns but with an extra scheduling pass after register allocation is done ๐. It's especially useful on machines with a pretty small number of registers, where memory loads take more than one cycle ๐.
Enabled at levels -O2, -O3, -Os. ๐
-fno-sched-interblock
Disables instruction scheduling across basic blocks ๐
โโ๏ธ. Normally this is on when scheduling happens before register allocation, meaning with -fschedule-insns or at -O2 or higher.
-fno-sched-spec
Disables speculative motion of non-load instructions ๐. Normally this is on when scheduling happens before register allocation, meaning with -fschedule-insns or at -O2 or higher.
-fsched-pressure
Enables register-pressure-sensitive insn scheduling before register allocation ๐. This only makes sense if pre-allocation scheduling is on, so with -fschedule-insns or at -O2 or higher. Using it can improve the generated code and shrink its size, because it stops register pressure from going above the number of available hard registers, which would otherwise lead to spills during allocation ๐ง .
-fsched-spec-load
Allows speculative motion of some load instructions ๐ท. Only makes sense when scheduling before register allocation, meaning with -fschedule-insns or at -O2 or higher.
-fsched-spec-load-dangerous
Allows speculative motion of more load instructions ๐ฌ. Same deal: only makes sense when scheduling before register allocation, meaning with -fschedule-insns or at -O2 or higher.
-fsched-stalled-insns -fsched-stalled-insns=n
This controls how many insns (if any) can be moved early from the queue of stalled insns into the ready list during the second scheduling pass ๐ฆ. -fno-sched-stalled-insns means none get moved early, and -fsched-stalled-insns=0 means there's no limit on how many queued insns can be moved early. Just -fsched-stalled-insns with no value is the same as -fsched-stalled-insns=1 ๐ฏ.
-fsched-stalled-insns-dep -fsched-stalled-insns-dep=n
This defines 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-insns is used. -fno-sched-stalled-insns-dep is the same as -fsched-stalled-insns-dep=0, and -fsched-stalled-insns-dep with no value is the same as -fsched-stalled-insns-dep=1 ๐.
-fsched2-use-superblocks
When scheduling after register allocation, this uses superblock scheduling ๐. That lets instructions move across basic block boundaries, which can give faster schedules โก. Heads up though: this option is experimental, because not all machine descriptions model the CPU closely enough to avoid unreliable results ๐.
This only makes sense when scheduling after register allocation, meaning with -fschedule-insns2 or at -O2 or higher.
-fsched-group-heuristic
Enables the group heuristic in the scheduler ๐ซง. This one favors the instruction that belongs to a schedule group. It's on by default when scheduling is enabled, meaning with -fschedule-insns or -fschedule-insns2 or at -O2 or higher ๐
.
-fsched-critical-path-heuristic
Enables the critical-path heuristic in the scheduler ๐ฃ๏ธ. This one favors instructions on the critical path. It's on by default when scheduling is enabled, meaning with -fschedule-insns or -fschedule-insns2 or at -O2 or higher ๐.
-fsched-spec-insn-heuristic
Enables the speculative instruction heuristic in the scheduler ๐ฎ. It favors speculative instructions with greater dependency weakness. On by default when scheduling is enabled, meaning with -fschedule-insns or -fschedule-insns2 or at -O2 or higher ๐ธ.
-fsched-rank-heuristic
Enables the rank heuristic in the scheduler ๐. It favors the instruction in a basic block with greater size or frequency. On by default when scheduling is enabled, meaning with -fschedule-insns or -fschedule-insns2 or at -O2 or higher ๐ฆ.
-fsched-last-insn-heuristic
Enables the last-instruction heuristic in the scheduler ๐ฏ. It favors the instruction that depends less on the last instruction scheduled. On by default when scheduling is enabled, meaning with -fschedule-insns or -fschedule-insns2 or at -O2 or higher โจ.
-fsched-dep-count-heuristic
Enables the dependent-count heuristic in the scheduler ๐ง. It favors the instruction that has more instructions depending on it. On by default when scheduling is enabled, meaning with -fschedule-insns or -fschedule-insns2 or at -O2 or higher ๐.
-freschedule-modulo-scheduled-loops
Modulo scheduling happens before traditional scheduling ๐. If a loop gets modulo scheduled, later scheduling passes may change its schedule, and this option is how you control that behavior ๐๏ธ.
-fselective-scheduling
Schedules instructions using the selective scheduling algorithm ๐งฉ. Selective scheduling runs instead of the first scheduler pass.
-fselective-scheduling2
Schedules instructions using the selective scheduling algorithm again ๐. This time it runs instead of the second scheduler pass.
-fsel-sched-pipelining
Enables software pipelining of innermost loops during selective scheduling ๐ฅ. This option has no effect unless -fselective-scheduling or -fselective-scheduling2 is turned on.
-fsel-sched-pipelining-outer-loops
When pipelining loops during selective scheduling, this also pipelines outer loops ๐. It has no effect unless -fsel-sched-pipelining is turned on.
-fsemantic-interposition
Okay this one is a whole saga ๐ญ. Some object formats, like ELF, let the dynamic linker interpose symbols. That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, because the function or variable might get swapped out later ๐ค. It's useful, for example, for 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 happens for functions, the overwriting function will have precisely the same semantics (and side effects). Similarly, if interposition happens for variables, the constructor of the variable will be the same. This flag has no effect on functions explicitly declared inline (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 need them, instead of at the top of the function ๐. This flag is enabled by default at -O and higher.
-fshrink-wrap-separate
Shrink-wraps the separate parts of the prologue and epilogue separately, so those parts only run when needed ๐ช. This option is on by default, but it has no effect unless -fshrink-wrap is also turned on and the target supports this.
-fcaller-saves
Enables allocating values to registers that get clobbered by function calls ๐งบ. GCC does this by emitting extra instructions to save and restore those registers around such calls. This allocation only happens when it seems to result in better code ๐ค.
This option is always enabled by default on certain machines, usually the ones that don't have call-preserved registers to use instead ๐ .
Enabled at levels -O2, -O3, -Os. ๐
-fcombine-stack-adjustments
Tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐ฅ.
Enabled by default at -O1 and higher. โจ
-fipa-ra
Uses caller-save registers for allocation if those registers aren't used by any called function ๐ง . In that case there's no need to save and restore them around calls. This only works if the called functions are part of the same compilation unit as the current function and get compiled before it ๐.
Enabled at levels -O2, -O3, -Os, but it's disabled if the generated code will be instrumented for profiling (-p or -pg), or if the callee's register usage can't be known exactly (which happens on targets that don't expose prologues and epilogues in RTL) ๐ซ.
-fconserve-stack
Attempts to minimize stack usage ๐ชถ. The compiler tries to use less stack space, even if that makes the program slower ๐ข. This option implies setting the large-stack-frame parameter to 100 and the large-stack-frame-growth parameter to 400 ๐.
-ftree-reassoc
Performs reassociation on trees ๐ณ. Enabled by default at -O and higher โจ.
-fcode-hoisting
Performs code hoisting ๐ช. Code hoisting tries to move the evaluation of expressions executed on all paths to the function exit as early as possible. This is especially useful as a code size optimization, but it often helps code speed too ๐๏ธ. This flag is enabled by default at -O2 and higher ๐.
-ftree-preโ okay so this one does partial redundancy elimination (PRE) on trees ๐ธ It's switched on by default at-O2and-O3โจ-ftree-partial-preโ this makes PRE way more aggressive ๐ฅ It's only on by default at-O3๐-ftree-forwpropโ forward propagation on trees, very clean-up-your-room energy ๐งน On by default at-Oand higher.-ftree-freโ full redundancy elimination (FRE) on trees ๐ The tea is that FRE only looks at expressions that get computed on all paths leading to the redundant computation. It's faster than PRE but catches fewer redundancies, so it's the chill sibling ๐ฆ On by default at-Oand higher.-ftree-phipropโ hoists loads from conditional pointers on trees ๐ This pass is on by default at-Oand higher.-fhoist-adjacent-loadsโ speculatively hoists loads from both branches of an if-then-else, but only when the loads come from adjacent spots in the same structure and the target architecture has a conditional move instruction ๐ซถ On by default at-O2and higher.-ftree-copy-propโ copy propagation on trees, which gets rid of unnecessary copy operations ๐งผ On by default at-Oand higher.-fipa-pure-constโ figures out which functions are pure or constant ๐ฎ On by default at-Oand higher.-fipa-referenceโ figures out which static variables don't escape the compilation unit ๐ On by default at-Oand higher.-fipa-reference-addressableโ finds read-only, write-only and non-addressable static variables ๐ฆ On by default at-Oand higher.-fipa-stack-alignmentโ reduces stack alignment on call sites whenever it's possible โจ On by default.-fipa-ptaโ interprocedural pointer analysis plus interprocedural modification and reference analysis ๐ง It's not enabled by default at any optimization level.
๐ Heads up bestie: -fipa-pta can cause excessive memory and compile-time usage on large compilation units, so it's not a casual add-on.
-fipa-profileโ interprocedural profile propagation ๐ Functions called only from cold functions get marked as cold, and functions executed once (such as "cold", "noreturn", static constructors or destructors) get identified. Cold functions and loop less parts of functions executed once then get optimized for size ๐ง On by default at-Oand higher.-fipa-modrefโ interprocedural mod/ref analysis ๐ It analyzes the side effects of functions (memory locations that are modified or referenced), which means better optimization across the function call boundary ๐ซง On by default at-Oand higher.-fipa-cpโ interprocedural constant propagation ๐ It checks when values passed to functions are constants, then optimizes accordingly. It can substantially increase performance if your app has constants passed to functions ๐ On by default at-O2,-Osand-O3. It's 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. Because this can create multiple copies of functions, it may significantly increase code size (see--param ipa-cp-unit-growth=value) ๐ On by default at-O3. It's also enabled by-fprofile-useand-fauto-profile.-fipa-bit-cpโ interprocedural bitwise constant propagation ๐ข On by default at-O2and by-fprofile-useand-fauto-profile. It requires that-fipa-cpis enabled.-fipa-vrpโ interprocedural propagation of value ranges ๐ On by default at-O2. It requires that-fipa-cpis enabled.-fipa-icfโ Identical Code Folding for functions and read-only variables ๐ช It reduces code size, but it may disturb unwind stacks by swapping a function out for an equivalent one with a different name. It works more effectively with link-time optimization turned on.- It's similar to the Gold Linker's ICF optimization, but GCC ICF works on different levels, so the optimizations aren't the same. There are equivalences only GCC finds, and equivalences only Gold finds ๐ค
- On by default at
-O2and-Os.
-flive-patching=levelโ tweaks GCC's optimizations so the output is suitable for live-patching ๐ฉน Quick vocab: if an optimization uses a function's body (or info pulled from that body) to optimize or change another function, that other one is called an impacted function of the first. If a function gets patched, its impacted functions should get patched too ๐- Which functions are impacted depends on the interprocedural optimizations. For example, a caller is impacted when a function gets inlined into it, when a function gets cloned and its caller is changed to call the new clone, or when a function's pureness/constness info gets extracted to optimize its direct or indirect callers, etc.
- Usually, the more IPA optimizations are enabled, the more impacted functions each function has. To keep that number under control and make the list easier to compute, IPA optimizations can be partially enabled at two different levels.
- The level argument should be one of the following:
inline-cloneโ only enables inlining and cloning optimizations, which covers inlining, cloning, interprocedural scalar replacement of aggregates and partial inlining ๐งฉ So when you patch a function, all its callers and its clones' callers are impacted and need patching too.-flive-patching=inline-clonedisables 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 ๐ฏ So when you patch a static function, all its callers are impacted and need patching too.- On top of everything
-flive-patching=inline-clonedisables,-flive-patching=inline-only-staticalso disables:-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp
- On top of everything
- When
-flive-patchingis specified without any value, the default value isinline-clone๐ - This flag is disabled by default.
- Note that
-flive-patchingis not supported with link-time optimization (-flto).
โ ๏ธ-flive-patchingand link-time optimization (-flto) don't get along, so this combo is a no-go.
-fisolate-erroneous-paths-dereferenceโ detects paths that trigger erroneous or undefined behavior due to dereferencing a null pointer ๐จ It isolates those paths from the main control flow and turns the statement with erroneous or undefined behavior into a trap. On by default at-O2and higher, and it depends on-fdelete-null-pointer-checksalso being enabled.-fisolate-erroneous-paths-attributeโ detects paths that trigger erroneous or undefined behavior because a null value gets used in a way forbidden by a"returns_nonnull"or"nonnull"attribute ๐ Same vibe as above: those paths get isolated from the main control flow and the statement becomes a trap. This is not currently enabled, but it may be enabled by-O2in the future ๐ฎ-ftree-sinkโ forward store motion on trees ๐๏ธ On by default at-Oand higher.-ftree-bit-ccpโ sparse conditional bit constant propagation on trees, and it propagates pointer alignment info too ๐งฎ It only operates on local scalar variables. On by default at-O1and higher, except for-Og. It requires that-ftree-ccpis enabled.-ftree-ccpโ sparse conditional constant propagation (CCP) on trees ๐ซ It only operates on local scalar variables. On by default at-Oand higher.-fssa-backpropโ propagates info about uses of a value up the definition chain so the definitions get simplified ๐ For example, this pass strips sign operations if the sign of a value never matters ๐งน On by default at-Oand higher.-fssa-phioptโ pattern matching on SSA PHI nodes to optimize conditional code ๐งฉ On by default at-O1and higher, except for-Og.-ftree-switch-conversionโ turns simple initializations in a switch into initializations from a scalar array ๐ On by default at-O2and higher.-ftree-tail-mergeโ looks for identical code sequences and, when it finds them, replaces one with a jump to the other ๐ช This is known as tail merging or cross jumping. On 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 ๐๏ธ On by default at-Oand higher.-ftree-builtin-call-dceโ conditional DCE for calls to built-in functions that may seterrnobut are otherwise free of side effects ๐ On by default at-O2and higher, if-Osisn't also specified.-ffinite-loopsโ assumes that a loop with an exit will eventually take the exit and won't loop indefinitely โพ๏ธ That lets the compiler remove loops that otherwise have no side effects, since it doesn't count eventual endless looping as such ๐ This option is enabled by default at-O2for C++ with-std=c++11or higher.-ftree-dominator-optsโ a bunch of simple scalar cleanups (constant/copy propagation, redundancy elimination, range propagation and expression simplification) based on a dominator tree traversal ๐งผ It also does jump threading (to reduce jumps to jumps) โ๏ธ On by default at-Oand higher.-ftree-dseโ Okay so this is dead store elimination (DSE) on trees ๐ A dead store is a store into a memory location that gets overwritten later by another store with no loads in between, so the earlier store can be deleted ๐๏ธ Enabled by default at-Oand higher โจ-ftree-chโ Loop header copying on trees ๐ฆ It's lowkey iconic because it boosts code motion optimizations and saves one jump. Enabled by default at-Oand higher, but not for-Os, since it usually bloats code size ๐-ftree-loop-optimizeโ Loop optimizations on trees ๐ธ Enabled by default at-Oand higher.-ftree-loop-linear,-floop-strip-mine,-floop-blockโ Loop nest optimizations ๐ง These are the same as-floop-nest-optimize. To actually use this transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure gets enabled. Don't skip that part, it's giving config drama ๐-fgraphite-identityโ Enables the identity transformation for Graphite ๐ For every SCoP, GCC builds the polyhedral representation and transforms it back to GIMPLE. This lets you check the costs or benefits of theGIMPLE -> GRAPHITE -> GIMPLEround trip. The isl code generator also does some minimal optimizations, like index splitting and dead code elimination in loops.-floop-nest-optimizeโ Enables the isl-based loop nest optimizer ๐ It's a generic one based on the Pluto optimization algorithms, and it calculates a loop structure optimized for data locality and parallelism.
โ ๏ธ Heads up bestie: this option is experimental, so use it with care ๐ซถ
-floop-parallelize-allโ Uses Graphite data dependence analysis to find loops that can be parallelized ๐งต It parallelizes every loop that can be analyzed as not containing loop carried dependences, without checking whether parallelizing is profitable first.-ftree-coalesce-varsโ When transforming the program out of SSA representation, this tries to cut down copying by coalescing versions of different user-defined variables, not just compiler temporaries ๐
๐ This may severely limit your ability to debug an optimized program compiled with -fno-var-tracking-assignments. The negated form of 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 vibe is to remove control flow from the innermost loops so the vectorization pass can handle them better. Enabled by default if vectorization is enabled.-ftree-loop-distributionโ Performs loop distribution ๐ This can improve cache performance on big loop bodies and lets further loop optimizations, like parallelization or vectorization, take place. For example, the 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โ Distributes loops over 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, the 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 can improve cache performance on loop nests and allow further loop optimizations, like vectorization, to take place. For example, the 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. Enabled by default at-O3. It is also enabled by-fprofile-useand-fauto-profile.-ftree-loop-imโ Performs loop invariant motion on trees ๐ It 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 that out takes 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 on exit can be determined using only its initial value and the number of loop iterations, uses of the final value get replaced by that computation, as long as it's sufficiently cheap. This reduces data dependencies and may allow further simplifications. Enabled by default at-Oand higher.-fivoptsโ Performs induction variable optimizations on trees ๐ That includes strength reduction, induction variable merging, and induction variable elimination.-ftree-parallelize-loops=nโ Parallelizes loops by splitting their iteration space to run innthreads ๐งต This is only possible for loops whose iterations are independent and can be arbitrarily reordered. The optimization is only profitable on multiprocessor machines, for CPU-intensive loops rather than loops constrained by, e.g., 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 ๐ฏ Enabled by default at-O1and higher, except for-Og.-ftree-sraโ Performs scalar replacement of aggregates ๐งธ It replaces structure references with scalars so structures don't get committed to memory too early. Enabled by default at-O1and higher, except for-Og.-fstore-mergingโ Merges narrow stores to consecutive memory addresses ๐ฆ It merges contiguous stores of immediate values that are narrower than a word into fewer, wider stores to reduce the number of instructions. Enabled by default at-O2and higher, as well as-Os.-ftree-terโ Performs temporary expression replacement during the SSA->normal phase ๐ช Single use/single def temporaries are replaced at their use location with their defining expression. This results in non-GIMPLE code, but gives the expanders much more complex trees to work on, which means better RTL generation. Enabled by default at-Oand 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. Enabled by default at-Oand 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 ๐ช Enabled by default at-O3, and by-ftree-vectorize,-fprofile-use, and-fauto-profile.-ftree-slp-vectorizeโ Performs basic block vectorization on trees โจ Enabled by default at-O3, and by-ftree-vectorize,-fprofile-use, and-fauto-profile.-fvect-cost-model=modelโ Alters the cost model used for vectorization ๐ฐ The model argument should be one of the following:unlimitedโ the vectorized code path is assumed to be profitable.dynamicโ a runtime check guards the vectorized code path, so it only runs for iteration counts that will likely execute faster than the original scalar loop.cheapโ disables vectorization of loops where doing so would be cost prohibitive, for example due to required runtime checks for data dependence or alignment. Otherwise it's equal todynamic.very-cheapโ only allows vectorization if the vector code would entirely replace the scalar code being vectorized. For example, if each iteration of a vectorized loop could only handle exactly four iterations of the scalar loop,very-cheapwould only allow vectorization if the scalar iteration count is known to be a multiple of four.
The default cost model depends on other optimization flags and is either dynamic or cheap ๐ท
-fsimd-cost-model=modelโ Alters the cost model used for vectorization of loops marked with the OpenMP simd directive ๐ The model argument should be one ofunlimited,dynamic,cheap. All values of model have the same meaning as described in-fvect-cost-model, and by default a cost model defined with-fvect-cost-modelis used ๐
โจ OPTIONS โจ (continued, bestie ๐)
-ftree-vrp๐ธ โ okay so this one runs Value Range Propagation on trees ๐ณ. It's basically the cousin of constant propagation, except it tracks whole ranges of values instead of single values ๐. That means the optimizers can ditch pointless checks like array bound checks and null pointer checks, which is giving efficiency ๐ฅ.- It's enabled by default at
-O2and higher. - Null pointer check elimination only happens if
-fdelete-null-pointer-checksis enabled ๐.
- It's enabled by default at
-fsplit-paths๐ฆ โ splits up paths that lead to loop backedges โฉ๏ธ. This can seriously help dead code elimination and common subexpression elimination ๐งน.- Enabled by default at
-O3and above.
- Enabled by default at
-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 makes the scheduling passes more efficient ๐.- A combo of
-fweband CSE is often enough to get the same effect, ngl ๐คทโโ๏ธ. It isn't reliable though when the loop body is more complicated than a single basic block ๐. - It doesn't work at all on some architectures because of restrictions in the CSE pass ๐.
- This optimization is enabled by default โจ.
- A combo of
-fvariable-expansion-in-unroller๐ โ when unrolling a loop, the compiler makes multiple copies of some local variables, which can result in superior code ๐.- It's enabled by default for PowerPC targets, but disabled by default otherwise ๐.
-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.
- Enabled at levels
-fpredictive-commoning๐ โ does 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.
- Enabled at level
-fprefetch-loop-arrays๐โโ๏ธ โ if the target machine supports it, GCC generates instructions to prefetch memory, which speeds up loops that access large arrays ๐ฆ.- This might give better or worse code ๐ฒ. The results are highly dependent on how the loops are structured in the source โจ.
- Disabled at level
-Os.
-fno-printf-return-value๐ฎ โ tells GCC not to swap in constants for the known return value of formatted output functions like"sprintf","snprintf","vsprintf", and"vsnprintf"(but not"printf"or"fprintf"). The transformation itself lets GCC optimize or even eliminate branches based on that known return value, as long as the arguments are constant or known to be in a range where the exact return value can be figured out ๐ง .
For example, with -fprintf-return-value in effect, both the branch and the body of the "if" statement (but not the call to "snprint") can be optimized away when "i" is a 32-bit or smaller integer, because the return value is guaranteed to be at most 8 ๐คฏ:
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations and gives the best results with -O2 and above ๐. It works in tandem with -Wformat-overflow and -Wformat-truncation ๐ซถ. The -fprintf-return-value option is enabled by default โ
.
-fno-peephole,-fno-peephole2๐งผ โ disables any machine-specific peephole optimizations. The difference between them is in how they're implemented inside the compiler: some targets use one, some use the other, and a few use both ๐ค.-fpeepholeis enabled by default.-fpeephole2is enabled at levels-O2,-O3,-Os.
-fno-guess-branch-probability๐ฏ โ stops GCC from guessing branch probabilities using heuristics ๐ โโ๏ธ.- GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (
-fprofile-arcs) ๐. These heuristics are based on the control flow graph ๐บ๏ธ. - If some branch probabilities are specified by
"__builtin_expect", the heuristics guess the probabilities for the rest of the control flow graph, taking the"__builtin_expect"info into account ๐งฉ. The interactions between the two can get complicated, so sometimes it's useful to disable the heuristics so the effects of"__builtin_expect"are easier to understand ๐ซถ. - You can also specify the expected probability of an expression with the
"__builtin_expect_with_probability"built-in function โจ. - The default is
-fguess-branch-probabilityat levels-O,-O2,-O3,-Os.
- GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (
-freorder-blocks๐ค๏ธ โ reorders basic blocks in the compiled function to reduce the number of taken branches and improve code locality ๐ .- Enabled at levels
-O,-O2,-O3,-Os.
- Enabled at levels
-freorder-blocks-algorithm=algorithm๐งญ โ picks the algorithm used for basic block reordering. Thealgorithmargument can be:simple, which doesn't increase code size (except sometimes through secondary effects like alignment) ๐ชถstc, the "software trace cache" algorithm, which tries to put all the often-executed code together, minimizing the number of branches executed by making extra copies of code ๐ง- The default is
simpleat levels-O,-Os, andstcat levels-O2,-O3.
-freorder-blocks-and-partition๐งฉ โ on top of reordering basic blocks to cut down on taken branches, this partitions hot and cold basic blocks into separate sections of the assembly and.ofiles ๐๏ธ. That improves paging and cache locality performance ๐.- 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 does not support named sections ๐ โโ๏ธ.
- When
-fsplit-stackis used, this option is not 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 ๐. It does this with special subsections:".text.hot"for the most frequently executed functions and".text.unlikely"for the unlikely-executed ones ๐ฅ. The reordering is done by the linker, so the object file format must support named sections and the linker must place them in a reasonable way ๐.- This option isn't effective unless you either provide profile feedback (see
-fprofile-arcsfor details) or manually annotate functions with"hot"or"cold"attributes ๐ญ. - Enabled at levels
-O2,-O3,-Os.
- This option isn't effective unless you either provide profile feedback (see
-fstrict-aliasing๐ต๏ธโโ๏ธ โ lets the compiler assume the strictest aliasing rules that apply to the language being compiled. For C (and C++), this activates optimizations based on the type of expressions ๐ง. An object of one type is assumed to never reside at the same address as an object of a different type, unless the types are almost the same. For example, an"unsigned int"can alias an"int", but not a"void*"or a"double"๐ . A character type may alias any other type ๐.
Pay special attention to code like this ๐:
union a_union {
int i;
double d;
};
int f() {
union a_union t;
t.d = 3.0;
return t.i;
}
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, accessing by taking the address, casting the resulting pointer, and dereferencing the result has undefined behavior, even if the cast uses a union type ๐จ:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
Undefined behavior alert ๐จ๐: the address-casting trick above is undefined behavior, so please don't build your code on it, bestie.
The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os ๐ซถ.
-falign-functions,-falign-functions=n,-falign-functions=n:m,-falign-functions=n:m:n2,-falign-functions=n:m:n2:m2๐ โ aligns the start of functions to the next power-of-two that's greater than or equal ton, skipping up tom-1bytes. This makes sure at least the firstmbytes of the function can be fetched by the CPU without crossing ann-byte alignment boundary ๐งฒ.- If
misn't specified, it defaults ton๐. - Examples ๐:
-falign-functions=32aligns functions to the next 32-byte boundary.-falign-functions=24aligns to the next 32-byte boundary only if this can be done by skipping 23 bytes or less.-falign-functions=32:7aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less.
- The second pair of
n2:m2values lets you specify a secondary alignment ๐ฏ. For example,-falign-functions=64:7:32:3aligns to the next 64-byte boundary if this can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if this can be done by skipping 2 bytes or less. Ifm2isn't specified, it defaults ton2. - Some assemblers only support this flag when
nis a power of two. In that case, it gets rounded up ๐งฎ. -fno-align-functionsand-falign-functions=1are equivalent and mean that functions are not aligned ๐ .- If
nis not specified or is zero, a machine-dependent default is used. The maximum allowednvalue is65536๐. - Enabled at levels
-O2,-O3๐ฅ.
- If
-flimit-function-alignment๐ท โ when this is enabled, the compiler tries to avoid unnecessarily overaligning functions ๐ โโ๏ธ. It attempts to instruct the assembler to align by the amount specified by-falign-functions, but not to skip more bytes than the size of the function ๐.-falign-labels,-falign-labels=n,-falign-labels=n:m,-falign-labels=n:m:n2,-falign-labels=n:m:n2:m2๐ฏ โ aligns all branch targets to a power-of-two boundary ๐.
Okay so these parameters work just like the ones for -falign-functions ๐
. And bestie, -fno-align-labels and -falign-labels=1 are literally the same thing: labels get no alignment at all ๐
If -falign-loops or -falign-jumps apply and their values are bigger than this one, their values win instead โจ
If you don't give an n or it's zero, GCC picks a machine-dependent default, which is very likely 1 (aka no alignment, lol) ๐. The max n you can use is 65536 ๐ฅ
Enabled at levels -O2, -O3 ๐ธ
-falign-loops
-falign-loops
-falign-loops=n
-falign-loops=n:m
-falign-loops=n:m:n2
-falign-loops=n:m:n2:m2
Okay this one is giving alignment for loops to a power-of-two boundary ๐ฆ. If the loops run a lot of times, the padding instructions are totally worth it, since they only run once per loop entry and the speedup makes up for it ๐ฅ
If -falign-labels is bigger than this value, its value gets used instead ๐
The parameters work the same way as -falign-functions. -fno-align-loops and -falign-loops=1 are equivalent and mean loops are not aligned ๐ซถ. The max n is 65536 โจ
If n isn't specified or is zero, you get a machine-dependent default ๐ง
Enabled at levels -O2, -O3 ๐
-falign-jumps
-falign-jumps
-falign-jumps=n
-falign-jumps=n:m
-falign-jumps=n:m:n2
-falign-jumps=n:m:n2:m2
This one aligns branch targets to a power-of-two boundary, but only for the targets you can only reach by jumping ๐ฆ. Since you're jumping there anyway, no dummy operations need to run, so it's extra iconic ๐
If -falign-labels is bigger than this value, its value gets used instead ๐
Parameters work like -falign-functions again ๐. -fno-align-jumps and -falign-jumps=1 are equivalent and mean that loops are not aligned ๐
If n isn't specified or is zero, you get the machine-dependent default. The max n is 65536 ๐ธ
Enabled at levels -O2, -O3 โจ
-fno-allocation-dce
Do not remove unused C++ allocations during dead code elimination. The compiler keeps them around, no cap ๐ซถ
-fallow-store-data-races
Okay this one is kinda spicy ๐ถ๏ธ. 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 affect optimization of local data, though ๐
Examples of the optimizations this enables include hoisting or if-conversions that might cause a value already in memory to get re-written with that same value. That re-writing is safe in a single-threaded context but may be unsafe in a multi-threaded one ๐. Also, on some processors, if-conversions may be required to enable vectorization ๐ฅ
Bestie, it's only safe to use this if you know global data won't be accessed by multiple threads. Otherwise, it's a whole mess ๐จ
Enabled at level -Ofast ๐
-funit-at-a-time
This one is only still here for compatibility reasons, so it has no effect ๐ฅน. -fno-unit-at-a-time does have effects though: it implies -fno-toplevel-reorder and -fno-section-anchors ๐ฆ
Enabled by default โจ
-fno-toplevel-reorder
Do not reorder top-level functions, variables, and "asm" statements. They get output in the same order they appear in the input file ๐. When you use this option, unreferenced static variables are not removed ๐ฌ
This option exists to support existing code that relies on a particular ordering. For new code, it's better to use attributes when possible ๐
-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested ๐ง. Also, -fno-toplevel-reorder implies -fno-section-anchors ๐
-fweb
This one constructs webs, which are commonly used for register allocation purposes, and assigns each web its own individual pseudo register ๐ธ๏ธ. The register allocation pass can then operate on pseudos directly, and it also strengthens several other optimization passes, like CSE, the loop optimizer, and the trivial dead code remover ๐ฅ
Heads up though: it can make debugging impossible, since variables no longer stay in a "home register" ๐
Enabled by default with -funroll-loops ๐ธ
-fwhole-program
Okay so this tells the compiler to assume the current compilation unit is the whole program being compiled ๐. All public functions and variables become static functions, except for "main" and anything merged by the attribute "externally_visible". Because of that, the interprocedural optimizers can go way harder on them โจ
Don't use this with -flto. Relying on a linker plugin should give you safer and more precise info instead ๐ซถ
-flto[=n]
Main character of the whole page, fr fr ๐. This runs the standard link-time optimizer. When you invoke it with source code, it generates GIMPLE (one of GCC's internal representations) and writes it into special ELF sections in the object file ๐ง. When the object files get linked together, all the function bodies are read from those ELF sections and instantiated as if they were part of the same translation unit ๐ฆ
To use the link-time optimizer, -flto and optimization options should be specified at compile time and during the final link ๐. It's recommended that you compile all the files in the same link with the same options, and also specify those options at link time. For example:
gcc -c -O2 -flto foo.c
gcc -c -O2 -flto bar.c
gcc -o myprog -flto -O2 foo.o bar.o
The first two invocations save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o ๐. The final invocation reads 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 files are merged, all the interprocedural analyses and optimizations work across the two files like they're one single file ๐ซถ. So 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 -flto. You can always override that automatic decision by passing -fno-lto to the link command ๐
To make whole program optimization effective, you have to make certain whole program assumptions ๐ง. The compiler needs to know which functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes info to the compiler about used and externally visible symbols ๐
. When the linker plugin isn't available, use -fwhole-program so the compiler can make these assumptions, which leads to more aggressive optimization decisions ๐ฅ
When a file is compiled with -flto without -fuse-linker-plugin, the object file is bigger than a regular one ๐ฆ. That's because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). Objects with LTO info can still be linked as normal object files. If you pass -fno-lto to the linker, no interprocedural optimizations are applied ๐. Also, if you enable -fno-fat-lto-objects, the compile stage is faster, but you cannot perform a regular, non-LTO link on them ๐ฌ
When producing the final binary, GCC only applies link-time optimizations to the files that contain bytecode ๐ฆ. So you can mix and match object files and libraries with GIMPLE bytecodes and final object code. GCC automatically picks which files to optimize in LTO mode and which to link without further processing ๐
Generally, options specified at link time override the ones specified at compile time ๐, although in some cases GCC tries to infer link-time options from the settings used to compile the input files ๐ง
If you don't specify an optimization level option -O at link time, GCC uses the highest optimization level used when compiling the object files ๐. Specifying an optimization level only at link time and not at compile time is generally ineffective, and there are two reasons why ๐. First, compiling without optimization suppresses the compiler passes that gather info needed for effective optimization at link time. Second, some early optimization passes can only be performed at compile time, not at link time ๐
There are some code generation flags that GCC preserves when generating bytecodes, since they need to be used during the final link โจ. Right now, the following options and their settings are taken from the first object file that explicitly specifies them: -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm, and all the -m target flags ๐
The options -fPIC, -fpic, -fpie and -fPIE are combined based on this scheme ๐ซถ:
-fPIC + -fpic = -fpic
-fPIC + -fno-pic = -fno-pic
-fpic/-fPIC + (no option) = (no option)
-fPIC + -fPIE = -fPIE
-fpic + -fPIE = -fpie
-fPIC/-fpic + -fpie = -fpie
Certain ABI-changing flags have to match in all compilation units. 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, are passed through to the link stage and merged conservatively for conflicting translation units ๐ฆ. Specifically, -fno-strict-overflow, -fwrapv and -fno-trapv take precedence, and for example -ffp-contract=off takes precedence over -ffp-contract=fast ๐
. You can override them at link time โจ
Okay bestie, so diagnostic options like -Wstringop-overflow get passed right through to the link stage ๐
and their setting lines up with the compile step at function granularity ๐ง. ngl this only matters for diagnostics that pop up during optimization โจ. Also, code transforms like inlining can make warnings switch on or off for regions of code that don't match the setting from compile time ๐ lowkey chaotic ๐.
When you need to pass stuff to the assembler through -Wa or -Xassembler ๐, either compile those translation units with -fno-lto, or use the exact same assembler options on every translation unit ๐ซถ. You can also specify assembler options at LTO link time instead ๐ฆ.
To get debug info you need -g at compile time ๐ธ. If any input files at link time were built with debug info, the link turns debug info on too ๐. Fancy debug settings like the dwarf level -gdwarf-5 have to be repeated explicitly on the linker command line ๐ญ, and mixing different settings across translation units is discouraged ๐.
If LTO runs into objects with C linkage declared with incompatible types across separate translation units being linked together (undefined behavior according to ISO C99 6.2.7) ๐ฌ, it may issue a non-fatal diagnostic ๐จ. The behavior is still undefined at run time, so that's still a whole mess ๐. Similar diagnostics may be raised for other languages too.
Another LTO feature is that you can apply interprocedural optimizations to files written in different languages ๐
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice the final link is done with g++ to get the C++ runtime libraries, and -lgfortran gets added for the Fortran runtime libraries ๐. In general, when mixing languages in LTO mode, use the same link command options you'd use when mixing languages in a regular (non-LTO) compilation ๐
.
If object files containing GIMPLE bytecode are stored in a library archive, say libfoo.a, you can extract and use them in an LTO link as long as you're using a linker with plugin support ๐ฆ. To 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 -fuse-linker-plugin so the library joins the LTO optimization process ๐
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin enabled, the linker pulls the needed GIMPLE files out of libfoo.a and hands them to the running GCC to become part of the aggregated GIMPLE image that gets optimized ๐ซถ.
If you aren't 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 need the whole program to be present ๐ธ. If the program doesn't require any symbols to be exported, you can combine -flto and -fwhole-program so the interprocedural optimizers can use more aggressive assumptions, which may lead to better optimization opportunities โญ. You don't need -fwhole-program 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 won't work with an older or newer version of GCC ๐.
Link-time optimization doesn't work well with debug info generation on systems other than those using a combination of ELF and DWARF ๐ญ.
If you specify the optional n, the optimization and code generation done at link time runs in parallel using n parallel jobs by utilizing an installed make program ๐ฅ. The environment variable MAKE can be used to override which program gets used ๐
.
You can also specify -flto=jobserver to use GNU make's job server mode to determine the number of parallel jobs ๐ง. This is super useful when the Makefile calling GCC is already running 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 it's available, or otherwise fall back to autodetecting the number of CPU threads in your system ๐.
-flto-partition=algโ Picks the partitioning algorithm the link-time optimizer uses ๐งฉ. Your choices are:1to1โ partitions mirror the original source files ๐ this can be used as a workaround for various code ordering issues ๐ฉนbalancedโ partitions into equally sized chunks (whenever possible) โ๏ธ this is the default ๐maxโ creates a new partition for every symbol where possible ๐งช this one is intended for internal testing only ๐noneโ disables partitioning and streaming completely ๐ซoneโ uses exactly one partition 1๏ธโฃ
Heads up:nonebypasses partitioning and runs the link-time optimization step directly from the WPA phase, which is different fromone๐
-flto-compression-level=nโ Sets the compression level for the intermediate language written to LTO object files ๐๏ธ this only means something when you're in LTO mode (-flto). GCC currently supports two LTO compression algorithms. Forzstd, valid values are0(no compression) to19(maximum compression), whilezlibsupports values from0to9๐. Values outside the range get clamped to the minimum or maximum of the supported values. If you don't give the option, a default balanced compression setting is used โจ.-fuse-linker-pluginโ Turns on the linker plugin during link-time optimization ๐. This relies on plugin support in the linker, which is available ingoldor in GNU ld 2.21 or newer ๐ฆ. It lets GCC pull object files with GIMPLE bytecode out of library archives, which improves optimization by exposing more code to the link-time optimizer ๐ฅ. The plugin info also says which symbols can be accessed externally (by a non-LTO object or during dynamic linking) ๐ธ. The code quality gains on binaries (and shared libraries that use hidden visibility) are similar to-fwhole-program๐. See-fltofor a description of what this flag does and how to use it.
This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker that supports plugins (GNU ld 2.21 or newer, or gold) ๐.
-ffat-lto-objectsโ Fat LTO objects are object files that contain both the intermediate language and the object code ๐ฐ. That makes them usable for both LTO linking and normal linking ๐ . This option only takes effect when you're compiling with-flto, and it's ignored at link time ๐.-fno-fat-lto-objectsโ This one improves compilation time over plain LTO, but it requires the complete toolchain to be aware of LTO ๐งฐ. It needs a linker with linker plugin support for basic functionality ๐. Also,nm,arandranlibneed to support linker plugins to allow a full-featured build environment (capable of building static libraries and so on) ๐. 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-plugins has the same effect as using the command wrappers (gcc-ar, gcc-nm and gcc-ranlib) โจ.
The default is -fno-fat-lto-objects on targets with linker plugin support ๐.
-fcompare-elimโ After register allocation and post-register-allocation instruction splitting, this finds arithmetic instructions that compute processor flags similar to a comparison operation based on that arithmetic ๐. If possible, it eliminates the explicit comparison operation ๐๏ธ. This pass only applies to certain targets that can't explicitly represent the comparison operation before register allocation is complete ๐ฏ. Turned on at-O,-O2,-O3, and-Os๐ .-fcprop-registersโ After register allocation and post-register-allocation instruction splitting, this runs a copy-propagation pass to try to reduce scheduling dependencies and occasionally eliminate the copy ๐. Turned on at-O,-O2,-O3, and-Os๐.-fprofile-correctionโ Profiles collected from an instrumented binary for multi-threaded programs can be inconsistent because of missed counter updates ๐งต. With this option, GCC uses heuristics to correct or smooth out those inconsistencies ๐ฉน. By default, GCC emits an error message when an inconsistent profile is detected ๐จ. This option is enabled by-fauto-profileโจ.-fprofile-partial-trainingโ With-fprofile-use, all the portions of your program that weren't executed during the train run get optimized aggressively for size rather than speed ๐. Sometimes it isn't practical to train every possible hot path in the program. For example, a program might contain functions specific to a given hardware setup, and training might not cover every hardware configuration the program runs on ๐ฅ๏ธ. With-fprofile-partial-training, profile feedback gets ignored for all functions not executed during the train run, so they're optimized as if they were compiled without profile feedback ๐ง . This leads to better performance when the train run isn't representative, but it also leads to significantly bigger code ๐ฆ.-fprofile-use,-fprofile-use=pathโ Enables profile feedback-directed optimizations, and the following optimizations, many of which are generally only profitable with profile feedback available ๐ฎ
Bestie, here's the rest of the -fprofile-use squad ๐
โจ
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Okay so, the big catch ๐: before you can use this option, you must generate profiling information first. No shortcuts, no cap.
By default, GCC throws an error if the feedback profiles don't match your source code ๐ญ. If you want that error to be a warning instead, use -Wno-error=coverage-mismatch. Just know this might give you poorly optimized code, so be careful ๐ฅบ. Also by default, GCC gives you a warning if the feedback profiles don't exist at all (see -Wmissing-profile) ๐ธ.
If you give it a path, GCC goes looking there for the profile feedback data files. See -fprofile-dir ๐๏ธ.
-fauto-profile,-fauto-profile=pathโ Okay this one is giving sampling-based feedback-directed optimizations ๐ฆ. It turns on these optimizations too, and a lot 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-correction
path is the name of a file holding your AutoFDO profile info ๐. If you skip it, it defaults to fbdata.afdo in the current directory, no stress ๐.
Making an AutoFDO profile file means you have to run your program with the perf utility on a supported GNU/Linux target system ๐ง. For more deets, check out https://perf.wiki.kernel.org/ ๐.
Here's an example, E.g.:
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Then you use the create_gcov tool to convert that raw profile data into a format GCC can actually read โจ. You also have to hand it the unstripped binary for your program, so don't forget that part ๐ซถ. See https://github.com/google/autofdo ๐.
Here's the example, E.g.:
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
Okay, next up is the floating-point crew ๐ง. These options control how the compiler handles floating-point math, and they're basically a speed-versus-correctness trade-off ๐ . You have to turn every single one of them on yourself, nothing happens automatically, periodt ๐.
-ffloat-storeโ This one tells the compiler to not keep floating-point variables in registers, and to block any other options that might change whether a floating-point value comes from a register or from memory ๐ง. It stops the "excess precision" drama on machines like the 68000, where the floating registers (of the 68881) hold more precision than a "double" is supposed to have ๐ค. The x86 architecture has the same issue. For most programs, that extra precision is only a good thing ๐, but a few programs depend on the exact definition of IEEE floating point. For those programs, use-ffloat-storeafter you've changed them to store all the important intermediate computations into variables ๐ซถ.-fexcess-precision=styleโ This option gives you more control over excess precision on machines where floating-point operations happen in a format with more precision or range than IEEE standard and interchange floating-point types ๐ฆ. By default,-fexcess-precision=fastis in effect, which means operations can happen in a wider precision than the types in your source code if that makes the code faster, and it's unpredictable when the rounding to your source types actually happens ๐ช๏ธ. When you're compiling C and you specify-fexcess-precision=standard, excess precision follows the rules in ISO C99. In particular, both casts and assignments get rounded to their semantic types, whereas-ffloat-storeonly touches assignments ๐ . This option is turned on by default for C if a strict conformance option like-std=c99is used.-ffast-mathturns on-fexcess-precision=fastby default no matter whether a strict conformance option is used ๐๏ธ.
-fexcess-precision=standard isn't implemented for languages other than C ๐
โโ๏ธ. On x86, it does nothing if you've specified -mfpmath=sse or -mfpmath=sse+387. With the former, IEEE semantics apply with no excess precision, and with the latter, rounding is unpredictable ๐ฅด.
-ffast-mathโ This sets-fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans,-fcx-limited-rangeand-fexcess-precision=fastall at once ๐๏ธ๐จ. It also causes the preprocessor macro"__FAST_MATH__"to get defined ๐. This option is not turned on by any -O option besides -Ofast, because it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions ๐. It might, however, give you faster code for programs that don't need the guarantees of those specs โจ.-fno-math-errnoโ Basically, don't set"errno"after calling math functions that run with 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, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It might, however, give faster code for programs that don't need those guarantees ๐ . The default is-fmath-errno.
Fun Darwin detail ๐: on Darwin systems, the math library never sets "errno". So there's no reason for the compiler to consider that it might, and -fno-math-errno is the default there ๐.
-funsafe-math-optimizationsโ This allows optimizations for floating-point arithmetic that (a) assume arguments and results are valid and (b) may violate IEEE or ANSI standards ๐ฌ. When it's used at link time, it may include libraries or startup files that change the default FPU control word or do other similar optimizations ๐ง. This option is not turned on by any -O option, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It might, however, give faster code for programs that don't need those guarantees ๐. It enables-fno-signed-zeros,-fno-trapping-math,-fassociative-mathand-freciprocal-math๐ซถ. The default is-fno-unsafe-math-optimizations.-fassociative-mathโ This allows re-association of operands in series of floating-point operations ๐. Heads up, it violates the ISO C and C++ language standards by possibly changing the computation result ๐ญ. NOTE: re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. That means it can't be used on code that relies on rounding behavior like"(x + 2**52) - 2**52". It may also reorder floating-point comparisons, so don't use it when ordered comparisons are required ๐ โโ๏ธ. This option requires that both-fno-signed-zerosand-fno-trapping-mathbe in effect. Also, it doesn't make much sense with-frounding-math. For Fortran, the option is automatically enabled when both-fno-signed-zerosand-fno-trapping-mathare in effect ๐. The default is-fno-associative-math.-freciprocal-mathโ This lets the reciprocal of a value get used instead of dividing by the value, if that enables optimizations โ. For example,"x / y"can be replaced with"x * (1/y)", which is handy if"(1/y)"is subject to common subexpression elimination ๐งฎ. Just know that 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 arguments and results are not NaNs or +-Infs ๐. This option is not turned on by any -O option, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It might, however, give faster code for programs that don't need those guarantees โจ. The default is-fno-finite-math-only.-fno-signed-zerosโ This allows optimizations for floating-point arithmetic that ignore the signedness of zero ๐ง. IEEE arithmetic specifies how distinct+0.0and-0.0values behave, which then stops you from simplifying expressions likex+0.0or0.0*x(even with-ffinite-math-only) ๐ซ. This option means the sign of a zero result isn't significant ๐ . The default is-fsigned-zeros.-fno-trapping-mathโ This tells the compiler to assume floating-point operations can't generate user-visible traps ๐ชค. Those traps include division by zero, overflow, underflow, inexact result and invalid operation โ ๏ธ. This option requires that-fno-signaling-nansbe in effect. Turning it on might allow faster code if you rely on "non-stop" IEEE arithmetic, for example ๐โโ๏ธ.
This option should never be turned on by any -O option, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. Don't let it sneak in on you ๐.
The default is -ftrapping-math.
-frounding-mathโ This disables transformations and optimizations that assume the default floating-point rounding behavior ๐ฒ. That default is round-to-zero for all floating-point-to-integer conversions, and round-to-nearest for all other arithmetic truncations. You should specify this for programs that change the FP rounding mode dynamically, or that may get executed with a non-default rounding mode ๐. It also disables constant folding of floating-point expressions at compile time (since that can be affected by rounding mode), along with arithmetic transformations that are unsafe with sign-dependent rounding modes ๐ง . The default is-fno-rounding-math.
This option is experimental, and it doesn't currently guarantee to disable all GCC optimizations that are affected by rounding mode ๐งช. Future versions of GCC may give finer control over this setting using C99's"FENV_ACCESS"pragma. This command-line option will be used to specify the default state for"FENV_ACCESS"๐ธ.
-fsignaling-nans: okay so this one tells GCC to assume IEEE signaling NaNs can cause user-visible traps during floating-point ops ๐ซ. Turning it on disables optimizations that could change how many exceptions show up with signaling NaNs. It implies-ftrapping-math.- Enabling it also defines the preprocessor macro
"__SUPPORT_SNAN__"๐. - The default is
-fno-signaling-nans๐ธ. - > This one is experimental, and it doesn't currently guarantee that every GCC optimization affecting signaling NaN behavior gets disabled ๐.
- Enabling it also defines the preprocessor macro
-fno-fp-int-builtin-inexact: this stops the built-in functionsceil,floor,roundandtrunc(plus theirfloatandlong doubleversions) from generating code that raises theinexactfloating-point exception for noninteger arguments ๐ฆ. ISO C99 and C11 let these functions raiseinexact, but ISO/IEC TS 18661-1:2014 (the C bindings to IEEE 754-2008, as folded into ISO C2X) doesn't, so this flag keeps you on the TS 18661 side ๐.- The default is
-ffp-int-builtin-inexact, which allows the exception to be raised, unless C2X or a later C standard is selected โจ. - This option does nothing unless
-ftrapping-mathis in effect ๐ . - Even with
-fno-fp-int-builtin-inexact, if the functions end up calling a library function,inexactmay still be raised if that library doesn't follow TS 18661 ๐ญ.
- The default is
-fsingle-precision-constant: floating-point constants get treated as single precision instead of being quietly converted to double-precision constants ๐.-fcx-limited-range: when this is on, GCC assumes no range reduction step is needed for complex division ๐ง. It also skips checking whether a complex multiplication or division result isNaN + I*NaNand trying to rescue that situation ๐. The default is-fno-cx-limited-range, but-ffast-mathturns it on ๐ฅ.- This option controls the default setting of the ISO C99
CX_LIMITED_RANGEpragma ๐. - It applies to all languages, not just C ๐ซถ.
- 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 for aNaN + I*NaNresult or any rescue attempt ๐.- The default is
-fno-cx-fortran-rulesโญ.
- The default is
The next group is all about optimizations that can boost performance but aren't switched on by any -O level ๐ฆ. Heads up, bestie: this section also has experimental options that might produce broken code ๐.
-fbranch-probabilities: this is the second act of profiling ๐ฎ. After you run a program built with-fprofile-arcs, you compile it again with-fbranch-probabilitiesso the optimizer can use how often each branch was actually taken ๐. When a-fprofile-arcsprogram exits, it saves arc execution counts to a file calledsourcename.gcdafor each source file ๐พ. That data is super dependent on the generated code's structure, so you need the same source code and the same optimization options for both compiles ๐ซถ.- With
-fbranch-probabilities, GCC attaches aREG_BR_PROBnote to eachJUMP_INSNandCALL_INSN๐งฉ. Right now those notes are only used in one place: inreorg.c, where instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to figure out exactly which path gets taken more often ๐ฏ. - Enabled by
-fprofile-useand-fauto-profileโจ.
- With
-fprofile-values: combined with-fprofile-arcs, this adds code that gathers data about the values of expressions in your program ๐.- With
-fbranch-probabilities, it reads that gathered data back in and uses it for optimizations ๐ง . - Enabled by
-fprofile-generate,-fprofile-use, and-fauto-profile๐.
- With
-fprofile-reorder-functions: function reordering based on profile instrumentation records the first time each function runs, then sorts the functions in ascending order by that time ๐โโ๏ธ.- Enabled with
-fprofile-use๐ธ.
- Enabled with
-fvpt: combined with-fprofile-arcs, this tells the compiler to add code that collects information about expression values ๐ต๏ธโโ๏ธ.- With
-fbranch-probabilities, it reads the data back and actually performs optimizations based on it. Right now those include specializing division operations using what it knows about the denominator's value ๐ฐ. - Enabled with
-fprofile-useand-fauto-profile๐.
- With
-frename-registers: this tries to avoid false dependencies in scheduled code by using registers left over after register allocation ๐. It mostly helps processors with lots of registers ๐ช.- Heads up: depending on the debug information format the target uses, it can make debugging impossible, because variables no longer stay in a "home register" ๐ญ.
- Enabled by default with
-funroll-loops๐.
-fschedule-fusion: a target-dependent pass over the instruction stream that schedules instructions of the same type together, since the target machine can run them more efficiently when they sit next to each other ๐.- Enabled at levels
-O2,-O3,-Os๐.
- Enabled at levels
-ftracer: performs tail duplication to enlarge superblock size ๐งต. This simplifies the function's control flow so other optimizations can do a better job ๐ซถ.- Enabled by
-fprofile-useand-fauto-profileโจ.
- Enabled by
-funroll-loops: unrolls loops whose iteration count can be figured out at compile time or when the loop is entered ๐.-funroll-loopsimplies-frerun-cse-after-loop,-fweband-frename-registers๐งฉ.- It also turns on complete loop peeling, meaning loops with a small constant number of iterations get fully removed ๐.
- > This makes code bigger, and it may or may not make it run faster ๐คทโโ๏ธ.
- Enabled by
-fprofile-useand-fauto-profile๐ .
-funroll-all-loops: unrolls all loops, even when their iteration count is uncertain on entry ๐.- > 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, either from profile feedback or static analysis ๐. It also turns on complete loop peeling, the same way as before, for loops with a small constant number of iterations โจ.- Enabled by
-O3,-fprofile-use, and-fauto-profile๐ฆ.
- Enabled by
-fmove-loop-invariants: turns on the loop invariant motion pass in the RTL loop optimizer ๐.- Enabled at level
-O1and higher, except for-Og๐ซถ.
- Enabled at level
-fsplit-loops: splits a loop into two if it contains a condition that's always true for one side of the iteration space and false for the other ๐ช.- Enabled by
-fprofile-useand-fauto-profile๐ธ.
- Enabled by
-funswitch-loops: moves branches with loop invariant conditions outside the loop, with duplicates of the loop on both branches (each one adjusted to the result of the condition) ๐.- Enabled by
-fprofile-useand-fauto-profile๐.
- Enabled by
-fversion-loops-for-strides: if a loop walks an array with a variable stride, GCC makes another version of the loop that assumes the stride is always one ๐ฃ๏ธ. Here's the vibe:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
- This is especially helpful for assumed-shape arrays in Fortran, where it can allow better vectorization by assuming contiguous accesses ๐ง.
- This flag is enabled by default at
-O3๐ฅ. It's also enabled by-fprofile-useand-fauto-profile๐.
-ffunction-sections,-fdata-sections: each function or data item gets its own section in the output file, if the target supports arbitrary sections ๐๏ธ. The function's name or the data item's name decides the section name in the output file ๐ท๏ธ.- Use these on systems where the linker can optimize for locality of reference in the instruction space. Most systems using the ELF object format have linkers like that. On AIX, the linker rearranges sections (CSECTs) based on the call graph, and the performance impact varies ๐ข.
- Together with linker garbage collection (the
linker --gc-sectionsoption), these can lead to smaller statically-linked executables (after stripping) ๐งน. - On ELF/DWARF systems, these options don't degrade the quality of the debug information. There could be issues with other object file or debug info formats ๐ค.
- > Only use these when there are significant benefits ๐. They make the assembler and linker produce larger object and executable files, and they're also slower ๐ข. They also affect code generation: they prevent the compiler and assembler from using relative locations inside a translation unit, since those locations are unknown until link time ๐. An example of an optimization that gets blocked is relaxing calls to short call instructions ๐.
-fstdarg-opt: optimizes the prologue of variadic argument functions based on how those arguments are used ๐.- NOTE: In Ubuntu 14.10 and later versions,
-fstack-protector-strongis enabled by default for C, C++, ObjC, and ObjC++, as long as none of-fno-stack-protector,-nostdlib, or-ffreestandingare found ๐ก๏ธ.
- NOTE: In Ubuntu 14.10 and later versions,
-fsection-anchors: tries to reduce the number of symbolic address calculations by using shared "anchor" symbols to reach nearby objects โ. On some targets, this can help cut down on GOT entries and GOT accesses ๐.- For example, take this function
foo:
- For example, take this function
static int a, b, c;
int foo (void) { return a + b + c; }
Usually 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):
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
Not all targets support this option. ๐
-fzero-call-used-regs=choiceโ okay so this one zeroes out the call-used registers when a function returns ๐งน, which is lowkey iconic for security because it can either mitigate Return-Oriented Programming (ROP) attacks ๐ก๏ธ or prevent information leaking out through registers ๐. The possible values of choice are the same as for thezero_call_used_regsattribute, and the default isskip๐ . You can control this for one specific function with the function attributezero_call_used_regsโจ.
โจ --param name=value โจ
bestie, GCC is constantly using secret little numbers to decide how much optimizing to do ๐ค. For example, it won't inline a function that has more than a certain number of instructions ๐
โโ๏ธ. You can tweak some of these numbers on the command line with the --param option ๐.
Heads up, babe: the names of specific parameters, and what their values mean, are tied to the compiler's internals and can change without notice in future releases ๐จ.
To get the minimal, maximal, and default value of a parameter, you can use --help=param -Q options ๐. In each case the value is 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 remove conditional branches around a block and swap them for conditionally executed instructions ๐ช. This is the max number of instructions in a block that should be considered for if-conversion. The compiler also uses other heuristics to decide whether if-conversion is likely to be profitable ๐ง .max-rtl-if-conversion-predictable-costโ RTL if-conversion will try to remove conditional branches around a block and replace them with conditionally executed instructions ๐ช. These parameters give the max permissible cost for the sequence that would be generated, depending on whether the branch is statically determined to be predictable or not ๐. The units are the same as for the GCC internalseq_costmetric ๐งฎ. The compiler will try to provide a reasonable default using theBRANCH_COSTtarget macro ๐ฏ.max-crossjump-edgesโ the max number of incoming edges to consider for cross-jumping ๐. The algorithm used by-fcrossjumpingis O(N^2) in the number of edges incoming to each block ๐ข. Bigger values mean more aggressive optimization, making compile time go up for probably a small improvement 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 is ignored when all instructions in the block being cross-jumped from are matched ๐.max-grow-copy-bb-insnsโ the max code size expansion factor when copying basic blocks instead of jumping ๐. The expansion is relative to a jump instruction ๐ฆ.max-goto-duplication-insnsโ the max number of instructions to duplicate into a block that jumps to a computed goto ๐ช. To avoid O(N^2) behavior in a number of passes, GCC factors computed gotos early in compilation and unfactors them as late as possible โฐ. Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsget unfactored ๐ .max-delay-slot-insn-searchโ the max number of instructions to consider when looking for an instruction to fill a delay slot ๐. If more than this arbitrary number is searched, the time saved by filling the delay slot is minimal, so GCC stops searching ๐. Bigger values mean more aggressive optimization, making compile time go up for probably a small improvement in execution time ๐.max-delay-slot-live-searchโ when trying to fill delay slots, the max number of instructions to consider when searching for a block with valid live register information ๐. Increasing this arbitrarily chosen value means more aggressive optimization, which increases compile time ๐ข. This parameter should be removed when the delay slot code is rewritten to maintain the control-flow graph ๐๏ธ.max-gcse-memoryโ the approximate max amount of memory in"kB"that can be allocated to do global common subexpression elimination ๐ง . If more memory than specified is required, the optimization is not done ๐ซ.max-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is larger than this value for any expression, then RTL PRE inserts or removes the expression, leaving partially redundant computations in the instruction stream ๐.max-pending-list-lengthโ the max number of pending dependencies scheduling allows before flushing the current state and starting over ๐. Large functions with few branches or calls can create excessively large lists that needlessly eat up memory and resources ๐.max-modulo-backtrack-attemptsโ the max number of backtrack attempts the scheduler should make when modulo scheduling a loop ๐. Larger values can exponentially increase compile time ๐๐.max-inline-insns-singleโ several parameters control the tree inliner used in GCC ๐ณ. This number sets the max number of instructions (counted in GCC's internal representation) in a single function that the tree inliner considers for inlining ๐. It only affects functions declaredinlineand methods implemented in a class declaration (C++) ๐.max-inline-insns-autoโ when you use-finline-functions(included in-O3), a lot of functions that would otherwise not be considered for inlining get investigated ๐. For those functions, a different and more restrictive limit than the one for functions declaredinlinecan be applied (--param max-inline-insns-auto) ๐.max-inline-insns-smallโ the bound applied to calls considered relevant with-finline-small-functions๐ญ.max-inline-insns-sizeโ the bound applied to calls optimized for size ๐. Small growth may be desirable to anticipate optimization opportunities exposed by inlining โจ.uninlined-function-insnsโ the number of instructions the inliner counts for function overhead, like the function prologue and epilogue ๐งพ.uninlined-function-timeโ the extra time the inliner counts for function overhead, like the time needed to execute the function prologue and epilogue โฑ๏ธ.inline-heuristics-hint-percentโ the scale (in percent) applied toinline-insns-single,inline-insns-single-O2, andinline-insns-autowhen inline heuristics hint that inlining is very profitable (it will enable later optimizations) ๐.uninlined-thunk-insns,uninlined-thunk-timeโ same as--param uninlined-function-insnsand--param uninlined-function-time, but applied to function thunks ๐งต.inline-min-speedupโ when the estimated performance improvement of caller + callee runtime exceeds this threshold (in percent), the function can be inlined regardless of the limit on--param max-inline-insns-singleand--param max-inline-insns-auto๐.large-function-insnsโ the limit that defines really large functions ๐. For functions larger than this limit after inlining, inlining is constrained by--param large-function-growth๐. This parameter is mainly useful to avoid extreme compilation time caused by non-linear algorithms used by the back end ๐ฅต.large-function-growthโ the max growth of large functions caused by inlining, in percent ๐. For example, the value100limits large function growth to 2.0 times the original size ๐ฏ.large-unit-insnsโ the limit that defines a large translation unit ๐. Growth caused by inlining units larger than this limit is constrained by--param inline-unit-growth. For small units that might be too tight ๐ค. For example, consider a unit consisting of function A, which is inline, and B, which just calls A three times. If B is small relative to A, the growth of the unit is 300% and yet such inlining is very sane ๐. For very large units made of small inlineable functions, though, the overall unit growth limit is needed to avoid exponential explosion of code size ๐ฅ. So for smaller units, the size gets bumped up to--param large-unit-insnsbefore--param inline-unit-growthis applied ๐.lazy-modulesโ the max number of concurrently open C++ module files when lazy loading ๐.inline-unit-growthโ the max overall growth of the compilation unit caused by inlining ๐ฑ. For example, the value20limits unit growth to 1.2 times the original size. Cold functions (either marked cold via an attribute or by profile feedback) are not counted in the unit size โ๏ธ.ipa-cp-unit-growthโ the max overall growth of the compilation unit caused by interprocedural constant propagation ๐ง. For example, the value10limits unit growth to 1.1 times the original size.ipa-cp-large-unit-insnsโ the size of a translation unit that the IPA-CP pass considers large ๐.large-stack-frameโ the limit specifying 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, the value1000limits 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 performing recursive inlining ๐โจ.
okay so this is the tail end of the last bit ๐ซถ --param max-inline-insns-recursive is the one for functions you actually declared inline ๐. For functions that aren't declared inline, recursive inlining only happens when -finline-functions (included in -O3) is enabled, and then you want --param max-inline-insns-recursive-auto instead โจ
max-inline-recursive-depth,max-inline-recursive-depth-autoโ ๐ sets the max recursion depth for recursive inlining.--param max-inline-recursive-depthis for functions declared inline, and for non-inline functions (which only get recursive inlining when-finline-functionsis on, so it's-O3territory) you use--param max-inline-recursive-depth-autoinstead.min-inline-recursive-probabilityโ ๐ฆ recursive inlining is only worth it for functions that recurse deeply on average. For functions with barely any recursion, it can backfire by bulking up the prologue or making the function body more complicated for other optimizers ๐. When profile feedback is available (see-fprofile-generate), the compiler can guess the real recursion depth from how likely a function is to recurse through a given call expression. This param only lets inlining happen for call expressions whose probability is above the threshold, given in percent.early-inlining-insnsโ ๐ง how much growth the early inliner is allowed to make. Basically, it bumps up the amount of inlining for code with a big abstraction penalty.max-early-inliner-iterationsโ ๐ฅ the limit on how many iterations the early inliner runs. This bounds how many nested indirect calls it can resolve. Deeper chains still get handled by late inlining.comdat-sharing-probabilityโ ๐ the probability (in percent) that C++ inline functions with comdat visibility get shared across multiple compilation units.modref-max-bases,modref-max-refs,modref-max-accessesโ ๐ the max number of base pointers, references, and accesses stored for a single function by mod/ref analysis.modref-max-testsโ ๐ the max number of tests the alias oracle can run to tell memory locations apart using mod/ref info. This one 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. Set it to0and the analysis is disabled completely ๐.modref-max-escape-pointsโ โจ the max number of escape points modref tracks per SSA-name.profile-func-internal-idโ ๐ controls whether the function's internal id gets used in the profile database lookup. If the value is0, the compiler uses an id based on the function's assembler name and filename, which makes old profile data more forgiving of source changes like function reordering ๐ฆ.min-vect-loop-boundโ ๐ซถ the minimum number of iterations below which loops don't get 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 in working out the max distance an expression can be moved by GCSE optimizations. It's only supported in the code hoisting pass ๐ง . The bigger the ratio, the more aggressive the hoisting for simple expressions (ones costing less thangcse-unrestricted-cost). Setting it to0disables hoisting of simple expressions.gcse-unrestricted-costโ โญ roughly, the cost (measured as about one typical machine instruction) at which GCSE optimizations stop limiting how far an expression can travel. Also only supported in the code hoisting pass. The lower the cost, the more aggressive the hoisting. Setting it to0lets every expression travel unrestricted distances.max-hoist-depthโ ๐ how deep the search goes up the dominator tree looking for expressions to hoist. This keeps the hoisting algorithm from going quadratic. A value of0doesn't limit the search, but it may slow down compilation of huge functions ๐ข.max-tail-merge-comparisonsโ ๐ the max number of similar basic blocks a block gets compared against. This stops tree tail merging from going quadratic.max-tail-merge-iterationsโ ๐ฅ the max number of iterations of the pass over the function. It's there to cap compile time in tree tail merging.store-merging-allow-unalignedโ ๐ธ lets the store merging pass introduce unaligned stores, but only if that's legal to do.max-stores-to-mergeโ ๐ the max number of stores the store merging pass will try to fold 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 in the store merging pass.max-stores-to-trackโ ๐ฆ the max number of stores tracked at the same time while trying to merge them into wider stores in the store merging pass.max-unrolled-insnsโ ๐ the max number of instructions a loop can have and still get unrolled. If a loop does get unrolled, this param also decides how many times the loop code is unrolled ๐.max-average-unrolled-insnsโ โจ same idea as above, but counts instructions biased by how likely they are to execute. If a loop gets unrolled, this param also decides how many times the loop code is unrolled.max-unroll-timesโ ๐ the max number of unrollings for a single loop.max-peeled-insnsโ ๐ the max number of instructions a loop can have and still get peeled. If a loop gets peeled, this param also decides how many times the loop code is peeled.max-peel-timesโ ๐ the max number of peelings for a single loop.max-peel-branchesโ ๐ the max number of branches on the hot path through the peeled sequence.max-completely-peeled-insnsโ ๐ซถ the max number of insns in a completely peeled loop.max-completely-peel-timesโ โญ the max number of iterations a loop can have and still be suitable for complete peeling.max-completely-peel-loop-nest-depthโ ๐ง the max depth of a loop nest that's suitable for complete peeling.max-unswitch-insnsโ ๐ฅ the max number of insns in an unswitched loop.max-unswitch-levelโ ๐ the max number of branches unswitched in a single loop.lim-expensiveโ ๐ the minimum cost for an expression to count as expensive in loop invariant motion.min-loop-cond-split-probโ ๐ฆ when FDO profile information is available, this sets the minimum threshold for the probability of a semi-invariant condition statement triggering a loop split ๐ธ.iv-consider-all-candidates-boundโ ๐ง the bound on the number of candidates for induction variables. Below this number, every candidate gets considered for each use in induction variable optimizations. Above it, only the most relevant ones get considered, to avoid quadratic time complexity.iv-max-considered-usesโ ๐ induction variable optimizations give up on loops that contain more induction variable uses than this.iv-always-prune-cand-set-boundโ ๐ if the candidate set is smaller than this value, the compiler always tries to remove unnecessary ivs from the set when adding a new one.avg-loop-niterโ โจ the average number of iterations of a loop.dse-max-object-sizeโ ๐ the max size (in bytes) of objects tracked bytewise by dead store elimination. Bigger values may mean longer compilation times ๐ข.dse-max-alias-queries-per-storeโ ๐ the max number of queries into the alias oracle per store. Bigger values mean longer compilation times and may remove more dead stores โจ.scev-max-expr-sizeโ ๐ the bound on the size of expressions used in the scalar evolutions analyzer. Large expressions slow the analyzer down.scev-max-expr-complexityโ ๐ the bound on the complexity of expressions in the scalar evolutions analyzer. Complex expressions slow the analyzer down too.max-tree-if-conversion-phi-argsโ ๐ซถ the max number of arguments in a PHI that tree if-conversion supports, unless the loop is marked with a simd pragma.vect-max-version-for-alignment-checksโ ๐ฅ the max number of run-time checks that can be done when loop versioning for alignment in the vectorizer.vect-max-version-for-alias-checksโ ๐ the max number of run-time checks that can be done when loop versioning for alias in the vectorizer.vect-max-peeling-for-alignmentโ ๐ง the max number of loop peels to improve access alignment for the vectorizer. A value of-1means no limit ๐ธ.max-iterations-to-trackโ ๐ฆ the max number of loop iterations the brute-force algorithm tries to evaluate when analyzing how many iterations a loop does.hot-bb-count-fractionโ ๐ the denominatornin the fraction1/nof the maximal execution count of a basic block in the entire program. A basic block has to reach at least that much to count as hot. The default is10000, which means a basic block counts as hot if its execution count is greater than1/10000of the maximal execution count. A value of0means it's never considered hot. This is used in non-LTO mode ๐.hot-bb-count-ws-permilleโ okay so this is the number of the biggest-hitting permilles (anywhere from0to1000) of the profiled execution of the whole program that a basic block's execution count has to be part of to count as hot ๐ฅ. The default is990, so a block is hot if its count lands in the upper990permilles, or 99.0%, of the profiled run.0means it's never hot. This one is only used in LTO mode ๐hot-bb-frequency-fractionโ this is the denominator n in the fraction 1/n of the entry block's execution frequency of a function โจ A basic block in that function needs to hit at least that much to be hot. The default is1000, so a block is hot in a function if it runs more often than 1/1000 of the entry block's frequency.0means it's never hot ๐unlikely-bb-count-fractionโ the denominator n in 1/n of the number of profiled runs of the whole program ๐ฆ If a basic block's execution count is below that, it's considered unlikely executed. The default is20, which means a block is unlikely if it runs in fewer than 1/20, or 5%, of the program's runs.0means it's always considered unlikely executed ๐max-predicted-iterationsโ the max number of loop iterations GCC will predict statically ๐ง This is clutch when a function has one loop with a known bound and another with an unknown bound. The known count gets predicted correctly, but the unknown one averages out to roughly10, so the unbounded loop looks artificially cold next to the other one. It's giving unfair ๐ญbuiltin-expect-probabilityโ controls the probability of an expression having the specified value ๐ This takes a percentage, so0 ... 100๐builtin-string-cmp-inline-lengthโ the max length of a constant string for a builtin string cmp call that's allowed to get inlined ๐ธalign-thresholdโ picks a fraction of the maximal execution frequency of a basic block in a function, and that's what decides whether the block gets aligned ๐ซถalign-loop-iterationsโ any loop that's expected to iterate at least this many times gets aligned โจtracer-dynamic-coverageandtracer-dynamic-coverage-feedbackโ these cap superblock formation once the given percentage of executed instructions is covered, so the code doesn't balloon for no reason ๐
Heads up: tracer-dynamic-coverage-feedback only gets used when profile feedback is available ๐ฅ Real profiles are way less balanced than the statically estimated ones, so the threshold can be a bigger value.
tracer-max-code-growthโ stops tail duplication once code growth hits the given percentage ๐ฆ Ngl this one is kind of an artificial limit, since most of the duplicates get wiped out later in cross jumping. So it can be set way higher than the growth you actually want ๐tracer-min-branch-ratioโ stops reverse growth when the reverse probability of the best edge drops below this threshold, in percent ๐tracer-min-branch-probabilityandtracer-min-branch-probability-feedbackโ stop 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 for compiling with profile feedback, and tracer-min-branch-probability is for compiling without it. The feedback value needs to be more conservative (higher) to make the tracer actually effective ๐ง
stack-clash-protection-guard-sizeโ specifies the size of the operating system provided stack guard, as 2 raised to num bytes ๐ก๏ธ Higher values can mean fewer explicit probes, but if the value is larger than the OS guard, your code is vulnerable to stack clash style attacks ๐stack-clash-protection-probe-intervalโ stack clash protection involves probing stack space as it gets allocated ๐ธ This controls the max distance between probes into the stack, as 2 raised to num bytes. Higher values can reduce the number of explicit probes, but a value bigger than the OS provided guard leaves your 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 sets the minimum percentage the GC heap is allowed to expand between collections. Tuning it might speed up compilation, but it has zero effect on code generation ๐
The default is 30% + 70% * (RAM/1GB), with an upper bound of 100% when RAM is >= 1GB. If getrlimit is available, "RAM" means the smallest of actual RAM and RLIMIT_DATA or RLIMIT_AS. If GCC can't calculate RAM on a platform, the lower bound of 30% is used. Setting this and ggc-min-heapsize to zero causes a full collection at every opportunity. That is extremely slow, but it can be useful for debugging ๐
ggc-min-heapsizeโ the minimum size of the GC heap before it starts bothering to collect 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 don't get exceeded. It has a lower bound of 4096 (four megabytes) and an upper bound of 131072 (128 megabytes). If GCC can't calculate RAM on a platform, the lower bound is used. Setting this parameter very large effectively disables garbage collection ๐ฆ Setting this and ggc-min-expand to zero causes a full collection at every opportunity.
max-reload-search-insnsโ the max number of instructions reload looks backward through for an equivalent register ๐ Bigger values mean more aggressive optimization, so compile time goes up for probably slightly better performance ๐ฅmax-cselib-memory-locationsโ the max number of memory locations cselib takes into account ๐ Same deal: bigger values mean more aggressive optimization, longer compile times, and probably slightly better performance ๐ธmax-sched-ready-insnsโ the max number of instructions that are ready to be issued the scheduler should consider at any given time during the first scheduling pass ๐ซถ Bigger values mean more thorough searches, so compile time goes up for probably little benefit ๐max-sched-region-blocksโ the max number of blocks in a region considered for interblock scheduling ๐งmax-pipeline-region-blocksโ the max number of blocks in a region considered for pipelining in the selective scheduler ๐max-sched-region-insnsโ the max number of insns in a region considered for interblock scheduling ๐max-pipeline-region-insnsโ the max number of insns in a region considered for pipelining in the selective scheduler ๐min-spec-probโ the minimum probability, in percents, of reaching a source block for interblock speculative scheduling ๐max-sched-extend-regions-itersโ the max number of iterations through the CFG to extend regions โจ A value of0disables region extensions ๐max-sched-insn-conflict-delayโ the max conflict delay an insn can have and still be considered for speculative motion ๐ฆsched-spec-prob-cutoffโ the minimal probability of speculation success, in percents, needed before speculative insns get scheduled ๐sched-state-edge-prob-cutoffโ the minimum probability an edge must have before the scheduler saves its state across it ๐sched-mem-true-dep-costโ the minimal distance, in CPU cycles, between a store and a load that target the same memory locations ๐ญselsched-max-lookaheadโ the max size of the lookahead window of selective scheduling ๐ง It's basically the depth of search for available instructions ๐ฅselsched-max-sched-timesโ the max number of times an instruction gets scheduled during selective scheduling ๐ธ This is the limit on how many iterations the instruction can be pipelined through ๐selsched-insns-to-renameโ the max number of best instructions in the ready list that get considered for renaming in the selective scheduler ๐ซถsms-min-scโ the minimum value of stage count that the swing modulo scheduler generates ๐max-last-value-rtlโ the max size, measured as the number of RTLs, that can be recorded in an expression in the combiner for a pseudo register as its last known value ๐max-combine-insnsโ the max number of instructions the RTL combiner tries to combine ๐integer-share-limitโ small integer constants can use a shared data structure, which cuts down on the compiler's memory usage and speeds it up โจ This sets the max value of a shared integer constant ๐ssp-buffer-sizeโ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectionis used ๐ก๏ธ
Okay so, picking up where we left off, bestie. Before Ubuntu 10.10 the default was "8" ๐ Now it's "4" โจ, which means more functions get covered by the stack protector ๐ก๏ธ
min-size-for-stack-sharingโ the smallest size a variable can be to join in on stack slot sharing when you're not optimizing ๐งmax-jump-thread-duplication-stmtsโ the most statements a block can have and still get duplicated when jumps are threaded ๐งตmax-fields-for-field-sensitiveโ how many fields a struct can have and still get the field-sensitive treatment during pointer analysis ๐prefetch-latencyโ a guess at how many instructions run on average before a prefetch finishes โฑ๏ธ The prefetch distance scales with this number, and cranking it up can mean fewer streams get prefetched (seesimultaneous-prefetches) ๐ธsimultaneous-prefetchesโ the max number of prefetches allowed to 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โ decides whether the loop array prefetch pass should slip in software prefetch hints for non-constant strides ๐ Sometimes that helps, but a non-constant stride makes it super hard to tell when the hints are actually worth it ๐ค- Set it to
1if you want hints issued 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 smallest constant stride, in bytes, where prefetch hints start kicking in ๐ If the stride is below this threshold, no hints get issued ๐ซถ- This one is useful on processors with hardware prefetchers, since the hardware and software prefetchers can clash. If the hardware prefetchers have a maximum stride they can handle, put that number here so the software prefetchers get used better ๐
- A value of
-1means there's no threshold, so hints can be issued for any constant stride โจ - It only matters for strides that are known and constant ๐ซง
loop-interchange-max-num-stmtsโ the max number of statements in a loop that can get interchanged ๐loop-interchange-stride-ratioโ the minimum ratio between the strides of two loops for an interchange to be worth it ๐ซmin-insn-to-prefetch-ratioโ the minimum ratio of instructions to prefetches needed before a loop gets prefetching turned on ๐prefetch-min-insn-to-mem-ratioโ the minimum ratio of instructions to memory references needed to turn on prefetching in a loop ๐งuse-canonical-typesโ whether the compiler uses the "canonical" type system ๐ง It should always be1, since that's a more efficient internal way to compare types in C++ and Objective-C++ ๐ But if bugs in the canonical type system are breaking your compiles, set it to0to turn canonical types off ๐ โโ๏ธswitch-conversion-max-branch-ratioโ switch initialization conversion won't build arrays bigger thanswitch-conversion-max-branch-ratiotimes the number of branches in the switch ๐ซmax-partial-antic-lengthโ the max length of the partial antic set computed during tree partial redundancy elimination (-ftree-pre) when you're optimizing at-O3and up ๐ Some code can make this optimization run away and eat all the memory on the host machine ๐ This cap stops that runaway behavior by limiting how long the sets can get. Setting it to0means the set length is unlimited ๐คrpo-vn-max-loop-depthโ the max loop depth that gets value-numbered optimistically ๐ When the limit is hit, the innermostrpo-vn-max-loop-depthloops and the outermost loop in the loop nest are value-numbered optimistically, and the rest aren't ๐ซถsccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries we run while hunting for redundant loads and stores ๐ต๏ธโโ๏ธ If the limit gets hit, the search is aborted and that load or store doesn't count as redundant. The number of queries is algorithmically capped at the number of stores on all paths from the load to the function entry ๐งฎira-max-loops-numโ IRA uses regional register allocation by default ๐งฉ If a function has more loops than this number, only that many of the most frequently executed loops form regions for regional register allocation ๐ฏira-max-conflict-table-sizeโ IRA is very smart about compressing the conflict table, but huge functions can still need an excessive amount of memory ๐ญ If a function's conflict table could go over this many MB, 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 estimate register pressure more accurately in loops when deciding whether to move loop invariants (see-O3) ๐ง This sets how many available registers get reserved for other purposes. The default is the best value found from loads of experiments ๐lra-inheritance-ebb-probability-cutoffโ LRA tries to reuse values reloaded into registers by later insns, and that's called inheritance ๐ EBB is the region used for this, and this parameter sets the minimal fall-through edge probability (as a percentage) for adding a BB to the inheritance EBB in LRA ๐ The default was picked from lots of SPEC2000 runs on x86-64 ๐loop-invariant-max-bbs-in-loopโ loop invariant motion can be super expensive in compile time and memory with really big loops ๐ฅต Loops with more basic blocks than this won't get loop invariant motion done on them ๐ โโ๏ธloop-max-datarefs-for-datadepsโ building data dependencies is expensive for massive loops ๐ This caps how many data references in a loop get considered for data dependence analysis. Loops that are too big don't get handled by the optimizations that use loop data dependencies ๐max-vartrack-sizeโ the max number of hash table slots used during variable tracking dataflow analysis of any function ๐๏ธ If that limit is blown with variable tracking at assignments enabled, the analysis gets retried without it after all debug insns are removed from the function ๐ If it's still over the limit without debug insns, var tracking analysis is totally disabled for that function ๐ต Setting it to zero makes it unlimited โพ๏ธmax-vartrack-expr-depthโ the max recursion levels when mapping variable names or debug temporaries to value expressions ๐ฟ This trades compile time for more complete debug info. If it's set too low, value expressions that could've been in the debug info might not get used. Setting it higher lets the compiler find fancier debug expressions, but compile time and memory use can grow ๐max-debug-marker-countโ the threshold for debug markers (like begin stmt markers) so you don't get a complexity explosion when inlining or expanding to RTL ๐ฅ If a function has more of these gimple stmts than the limit, they get dropped from the inlined copy of the function and from its RTL expansion ๐ซmin-nondebug-insn-uidโ nondebug insns start their uids at this number ๐ข The range below it is reserved for debug insns created by-fvar-tracking-assignments, but debug insns can still get non-overlapping uids above it if that reserved range runs out ๐ipa-sra-ptr-growth-factorโ IPA-SRA only swaps a pointer to an aggregate for one or more new parameters if their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter ๐ชipa-sra-max-replacementsโ the max number of pieces of an aggregate that IPA-SRA tracks ๐งฉ That also makes it the max number of replacements for a formal parameter ๐sra-max-scalarization-size-Ospeed,sra-max-scalarization-size-Osizeโ both Scalar Reduction of Aggregates passes (SRA and IPA-SRA) try to swap scalar parts of aggregates for uses of independent scalar variables ๐ง These two params set the max size, in storage units, of an aggregate that's considered for that swap when compiling for speed (sra-max-scalarization-size-Ospeed) or for size (sra-max-scalarization-size-Osize) ๐๏ธ๐ฆsra-max-propagationsโ the max number of artificial accesses that Scalar Replacement of Aggregates (SRA) tracks per local variable so it can do copy propagation ๐tm-max-aggregate-sizeโ when copying thread-local variables inside a transaction, this sets the size in bytes after which variables get saved with the logging functions instead of save/restore code sequence pairs ๐ This only applies when you're using-fgnu-tm๐graphite-max-nb-scop-paramsโ okay so the Graphite loop transforms can go exponential if you let them run wild ๐, which is why the number of parameters in a Static Control Part (SCoP) gets capped ๐งข. Set it to0to lift the cap entirely โจ. And a variable whose value isn't known at compile time and is defined outside a SCoP counts as one of that SCoP's parameters ๐ฆ.loop-block-tile-sizeโ loop blocking and strip mining (switched on with-floop-blockor-floop-strip-mine) chop every loop in the nest into strips of a set number of iterations ๐. You can change how long those strips are with this parameter ๐ .ipa-jump-function-lookupsโ sets how many statements get visited while IPA hunts down jump function offsets ๐.ipa-cp-value-list-sizeโ IPA-CP tries to track every value and type that gets passed into a function's parameter so it can propagate them and do devirtualization ๐ง . This is the max number of values and types it'll store for each formal parameter ๐.ipa-cp-eval-thresholdโ IPA-CP scores its own cloning profitability ๐. Any cloning opportunity whose score beatsipa-cp-eval-thresholdgets done ๐ฅ.ipa-cp-max-recursive-depthโ the deepest level of recursive cloning allowed for a self-recursive function ๐.ipa-cp-min-recursive-probabilityโ recursive cloning only happens when the chance of the call actually running is higher than this parameter ๐ฒ.ipa-cp-recursion-penaltyโ a percentage penalty that recursive functions take when they're being evaluated for cloning ๐.ipa-cp-single-call-penaltyโ a percentage penalty for functions whose only job is making a single call to another function, applied when they're up for cloning ๐.ipa-max-agg-itemsโ IPA-CP can also propagate scalar values that get passed inside an aggregate ๐ฆ. This caps how many of those values it'll handle for one parameter ๐.ipa-cp-loop-hint-bonusโ if IPA-CP figures out that a cloning candidate would make a loop's iteration count known, the candidate gets a bonus ofipa-cp-loop-hint-bonusadded to its profitability score ๐.ipa-max-loop-predicatesโ the maximum number of different predicates IPA uses to describe when a function's loops have known properties ๐งฉ.ipa-max-aa-stepsโ IPA-CP uses alias analysis to keep track of what function parameters point to ๐. To avoid spending forever on huge functions, it gives up after examiningipa-max-aa-stepsmemory-modifying statements and just assumes all memory got clobbered ๐.ipa-max-switch-predicate-boundsโ the maximum number of boundary endpoints for case ranges in a switch statement ๐. If a switch goes over this limit, IPA-CP won't build the cloning cost predicate for its default case, which is what's used to estimate cloning benefit ๐ซ.ipa-max-param-expr-opsโ IPA-CP will look at conditional statements that reference a function parameter to estimate the benefit of cloning for a certain constant value ๐ค. But if a parameter expression has more operations thanipa-max-param-expr-ops, it's considered too complicated and IPA analysis skips it ๐.lto-partitionsโ the desired number of partitions made during WHOPR compilation ๐งฉ. You want this to be more than the number of CPUs being used for compilation ๐ฅ๏ธ.lto-min-partitionโ the minimum partition size for WHOPR, measured in estimated instructions ๐. This stops tiny programs from getting split into way too many partitions ๐ โโ๏ธ.lto-max-partitionโ the max partition size for WHOPR, also in estimated instructions ๐. It sets an upper bound on how big any single partition can get ๐ซถ. It's only meant to be used with balanced partitioning โ๏ธ.lto-max-streaming-parallelismโ the maximum number of parallel processes used for LTO streaming ๐.cxx-max-namespaces-for-diagnostic-helpโ when C++ name lookup fails for an identifier, this is the max number of namespaces the compiler checks for suggestions ๐.sink-frequency-thresholdโ the highest relative execution frequency (as a percent) that the target block can have, compared to the statement's original block, and still allow that statement to get sunk ๐. Bigger numbers mean more aggressive sinking ๐ฅ. Statements with memory operands get a small positive adjustment, since sinking them is even more profitable โจ.max-stores-to-sinkโ the max number of conditional store pairs that can be sunk ๐ณ๏ธ. It gets set to 0 if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is turned off ๐ซ.case-values-thresholdโ the smallest number of different values where a jump table is a better pick than a tree of conditional branches ๐ณ. If it's0, the machine's default gets used ๐ค.jump-table-max-growth-ratio-for-sizeโ the max code size growth ratio (in percent) when expanding into a jump table ๐. This one's used when you're optimizing for size ๐๏ธ.jump-table-max-growth-ratio-for-speedโ same max code size growth ratio (in percent) for expanding into a jump table ๐. This one's used when you're optimizing for speed ๐๏ธ.tree-reassoc-widthโ sets the max number of instructions executed in parallel in a reassociated tree ๐ฒ. If it's set to a non-zero value, it overrides the target-dependent heuristics that would be used by default ๐ช.sched-pressure-algorithmโ picks between the two implementations of-fsched-pressure๐งช. Algorithm 1 is the original, and it's the one more likely to stop instructions from getting reordered ๐ โโ๏ธ. Algorithm 2 was built as a compromise between the pretty conservative algorithm 1 and the rather aggressive default scheduler โ๏ธ. It leans harder on having a regular register file and accurate register pressure classes ๐งฒ. Check haifa-sched.c in the GCC sources for more details ๐.
The default choice depends on the target ๐ฏ.
max-slsr-cand-scanโ the max number of existing candidates that get looked at when hunting for a basis for a new straight-line strength reduction candidate ๐.asan-globalsโ turns on buffer overflow detection for global objects ๐. This protection is on by default if you're using-fsanitize=address๐ก๏ธ. To turn off global objects protection, use--param asan-globals=0๐ โโ๏ธ.asan-stackโ turns on buffer overflow detection for stack objects ๐ฅ. It's on by default when you use-fsanitize=addressโจ. To disable stack protection, use--param asan-stack=0๐ซ.asan-instrument-readsโ turns on buffer overflow detection for memory reads ๐. It's on by default when using-fsanitize=address๐ก๏ธ. To disable memory reads protection, use--param asan-instrument-reads=0๐ โโ๏ธ.asan-instrument-writesโ turns on buffer overflow detection for memory writes โ๏ธ. It's on by default when using-fsanitize=address๐ก๏ธ. To disable memory writes protection, use--param asan-instrument-writes=0๐ซ.asan-memintrinโ turns on detection for built-in functions ๐งฐ. It's on by default when using-fsanitize=address๐ก๏ธ. To disable built-in functions protection, use--param asan-memintrin=0๐ โโ๏ธ.asan-use-after-returnโ turns on detection of use-after-return ๐. It's on by default when using the-fsanitize=addressoption ๐ก๏ธ. To turn it off, use--param asan-use-after-return=0๐ซ.
Note: by default this check is disabled at run time ๐ญ. To enable it, add"detect_stack_use_after_return=1"to the environment variableASAN_OPTIONS๐.
asan-instrumentation-with-call-thresholdโ if a function being instrumented has at least this many memory accesses, the compiler uses callbacks instead of inline checks ๐. For example, to turn off inline code, use--param asan-instrumentation-with-call-threshold=0๐ง.hwasan-instrument-stackโ turns on hwasan instrumentation of statically sized stack-allocated variables ๐งฑ. This is on by default with-fsanitize=hwaddressand off by default with-fsanitize=kernel-hwaddress๐. To turn stack instrumentation off, use--param hwasan-instrument-stack=0, and to turn it on, use--param hwasan-instrument-stack=1๐.hwasan-random-frame-tagโ when stack instrumentation is on, tags for stack variables come from a deterministic sequence that starts at a random tag for each frame ๐ฒ. If this parameter isn't set, the tags use the same sequence but start from 1 ๐ข. It's on by default for-fsanitize=hwaddressand not available for-fsanitize=kernel-hwaddress๐ซ. To turn it off, use--param hwasan-random-frame-tag=0๐ โโ๏ธ.hwasan-instrument-allocasโ turns on 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 it off, use--param hwasan-instrument-allocas=0, and to turn it on, use--param hwasan-instrument-allocas=1๐.hwasan-instrument-readsโ turns on hwasan checks on memory reads ๐. Read instrumentation is on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddressโจ. To stop checking memory reads, use--param hwasan-instrument-reads=0๐ โโ๏ธ.hwasan-instrument-writesโ Turns on hwasan checks for memory writes ๐ฅ. Write instrumentation is already on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress, but if you want to skip checking writes, use--param hwasan-instrument-writes=0.hwasan-instrument-mem-intrinsicsโ Adds hwasan instrumentation to builtin functions ๐. This is also on by default for both-fsanitize=hwaddressand-fsanitize=kernel-hwaddress, and you can turn it off with--param hwasan-instrument-mem-intrinsics=0.use-after-scope-direct-emission-thresholdโ If a local variable is<pink>this many bytes or smaller</pink>, the shadow memory gets poisoned (or unpoisoned) directly โจ. Bigger variables fall back to run-time callbacks instead.tsan-distinguish-volatileโ Gives accesses to volatiles their own special instrumentation ๐ฆ.tsan-instrument-func-entry-exitโ Emits instrumentation calls to__tsan_func_entry()and__tsan_func_exit()๐ง.max-fsm-thread-path-insnsโ The most instructions that can get copied when duplicating blocks along a finite state automaton jump thread path ๐ธ.max-fsm-thread-lengthโ The most basic blocks allowed on a finite state automaton jump thread path ๐.max-fsm-thread-pathsโ The most new jump thread paths GCC will create for a finite state automaton ๐ .parloops-chunk-sizeโ The chunk size of the omp schedule for loops thatparloopsparallelizes ๐ซถ.parloops-scheduleโ The omp schedule type for loops parallelized byparloops. You can pick fromstatic,dynamic,guided,auto, orruntime๐.parloops-min-per-threadโ The minimum number of iterations each thread needs in an innermost parallelized loop before the parallel version is preferred over the single-threaded one ๐งต. Heads up: for a parallelized loop nest, the minimum number of iterations of the outermost loop per thread is two, so that part's already set. ๐max-ssa-name-query-depthโ How deep the recursion can go when you query properties of SSA names in things like fold routines ๐. Each level of recursion means following one use-def chain.max-speculative-devirt-maydefsโ The max number of may-defs analyzed while hunting for a must-def that tells you the dynamic type of an object making a virtual call ๐ต๏ธโโ๏ธ. Those are the ones that might get devirtualized speculatively.max-vrp-switch-assertionsโ The max number of assertions added along a switch statement's default edge during VRP ๐.evrp-modeโ Picks the mode that Early VRP operates in โญ.unroll-jam-min-percentโ The minimum percentage of memory references that have to get optimized away before the unroll-and-jam transformation counts as profitable ๐.unroll-jam-max-unrollโ The max number of times the outer loop can be unrolled by unroll-and-jam ๐ฆ.max-rtl-if-conversion-unpredictable-costโ The most expensive sequence the RTL if-conversion pass can generate for a branch that's considered unpredictable ๐.max-variable-expansions-in-unrollerโ When-fvariable-expansion-in-unrolleris on, this is how many times one variable can get expanded during loop unrolling ๐.tracer-min-branch-probability-feedbackโ Stops forward growth once the probability of the best edge drops below this threshold (a percentage). It only kicks in when profile feedback is available ๐ธ.partial-inlining-entry-probabilityโ The max probability of the entry BB of a split region (a percentage relative to the function's entry BB) that still lets partial inlining happen ๐.max-tracked-strlensโ The max number of strings the strlen optimization pass will track lengths for ๐ .gcse-after-reload-partial-fractionโ The threshold ratio for doing partial redundancy elimination after reload โจ.gcse-after-reload-critical-fractionโ The threshold ratio of critical-edge execution counts that allows redundancy elimination after reload ๐ซถ.max-loop-header-insnsโ The max number of insns in a loop header that the copy loop headers pass is allowed to duplicate ๐ฅ.vect-epilogues-nomaskโ Turns on loop epilogue vectorization using a smaller vector size ๐.vect-partial-vector-usageโ Decides when the loop vectorizer is allowed to use partial vector loads and stores instead of falling back to scalar code ๐. The options are:0โ the vectorizer never uses partial vector loads and stores.1โ partial vector loads and stores are allowed, but only if vectorization gets rid of the need for the code to iterate.2โ partial vector loads and stores are allowed in all loops.
This only does anything on targets that support partial vector loads and stores ๐.
avoid-fma-max-bitsโ The max number of bits for which GCC avoids creating FMAs ๐ง.sms-loop-average-count-thresholdโ A threshold on the average loop count that the swing modulo scheduler takes into account ๐ฆ.sms-dfa-historyโ How many cycles the swing modulo scheduler looks at when checking for conflicts using DFA ๐ธ.max-inline-insns-recursive-autoโ The max number of instructions a non-inline function can grow to through recursive inlining ๐.graphite-allow-codegen-errorsโ Decides whether codegen errors should be ICEs when-fcheckingis on ๐.sms-max-ii-factorโ A factor for tuning the upper bound the swing modulo scheduler uses when it schedules a loop ๐ .lra-max-considered-reload-pseudosโ The max number of reload pseudos considered while spilling a non-reload pseudo โจ.max-pow-sqrt-depthโ The max depth of sqrt chains used when synthesizing exponentiation by a real constant ๐.max-dse-active-local-storesโ The max number of active local stores in RTL dead store elimination ๐.asan-instrument-allocasโ Turns on asan protection for allocas and VLAs ๐ก๏ธ.max-iterations-computation-costโ The bound on the cost of an expression used to compute the number of iterations ๐.max-isl-operationsโ The max number of isl operations.0means unlimited ๐.graphite-max-arrays-per-scopโ The max number of arrays per scop ๐ธ.max-vartrack-reverse-op-sizeโ The max size of a loc list that's allowed to get reverse ops added ๐ฆ.tracer-dynamic-coverage-feedbackโ The percentage of a function, weighted by execution frequency, that trace formation has to cover. This one's used when profile feedback is available ๐ฅ.max-inline-recursive-depth-autoโ The max depth of recursive inlining for non-inline functions ๐.fsm-scale-path-stmtsโ A scale factor applied to the number of statements in a threading path when it gets compared to the number of (scaled) blocks ๐ .fsm-maximum-phi-argumentsโ The max number of arguments a PHI can have before the FSM threader stops trying to thread through its block โจ.uninit-control-dep-attemptsโ The max number of nested calls used to search for control dependencies during uninitialized variable analysis ๐ซถ.sra-max-scalarization-size-Osizeโ The max size, in storage units, of an aggregate that should be considered for scalarization when compiling for size ๐.fsm-scale-path-blocksโ A scale factor applied to the number of blocks in a threading path when it gets compared to 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 looks into. At' ', only the instruction sorting heuristic gets enabled ๐ง.loop-versioning-max-inner-insnsโ The max number of instructions an inner loop can have before the loop versioning pass decides it's too big to copy ๐ฆ.loop-versioning-max-outer-insnsโ The max number of instructions an outer loop can have before the loop versioning pass decides it's too big to copy ๐ธ. Any instructions in inner loops that directly benefit from versioning don't count toward that total ๐.ssa-name-def-chain-limitโ The max number of SSA_NAME assignments to follow when figuring out a property of a variable, like its value ๐ . This caps how many iterations or recursive calls GCC makes while optimizing certain statements or checking whether they're valid before it issues diagnostics โจ.store-merging-max-sizeโ The max size of a single store merging region, in bytes ๐ซถ.hash-table-verification-limitโ How many elements get hash table verification done for each searched element ๐.max-find-base-term-valuesโ The max number of VALUEs handled in a singlefind_base_termcall ๐.analyzer-max-enodes-per-program-pointโ The max number of exploded nodes per program point within the analyzer. Once you hit it, 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 will think about summarizing its effects at call sites ๐ฆ.analyzer-max-enodes-for-full-dumpโ The max depth of exploded nodes that can appear 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 within the analyzer. Once that's hit, analysis of a call that would recurse deeper stops ๐.analyzer-max-svalue-depthโ The max depth of a symbolic value. Past this, the value gets approximated 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 it takes for a basic block to count as hot ๐ฅ. This param is only used in the GIMPLE FE ๐ซถ.analyzer-bb-explosion-factorโ ๐ The most "after supernode" exploded nodes the analyzer can make per supernode. Once it hits this number, it stops the analysis โจ.ranger-logical-depthโ ๐ง How deep ranger is allowed to dig into logical expression evaluation when it checks the ranges on outgoing edges. This is the max depth, bestie ๐ซถ.openacc-kernelsโ ๐ธ Picks how OpenACCkernelsconstructs get handled. There are two choices:--param=openacc-kernels=decomposeโ chops eachkernelsconstruct into parts, a sequence of compute constructs, and handles each one individually. It's still work in progress ๐ง.--param=openacc-kernels=parloopsโ handleskernelsconstructs with the parloops pass, all at once (en bloc). This is the current default, and it's giving stable ๐.
The following are available on AArch64 targets ๐ฆ:
aarch64-sve-compare-costsโ ๐ When vectorizing for SVE, GCC can consider "unpacked" vectors for smaller elements, then let the cost model 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 forfloattypes. When division approximation is enabled, the precision of division scales with this param. The default value is1.aarch64-double-recp-precisionโ ๐ข The number of Newton iterations used to calculate the reciprocal fordoubletypes. When division approximation is enabled, the precision of division scales with this param. The default value is2.aarch64-autovec-preferenceโ ๐ฏ Forces an ISA selection strategy for auto-vectorization. It accepts values from0to4, inclusive:0โ Uses the default heuristics.1โ Uses only Advanced SIMD for auto-vectorization.2โ Uses only SVE for auto-vectorization.3โ Uses both Advanced SIMD and SVE, and prefers Advanced SIMD when the costs are deemed equal.4โ Uses both Advanced SIMD and SVE, and prefers SVE when the costs are deemed equal.
The default value is 0.
aarch64-loop-vect-issue-rate-nitersโ ๐ง Some AArch64 CPUs tune by considering 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 that are known to execute in fewer thannAdvanced SIMD iterations.
๐ Program Instrumentation Options ๐
GCC has a bunch of command-line options that add run-time instrumentation to the code it normally generates ๐. Instrumentation can collect profiling statistics so you can find your program's hot spots, do code coverage analysis, or feed profile-guided optimizations. Another kind of instrumentation adds run-time checking to 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 for 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 must use this option when compiling the source files you want data about, and you must also use it when linking.
You can use the function attribute "no_instrument_function" to stop profiling individual functions when compiling with these options.
-fprofile-arcsโ ๐น Adds code so that program flow arcs are instrumented. While the program runs, it records how many times each branch and call is executed, and how many times each is taken or returns. On targets that support constructors with priority, profiling properly handles constructors, destructors, and C++ constructors (and destructors) of classes that are used as the type of a global variable.
When the compiled program exits, it saves this data to a file called auxname.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 is generated from the name of the output file if it's explicitly specified and isn't the final executable. Otherwise, it's the basename of the source file. In both cases, any suffix is removed. For example, you get foo.gcda for input file dir/foo.c, or dir/foo.gcda for output file specified as -o dir/foo.o.
--coverageโ ๐งช Compiles and links code instrumented for coverage analysis. It's a synonym for-fprofile-arcs-ftest-coverage(when compiling) and-lgcov(when linking). Check the docs for those options for more details. Here's the full workflow:- Compile the source files with
-fprofile-arcs, plus optimization and code generation options. For test coverage analysis, add the-ftest-coverageoption too. You don't need to profile every source file in a program. - Compile the source files additionally with
-fprofile-abs-pathto create absolute path names in the.gcnofiles. This lets gcov find the correct sources in projects where compilations happen with different working directories. - Link your object files with
-lgcovor-fprofile-arcs. The latter implies the former. - Run the program on a representative workload to generate the arc profile information. You can repeat this any number of times. You can run concurrent instances of your program, and as long as the file system supports locking, the data files will be updated correctly. Unless a strict ISO C dialect option is in effect,
forkcalls are detected and handled correctly without double counting ๐ด. - For profile-directed optimizations, compile the source files again with the same optimization and code generation options, plus
-fbranch-probabilities. - For test coverage analysis, use
gcovto produce human-readable information from the.gcnoand.gcdafiles. Check the gcov documentation for more info.
- Compile the source files with
With -fprofile-arcs, for each function in your program GCC creates a program flow graph, then finds a spanning tree for that graph. Only arcs that are not on the spanning tree have to be instrumented: the compiler adds code to count how many times those arcs run. When an arc is the only exit or the only entrance to a block, the instrumentation code can go in that block. Otherwise, a new basic block has to be created to hold it ๐งฉ.
-ftest-coverageโ ๐ Produces a notes file that thegcovcode-coverage utility can use to show program coverage. Each source file's notes file is calledauxname.gcno. See the-fprofile-arcsoption above for a description ofauxnameand instructions on generating test coverage data. Coverage data matches the source files more closely if you don't optimize.-fprofile-abs-pathโ ๐บ๏ธ Automatically converts relative source file names into absolute path names in the.gcnofiles. This lets gcov find the correct sources in projects where compilations happen with different working directories.-fprofile-dir=pathโ ๐ Sets the directory where profile data files are searched for topath. This option only affects profile data generated by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-useand-fbranch-probabilitiesand its related options. Both absolute and relative paths work. By default, GCC uses the current directory, so the profile data file sits in the same directory as the object file. To prevent file name clashes, 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. See the similar option-fprofile-note.
When an executable runs in a massively parallel environment, it's recommended to save profiles to different folders ๐. You can do that with variables in path that get exported at run-time:
%pโ process ID.%q{VAR}โ value of environment variableVAR.
-fprofile-generate,-fprofile-generate=pathโ ๐ญ Enables options that are usually used to instrument an application so it produces a profile useful for later recompilation with profile feedback-based optimization. You must use-fprofile-generateboth when compiling and when linking your program.
The following options get enabled: -fprofile-arcs, -fprofile-values, -finline-functions, and -fipa-bit-cp.
If path is specified, GCC looks there for the profile feedback data files. See -fprofile-dir. To optimize the program based on the collected profile info, use -fprofile-use ๐.
-fprofile-info-section,-fprofile-info-section=nameโ ๐ฆ Registers the profile information in the specified section instead of using a constructor/destructor. The section name isnameif you specify it, otherwise it defaults to".gcov_info". A pointer to the profile information generated by-fprofile-arcsor-ftest-coverageis placed in the specified section for each translation unit. This option disables profile information registration through a constructor, and it disables profile information processing through a destructor. It isn't meant for hosted environments like GNU/Linux. It targets systems with limited resources that don't support constructors and destructors. The linker could collect the input sections into a continuous memory block and define start and end symbols. The runtime support could dump the profiling information registered in this linker set to a serial line during program termination, for example. A GNU linker script example that defines a linker output section follows:
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
-fprofile-note=pathโ okay so if you give it a path, GCC saves the.gcnofile right into that location ๐โจ Heads up, bestie: if you combine this with multiple source files, that.gcnofile gets overwritten ๐-fprofile-prefix-path=pathโ this one is giving teamwork withprofile-generate=profile_dirandprofile-use=profile_dir๐ค It tells GCC where the base directory of your built source tree lives ๐ณ By default,profile_dirgets files with mangled absolute paths of every object file in the built project, and ngl that's messy ๐ญ It's a problem when the directory you used for the instrumented binary is different from the one you used for the optimized build, because then the profile data can't be found during the optimized build ๐ So in those setups,-fprofile-prefix-path=path(with path pointing to the base build directory) strips the irrelevant bits and keeps all file names relative to the main build directory ๐งนโจ-fprofile-update=methodโ this changes how an app instrumented for profile feedback based optimization updates its counters ๐ The method should be one ofsingle,atomicorprefer-atomic๐singleis perfect for single-threaded apps, andatomicprevents profile corruption by emitting thread-safe code ๐งต
Warning: if an application doesn't properly join all of its threads (or it creates a detached thread), the profile file can still get corrupted ๐ฑ
Using prefer-atomic gets transformed into atomic if the target supports it, or into single if it doesn't ๐ฏ The GCC driver automatically picks prefer-atomic whenever -pthread shows up in the command line ๐ซถ
-fprofile-filter-files=regexโ only instruments functions from files whose names match any of the regular expressions (separated by semi-colons) ๐
For example, -fprofile-filter-files=main\.c;module.*\.c will instrument only main.c and all C files starting with 'module' ๐ธ
-fprofile-exclude-files=regexโ the opposite energy ๐ โโ๏ธ It only instruments functions from files whose names do not match any of the regular expressions (separated by semi-colons) ๐ซ
For example, -fprofile-exclude-files=/usr/.* will prevent instrumentation of all files located in the /usr/ folder ๐งฑ
-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ controls how reproducible the profile gathered by"-fprofile-generate"is ๐ This lets you rebuild a program with the same outcome, which is super useful for things like distribution packages ๐ฆ๐
With -fprofile-reproducible=serial, the profile gathered by -fprofile-generate is reproducible, provided that the trained program behaves the same at each invocation of the train run, it is not multi-threaded, and profile data streaming is always done in the same order ๐ง Also, profile streaming happens at the end of the program run, but also before the "fork" function is invoked ๐ด
Literally, it's pretty common for execution counts in some parts of a program to depend on things like the length of temporary file names or memory space randomization (which may affect hash-table collision rate) ๐ฒ Those non-reproducible parts can be annotated with the "no_instrument_function" function attribute ๐ท๏ธ You can use gcov-dump with -l to dump the gathered data and verify that it's actually reproducible ๐
With -fprofile-reproducible=parallel-runs, the collected profile stays reproducible no matter what order the data gets streamed into gcda files ๐ This setting lets you run multiple instances of the instrumented program in parallel (like with make -j) ๐โโ๏ธ๐จ The catch is that it reduces the quality of the gathered data, especially for indirect call profiling ๐ฌ
-fsanitize=addressโ enables AddressSanitizer, a fast memory error detector ๐ Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs ๐ต๏ธโโ๏ธ This option also enables-fsanitize-address-use-after-scope๐ More details live at<https://github.com/google/sanitizers/wiki/AddressSanitizer>๐ You can influence the run-time behavior with theASAN_OPTIONSenvironment variable ๐๏ธ When it's set to"help=1", the available options get shown at startup of the instrumented program ๐ For a list of supported options, check<https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags>๐ This option can't be combined with-fsanitize=threador-fsanitize=hwaddress๐ โโ๏ธ And FYI, the only target-fsanitize=hwaddressis currently supported on is AArch64 ๐ฆพ-fsanitize=kernel-addressโ enables AddressSanitizer for the Linux kernel ๐ง More details at<https://github.com/google/kasan>๐ง-fsanitize=hwaddressโ enables Hardware-assisted AddressSanitizer, which uses a hardware ability to ignore the top byte of a pointer so it can detect memory errors with low memory overhead โจ Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs ๐ซง This option enables-fsanitize-address-use-after-scopetoo ๐ See<https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html>for more details ๐ The run-time behavior can be influenced with theHWASAN_OPTIONSenvironment variable, and when it's set to"help=1", the available options are shown at startup of the instrumented program ๐ This option can't be combined with-fsanitize=threador-fsanitize=address, and it's currently only available on AArch64 ๐ฆพ-fsanitize=kernel-hwaddressโ enables Hardware-assisted AddressSanitizer for compiling the Linux kernel ๐งโก It's similar to-fsanitize=kernel-addressbut uses an alternate instrumentation method, and it's similar to-fsanitize=hwaddressbut with instrumentation differences needed for compiling the kernel ๐งฉ Those differences exist to avoidhwasanlibrary initialization calls and to account for the stack pointer having a different value in its top byte ๐
Note: this option has different defaults from-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 ๐ซ
-fsanitize=pointer-compareโ instruments comparison operations (<,<=,>,>=) with pointer operands ๐ It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it can't be combined with-fsanitize=thread๐ โโ๏ธ
Note: the check is disabled at run time by default ๐ 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 ๐ซถ
-fsanitize=pointer-subtractโ instruments subtraction with pointer operands ๐งฎ It must be combined with either-fsanitize=kernel-addressor-fsanitize=address, and it can't be combined with-fsanitize=thread๐ซ
Note: the check is disabled at run time by default ๐ฅฒ 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 ๐
-fsanitize=threadโ enables ThreadSanitizer, a fast data race detector ๐งตโก Memory access instructions get instrumented to catch data race bugs ๐ธ๏ธ See<https://github.com/google/sanitizers/wiki#threadsanitizer>for more details ๐ The run-time behavior can be influenced with theTSAN_OPTIONSenvironment variable, and you can find a list of supported options at<https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags>๐ This option can't be combined with-fsanitize=addressor-fsanitize=leak๐ โโ๏ธ
Also, sanitized atomic builtins can't throw exceptions when operating on invalid memory addresses with non-call exceptions (-fnon-call-exceptions) ๐ญ
-fsanitize=leakโ enables LeakSanitizer, a memory leak detector ๐ง This option only matters when linking executables, and the executable is linked against a library that overrides"malloc"and other allocator functions ๐ง See<https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer>for more details ๐ The run-time behavior can be influenced with theLSAN_OPTIONSenvironment variable ๐๏ธ This option can't be combined with-fsanitize=thread๐ซ-fsanitize=undefinedโ enables UndefinedBehaviorSanitizer, a fast undefined behavior detector ๐โจ Various computations get instrumented to catch undefined behavior at runtime ๐ซง See<https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html>for more details ๐ The run-time behavior can be influenced with theUBSAN_OPTIONSenvironment variable ๐๏ธ The current suboptions are:-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, it checks that the result of the shift operation is not undefined ๐ง Again, what exactly counts as undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc. ๐-fsanitize=integer-divide-by-zeroโ detects integer division by zero, as well as"INT_MIN / -1"division ๐-fsanitize=unreachableโ the compiler turns the"__builtin_unreachable"call into a diagnostics message call instead ๐ฃ When execution reaches the"__builtin_unreachable"call, the behavior is undefined ๐-fsanitize=vla-boundโ the compiler checks that the size of a variable length array is positive ๐โจ
-fsanitize=nullโ pointer checking ๐ Your program will throw an error message when it tries to dereference a NULL pointer, when a reference (rvalue references included) gets bound to a NULL pointer, or when a method gets invoked on an object pointed at by a NULL pointer. ๐ญ-fsanitize=returnโ return statement checking ๐ฅ If the end of a non-void function is reached without actually returning a value, you get an error message. This one only works in C++ ๐ง.-fsanitize=signed-integer-overflowโ signed integer overflow checking โจ It checks that the result of+,*, and both unary and binary-doesn't overflow in signed arithmetic. Integer promotion rules absolutely have to be taken into account here, so this one is NOT an overflow, bestie ๐:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ array bounds instrumentation ๐ 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โ the stricter, no-nonsense version ๐ฆ Most out-of-bounds accesses get detected, including flexible array members and flexible array member-like arrays. Initializers of variables with static storage still aren't instrumented.-fsanitize=alignmentโ checks pointer alignment ๐ when pointers get 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_sizefunction. Various out-of-bounds pointer accesses get detected.-fsanitize=float-divide-by-zeroโ detects floating-point division by zero ๐ Unlike other similar options, this one is NOT turned on by-fsanitize=undefined, because dividing floats by zero can be a totally legit way to get infinities and NaNs ๐ธ.-fsanitize=float-cast-overflowโ checks floating-point to integer conversions โจ and that the result of the conversion doesn't overflow. Unlike other similar options, this one is NOT enabled by-fsanitize=undefined๐ฌ. It also doesn't play nicely withFE_INVALIDexceptions enabled.-fsanitize=nonnull-attributeโ instruments calls ๐ and checks that NULL values aren't passed to arguments marked as requiring a non-null value by thenonnullfunction attribute.-fsanitize=returns-nonnull-attributeโ instruments return statements in functions marked with thereturns_nonnullfunction attribute ๐ซถ so it can catch NULL values being returned from them.-fsanitize=boolโ instruments loads frombool๐ If a value other than 0/1 gets loaded, you get a run-time error.-fsanitize=enumโ instruments loads from an enum type ๐ If a value outside the range of values for that enum type gets loaded, you get a run-time error.-fsanitize=vptrโ instruments C++ member function calls, member accesses, and some conversions between pointers to base and derived classes ๐ฆ to verify the referenced object has the correct dynamic type.-fsanitize=pointer-overflowโ instruments pointer arithmetic ๐ If the pointer arithmetic overflows, you get a run-time error.-fsanitize=builtinโ instruments arguments to selected builtin functions ๐ ๏ธ If an invalid value gets passed to those arguments, you get a run-time error. For example, passing0as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior, and this option diagnoses it ๐.
While -ftrapv causes traps for signed overflows to be emitted, -fsanitize=undefined gives a diagnostic message ๐
This currently works only for the C family of languages.
-fno-sanitize=allโ disables all previously enabled sanitizers ๐งน
๐จ -fsanitize=all is not allowed, as some sanitizers cannot be used together.
-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks ๐งช It's useful for experimenting with different shadow memory layouts in Kernel AddressSanitizer.-fsanitize-sections=s1,s2,...โ sanitizes global variables in selected user-defined sections ๐ฆ si may contain wildcards.-fsanitize-recover[=opts]โ ๐ช controls the error recovery mode for the sanitizers in the comma-separated listopts. Turn it on for a sanitizer and it'll try to keep running the program like no error happened ๐. That means multiple runtime errors can get reported in one single run, and the exit code might say success even when errors were reported ๐ฌ. The-fno-sanitize-recover=option can flip this: only the first detected error gets reported, and then the program exits with a non-zero exit code.
Right now this only works for -fsanitize=undefined (and its suboptions, except for -fsanitize=unreachable and -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address and -fsanitize=address. For these sanitizers, error recovery is turned on by default, except for -fsanitize=address, where this feature is still experimental. -fsanitize-recover=all and -fno-sanitize-recover=all are also accepted: the former enables recovery for all sanitizers that support it, and the latter disables recovery for all sanitizers that support it.
Even if a recovery mode is turned on compiler-side, it also needs to be enabled on the runtime library side, otherwise the failures are still fatal ๐. The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while the default value for AddressSanitizer is halt_on_error=1. This can be overridden by setting the halt_on_error flag in the corresponding environment variable ๐ท.
๐จ Syntax without an explicit opts parameter is deprecated. It's the same as specifying an opts list of:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ enables sanitization of local variables to catch use-after-scope bugs ๐ This option sets-fstack-reusetonone.-fsanitize-undefined-trap-on-errorโ reports undefined behavior using__builtin_trapinstead of alibubsanlibrary routine ๐ชค The advantage is that thelibubsanlibrary isn't needed and isn't linked in, so this is usable even in freestanding environments.-fsanitize-coverage=trace-pcโ enables coverage-guided fuzzing code instrumentation ๐ Inserts a call to__sanitizer_cov_trace_pcinto every basic block.-fsanitize-coverage=trace-cmpโ enables dataflow-guided fuzzing code instrumentation ๐ง Inserts calls to:__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__sanitizer_cov_trace_cmp8for integral comparisons with both operands variable.__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4or__sanitizer_cov_trace_const_cmp8for integral comparisons with one operand constant.__sanitizer_cov_trace_cmpfor__sanitizer_cov_trace_cmpdfor float or double comparisons.__sanitizer_cov_trace_switchfor switch statements.
-fcf-protection=[full|branch|return|none|check]โ ๐ก๏ธ enables code instrumentation of control-flow transfers to boost program security by checking that target addresses of control-flow transfer instructions (such as indirect function calls, function returns, and indirect jumps) are valid. This stops the flow of control from being diverted to an unexpected target. It's meant to protect against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP).branch: checks validity at the point of indirect branch instructions, i.e. call/jmp instructions.return: checks validity at the point of returning from a function.full: an alias for specifying bothbranchandreturn.none: turns off instrumentation.check: used for the final link with link-time optimization (LTO). An error is issued if LTO object files are compiled with different-fcf-protectionvalues. This value is ignored at compile time.
The macro __CET__ is defined when -fcf-protection is used. The first bit of __CET__ is set to 1 for the value branch, and the second bit of __CET__ is set to 1 for return ๐ฆ.
You can also use the nocf_check attribute to identify which functions and calls should be skipped from instrumentation.
Currently the x86 GNU/Linux target provides an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processors or newer โจ.
๐ NOTE: In Ubuntu 19.10 and later versions,-fcf-protectionis enabled by default for C, C++, ObjC, ObjC++, if none of-fno-cf-protectionnor-fcf-protection=*are found. ๐
-fstack-protectorโ ๐ก๏ธ okay bestie, this one is a total bodyguard for your stack ๐ It makes the compiler sneak in extra code that checks for buffer overflows, like those sneaky stack smashing attacks ๐ซฃ It drops a guard variable into functions with vulnerable objects. That means functions that callalloca, plus functions with buffers that are8 bytesor bigger (so larger than or equal to 8 bytes ๐ ). The guards get set up when a function is entered and get checked again when it exits. If a guard check fails, an error message gets printed and the program exits ๐ Only variables that are actually allocated on the stack count ๐ฅน Optimized-away variables or variables living in registers don't count, sorry ๐-fstack-protector-allโ same energy as-fstack-protector, but now literally every function gets protected ๐-fstack-protector-strongโ the upgraded version of-fstack-protector๐ฅ It protects even more functions, including the ones with local array definitions and the ones with references to local frame addresses. Same rule applies though: only variables actually allocated on the stack count, and optimized-away or register variables don't ๐ซถ-fstack-protector-explicitโ the VIP-list option ๐ It only protects the functions that have thestack_protectattribute, so nobody else gets past the velvet rope ๐-fstack-checkโ generates code to check that you don't go past the boundary of the stack ๐ง You'd want this if you're in an environment with multiple threads ๐งต In a single-threaded environment you rarely need it, because stack overflow is automatically detected on nearly all systems when there's only one stack ๐
That said, this switch doesn't actually do the checking itself ๐ The operating system or the language runtime has to do that. The switch just makes sure the generated code lets them see the stack being extended.
You can also add a string parameter to -fstack-check=:
noโ no checking at all, zero, nada ๐genericโ forces the old-style checking ๐ขspecificโ uses the best checking method, and it's equivalent to bare-fstack-checkโจ
Old-style checking is a generic mechanism that doesn't need any specific target support in the compiler, but it comes with these drawbacks ๐ฌ
- Modified allocation strategy for large objects: they're always allocated dynamically if their size goes over a fixed threshold. Heads up, this may change the semantics of some code โ ๏ธ
- Fixed limit on the size of the static frame of functions: when it's topped by a particular function, stack checking isn't reliable and the compiler issues a warning โ ๏ธ
- Inefficiency: because of both the modified allocation strategy and the generic implementation, code performance gets hampered ๐
Old-style stack checking is also the fallback method for specific if no target support has been added to 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's 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 ๐งฑ With this enabled, the compiler only allocates one page of stack space at a time, and each page gets accessed immediately after allocation. So allocations can't jump over any stack guard page the operating system provides ๐ โโ๏ธ
Most targets don't fully support stack clash protection. On those targets, though, -fstack-clash-protection will protect dynamic stack allocations ๐ซ It may also give limited protection for static stack allocations if the target supports -fstack-check=specific โจ
โ ๏ธ NOTE: In Ubuntu 19.10 and later versions,-fstack-clash-protectionis enabled by default for C, C++, ObjC, ObjC++, unless-fno-stack-clash-protectionis found.
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ these make sure the stack never grows beyond a certain value ๐ง That value is either the value of a register or the address of a symbol. If a larger stack is needed, a signal gets raised at run time ๐ฃ On most targets the signal is raised before the stack overruns the boundary, so you can catch it without taking any special precautions ๐ง
For instance, if the stack starts at absolute address 0x80000000 and grows downwards, you can use the flags -fstack-limit-symbol=__stack_limit and -Wl,--defsym,__stack_limit=0x7ffe0000 to enforce a stack limit of 128KB. Note that this may only work with the GNU linker ๐ง
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 can't allocate any more memory. This is most useful when running threaded programs, because you no longer need to calculate a good stack size to use for each thread ๐งตโจ It's 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 left for the latter code to run in ๐ต If compiling all code, including library code, with -fsplit-stack isn't an option, the linker can fix up these calls so the code compiled without -fsplit-stack always has a large stack. Support for this is in the gold linker in GNU binutils release 2.21 and later ๐ง
-fvtable-verify=[std|preinit|none]โ C++ only, bestie ๐ This turns on (or off, if you use-fvtable-verify=none) the security feature that checks at run time, for every virtual call, that the vtable pointer used for the call 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 the program's execution is immediately halted ๐
This option makes run-time data structures get built at program startup, and those are what verify the vtable pointers ๐๏ธ The std and preinit values control when those data structures get built. In both cases they're built before execution reaches main. 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 shows up multiple times on the command line with different values, none takes the highest priority over both std and preinit, and preinit takes priority over std ๐
-fvtv-debugโ use this with-fvtable-verify=stdor-fvtable-verify=preinit๐ It makes debug versions of the runtime functions for the vtable verification feature get called. It also makes the compiler log which vtable pointers it finds for each class ๐ That info is written to a file namedvtv_set_ptr_data.login the directory named by the environment variableVTV_LOGS_DIRif that's defined, or in the current working directory otherwise ๐
๐๏ธ Heads up: this feature appends data to the log file. If you want a fresh log file, delete any existing one first.
-fvtv-countsโ a debugging flag ๐ Used with-fvtable-verify=stdor-fvtable-verify=preinit, it makes the compiler keep 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 it inserts, and logs that info for each compilation unit ๐ The compiler writes this to a file namedvtv_count_data.login the directory named byVTV_LOGS_DIRif that's defined, or the current working directory otherwise. It also counts the size of the vtable pointer sets for each class and writes that tovtv_class_set_sizes.login the same directory ๐งพ
๐๏ธ Heads up again: this feature appends data to the log files. For fresh log files, delete any existing ones first.
-finstrument-functionsโ generates instrumentation calls for function entry and exit ๐ฌ Just after function entry and just before function exit, the following profiling functions get called with the address of the current function and its call site. (On some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site info might not be available to the profiling functions otherwise ๐)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
The first argument is the address of the start of the current function, which can be looked up exactly in the symbol table ๐
This instrumentation is also done for functions expanded inline in other functions. The profiling calls show where, conceptually, the inline function is entered and exited ๐งฉ That means 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 isn't done. This can be used for things like the profiling functions listed above, high-priority interrupt routines, and any functions from which the profiling functions can't safely be called (perhaps signal handlers, if the profiling routines generate output or allocate memory) ๐ซ๐
-finstrument-functions-exclude-file-list=file,file,... ๐ okay so this one is the file version of skipping instrumentation (same deal as -finstrument-functions, so peek at that one first ๐). Any function defined in a file that matches one of your file entries just doesn't get instrumented. The matching is lowkey loose too: if your string shows up anywhere inside the file name, it counts as a match ๐ซถ.
Here's a vibe 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 ๐
Now, if you literally need a comma inside one of your entries (chaotic, but valid ๐), type two commas, ,,, instead. So -finstrument-functions-exclude-file-list=',,tmp' works, and yes, the single quotes around the whole option are doing important shell-protecting work here ๐ญ
-finstrument-functions-exclude-function-list=sym,sym,...โ ๐ฆ this is the function name sibling of the file list above. Same instrumentation skip, but you're matching function names instead of file names.
The name it matches is the user-visible one, like vector<int> blah(const vector<int> &), NOT the internal mangled gibberish like _Z4blahRSt6vectorIiSaIiEE ๐ Matching is substring-based again: if your sym shows up inside the function name, it's a match. And for C99 and C++ extended identifiers, you have to write the function name in UTF-8, not with universal character names.
-fpatchable-function-entry=N[,M]โ โจ generatesNNOPs right at the start of each function, with the function entry point sitting before the Mth NOP. If you leaveMout, it defaults to0, so the entry point is the address right at the first NOP. Those NOPs reserve extra room you can patch instrumentation into at run time, as long as the code segment is writable. How much room you get is controlled indirectly, through the number of NOPs. The NOP instruction used matches what the internal GCC back-end interfacegen_nopemits. This is target-specific and may also depend on the architecture variant and/or other compilation options ๐ฅ
For run-time identification, the starting addresses of these areas (which are their function entries minus M) also get collected in the "__patchable_function_entries" section of the resulting binary ๐ง
Note that __attribute__ ((patchable_function_entry (N,M))) takes precedence over the command-line option -fpatchable-function-entry=N,M ๐ That means you can increase the area size, or remove it completely, on a single function. If N=0, no pad location is recorded.
The NOP instructions get inserted at---and maybe before, depending on M---the function entry address, even before the prologue. The maximum value of N and M is 65535 ๐
Heads up: that patching trick only works if the code segment is writable, so don't skip that part ๐
โจ Options Controlling the Preprocessor โจ
These options control the C preprocessor, which runs on each C source file before the actual compilation happens ๐ธ
If you use the -E option, nothing gets done except preprocessing. Some of these options only make sense together with -E, because they make the preprocessor output unsuitable for actual compilation.
Besides the options listed here, there are a bunch of options that control search paths for include files, documented in Directory Options. 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. Important bit: the definition gets truncated by embedded newline characters ๐
If you're invoking the preprocessor from a shell or shell-like program, you might need the shell's quoting syntax to protect characters like spaces that have a meaning in shell syntax ๐ซถ
Want a function-like macro on the command line? Write its argument list with surrounding parentheses before the equals sign (if there is one). Parentheses are meaningful to most shells, so you should quote the option. With sh and csh, -D'name(args...)=definition' works โจ
-D and -U options are processed in the order they're given on the command line. All -imacros file and -include file options get processed after all -D and -U options ๐
-U nameโ cancel any previous definition ofname, whether it was built in or provided with a-Doption ๐-include fileโ processfileas if#include "file"appeared as the first line of the primary source file. The twist: the first directory searched forfileis the preprocessor's working directory, not the directory containing the main source file. If it's not found there, it gets searched for in the remainder of the#include "..."search chain as normal ๐ฆ
If multiple -include options are given, the files are included in the order they appear on the command line.
-imacros fileโ exactly like-include, except any output produced by 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 specified by -imacros are processed before all files specified by -include.
-undefโ do not predefine any system-specific or GCC-specific macros. The standard predefined macros stay defined ๐-pthreadโ defines additional macros required for using the POSIX threads library. You should use this option consistently for both compilation and linking. It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets ๐ฅ-Mโ instead of outputting the result of preprocessing, you get a rule suitable formakedescribing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from-includeor-imacroscommand-line options ๐
Unless you specify it explicitly (with -MT or -MQ), the object file name is the name of the source file with any suffix replaced by the object file suffix, and with any leading directory parts removed. If there are many included files, the rule gets split into several lines using \-newline. The rule has no commands ๐
This option does not suppress the preprocessor's debug output, such as -dM. To avoid mixing that debug output with the dependency rules, explicitly specify the dependency output file with -MF, or use an environment variable like DEPENDENCIES_OUTPUT. Debug output is still sent to the regular output stream as normal ๐
Passing-Mto the driver implies-E, and suppresses warnings with an implicit-w. Plan accordingly, bestie ๐
-MMโ like-M, but don't mention header files that are found in system header directories, nor header files that are included, directly or indirectly, from such a header ๐ธ
This implies that the choice of angle brackets or double quotes in an #include directive does not, by itself, determine whether that header appears in -MM dependency output.
-MF fileโ when used with-Mor-MM, this specifies a file to write the dependencies to. If no-MFswitch is given, 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. Iffileis-, then the dependencies are written to stdout ๐-MGโ in conjunction with an option such as-Mrequesting dependency generation,-MGassumes missing header files are generated files and adds them to the dependency list without raising an error. The dependency filename is taken directly from the#includedirective without prepending any path.-MGalso suppresses preprocessed output, since a missing header file makes that useless ๐
This feature is used in automatic updating of makefiles ๐ ๏ธ
-Mno-modulesโ disables dependency generation for compiled module interfaces ๐ฆ-MPโ this instructs CPP to add a phony target for each dependency other than the main file, causing each to depend on nothing. These dummy rules work around errorsmakegives if you remove header files without updating the Makefile to match ๐
This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ changes the target of the rule emitted by dependency generation. By default, CPP takes the name of the main input file, deletes any directory components and any file suffix such as.c, and appends the platform's usual object suffix. That result is the target ๐ง
An -MT option 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 -MT options.
For example, -MT '$(objpfx)foo.o' might give:
$(objpfx)foo.o: foo.c
-MQ targetโ same as-MT, but it quotes any characters which are special to Make.-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
The default target is automatically quoted, as if it were given with -MQ ๐
-MDโ-MDis equivalent to-M -MF file, except that-Eis not implied. The driver determinesfilebased on whether an-ooption is given. If it is, the driver uses its argument but with a suffix of.d. Otherwise, it takes the name of the input file, removes any directory components and suffix, and applies a.dsuffix ๐
If -MD is used in conjunction with -E, any -o switch is understood to specify the dependency output file. But if it's used without -E, each -o is understood to specify a target object file.
Since -E is not implied, -MD can be used to generate a dependency output file as a side effect of the compilation process โญ
-MMDโ like-MDexcept it mentions only user header files, not system header files ๐ซถ-fpreprocessed: ๐ Okay so this one tells the preprocessor "hey, this file is ALREADY preprocessed, don't redo it!" ๐ It skips macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives. Comments still get recognized and removed though, so you can totally pass it a file made with-Cand it'll be fine ๐ซถ. 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, this handles directives but does NOT expand macros. How it acts depends on-Eand-fpreprocessed, so let's break it down bestie ๐.- With
-E, preprocessing is limited to directives like#define,#ifdef, and#error. Macro expansion and trigraph conversion are not performed. The-dDoption is also implicitly enabled. - With
-fpreprocessed, predefinition of command line and most builtin macros is disabled. Contextually dependent macros like__LINE__are handled normally. This lets you compile files that were previously preprocessed with-E -fdirectives-only๐ธ. - With both
-Eand-fpreprocessed, the-fpreprocessedrules take precedence. This gives you full preprocessing of files that were previously preprocessed with-E -fdirectives-only๐.
- With
-fdollars-in-identifiers: ๐ Accepts$in identifiers. Literally that's it, iconic.-fextended-identifiers: โจ Accepts universal character names and extended characters in identifiers. This one is on by default for C99 (and later C standard versions) and C++ ๐.-fno-canonical-system-headers: ๐ When preprocessing, this stops system header paths from being shortened with canonicalization. No shortening, no cap ๐ .-fmax-include-depth=depth: ๐ธ Sets the maximum depth of nested#include. The default is200๐ฅ.-ftabstop=width: ๐ฆ Sets the distance between tab stops. This helps the preprocessor report correct column numbers in warnings or errors, even when tabs show up on the line ๐ . If the value is less than1or greater than100, the option is ignored. The default is8โญ.-ftrack-macro-expansion[=level]: ๐ฅ Tracks token locations across macro expansions, so when a compile error happens inside a macro expansion, the compiler can show you the current macro expansion stack. Heads up though, using this makes the preprocessor and the compiler eat more memory ๐. Thelevelparameter lets you pick how precise the token location tracking is, so you can drop memory usage if you need to.0deactivates this option.1tracks token locations in a degraded mode for minimal memory overhead. In this mode, all tokens resulting from expanding an argument of a function-like macro share the same location.2tracks token locations completely. This is the most memory hungry value ๐.- If you give this option no argument, the default parameter value is
2. - Note that
-ftrack-macro-expansion=2is activated by default ๐.
-fmacro-prefix-map=old=new: ๐ง When preprocessing files living in directoryold, the__FILE__and__BASE_FILE__macros expand as if the files lived in directorynewinstead. This is how you turn an absolute path into a relative one: use.fornew. It can give you more reproducible, location-independent builds ๐ซถ. This option 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. Thecharsetcan be any encoding your system'siconvlibrary routine supports ๐.-fwide-exec-charset=charset: ๐ Sets the wide execution character set, used for wide string and character constants. The default is one ofUTF-32BE,UTF-32LE,UTF-16BE, orUTF-16LE, whichever matches the width ofwchar_tand the big-endian or little-endian byte order being used for code generation โจ. Just like-fexec-charset,charsetcan be any encoding your system'siconvsupports. Heads up though: you'll have problems with encodings that don't fit exactly inwchar_t๐ญ.-finput-charset=charset: ๐ฆ Sets the input character set, used to translate from the input file's character set to the source character set GCC uses. If the locale doesn't specify one, or GCC can't get that info from the locale, the default isUTF-8. This can be overridden by either the locale or this command-line option. Currently the command-line option wins if there's a conflict ๐. Thecharsetcan be any encoding your system'siconvsupports.-fpch-deps: ๐ฅ When you're using precompiled headers, this flag makes the dependency-output flags also list the files from the precompiled header's dependencies. Without it, only the precompiled header gets listed, not the files that were used to create it, since those aren't consulted when a precompiled header is used ๐ .-fpch-preprocess: ๐ธ This lets you use a precompiled header together with-E. It inserts a special#pragma,#pragma GCC pch_preprocess "filename", into the output to mark where the precompiled header was found, plus its filename โจ. When-fpreprocessedis in use, GCC recognizes this#pragmaand loads the PCH ๐ง.- This option is off by default, because the resulting preprocessed output is really only suitable as input to GCC ๐. It gets switched on by
-save-temps. - You should not write this
#pragmain your own code. But it's 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.
- This option is off by default, because the resulting preprocessed output is really only suitable as input to GCC ๐. It gets switched on by
-fworking-directory: ๐ Enables generation of linemarkers in the preprocessor output that let the compiler know the working directory at the time of preprocessing. When this is enabled, the preprocessor emits a second linemarker after the initial one, containing the current working directory followed by two slashes ๐. GCC uses that directory, if it's in the preprocessed input, as the directory it emits as the current working directory in some debugging information formats.- This option is implicitly enabled if debugging information is enabled. You can turn it off with the negated form
-fno-working-directory๐ . - If the
-Pflag is in the command line, this option does nothing, since no#linedirectives get emitted whatsoever ๐.
- This option is implicitly enabled if debugging information is enabled. You can turn it off with the negated form
-A predicate=answer: โญ Makes an assertion with the predicatepredicateand the answeranswer. This form is preferred over the older-A predicate(answer)form, which is still supported, because it doesn't use shell special characters ๐ .-A -predicate=answer: ๐ฆ Cancels an assertion with the predicatepredicateand the answeranswer๐ซถ.-C: ๐ Do not discard comments! All comments get passed through to the output file, except for comments in processed directives, which get deleted along with the directive ๐.- > Be prepared for side effects when you use
-C. It makes the preprocessor 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#๐ญ.
- > Be prepared for side effects when you use
-CC: โจ Do not discard comments, INCLUDING during macro expansion. This is like-C, except comments inside macros also get passed through to the output file wherever the macro is expanded ๐ธ.- On top of the side effects of
-C, the-CCoption 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 ๐. -CCis generally used to support lint comments ๐ง.
- On top of the side effects of
-P: ๐ Inhibits generation of linemarkers in the preprocessor output. This might be useful when you're running the preprocessor on something that isn't C code and will be sent to a program that might get confused by the linemarkers ๐.-traditionaland-traditional-cpp: ๐ฆ These try to imitate pre-standard C preprocessors, as opposed to ISO C preprocessors. See the GNU CPP manual for details ๐.- Note that GCC does NOT otherwise try to emulate a pre-standard C compiler ๐
, and these options are only supported with the
-Eswitch, or when invoking CPP explicitly.
- Note that GCC does NOT otherwise try to emulate a pre-standard C compiler ๐
, and these options are only supported with the
-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, such as MS-DOS ๐พ.-H: ๐ฅ Prints the name of each header file used, in addition to the other normal activities. Each name is indented to show how deep it is in the#includestack ๐ธ. Precompiled header files get printed too, even if they turn out to be invalid. An invalid precompiled header is printed with...x, and a valid one with...!โจ.-dletters: ๐ Makes debugging dumps during compilation, as specified byletters. The flags documented here are the ones relevant to the preprocessor. Other letters are interpreted by the compiler proper, or reserved for future versions of GCC, so they're silently ignored ๐. If you specify letters whose behavior conflicts, the result is > undefined ๐.-dM: Instead of the normal output, this generates a list of#definedirectives for all the macros defined during the execution of the preprocessor, including predefined macros. It's a way of finding 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
Run that and boom, it shows all the predefined macros ๐ โจ
Heads up, bestie ๐ if you use -dM without the -E option, it gets treated as a synonym for -fdump-rtl-mach. Not what you want, so don't sleep on it.
-dDโ Okay, so this is basically-dMwith two twists ๐ฆ. It skips the predefined macros, and it outputs both the#definedirectives and the result of preprocessing. Both kinds of output go to the standard output file.-dNโ Same energy as-dD, but only the macro names get printed, not their expansions ๐ธ-dIโ Adds#includedirectives to the preprocessing result ๐ง-dUโ Like-dD, but way more selective ๐. Only macros that get expanded, or whose definedness gets tested in preprocessor directives, are output. The output is held back until that macro is used or tested, and#undefdirectives also show up for macros that got tested but were undefined at the time.-fdebug-cppโ This one is only lowkey useful if you're debugging GCC itself ๐ฅ. When it's used from CPP or with-E, it dumps debugging information about location maps, and every token in the output gets preceded by the dump of the map its location belongs to. When it's used from GCC without-E, it does absolutely nothing ๐-Wp,optionโ This lets you bypass the compiler driver and passoptionstraight through to the preprocessor. Ifoptionhas commas, it gets split into multiple options at the commas. Here's the tea โ: a lot of options get modified, translated, or interpreted by the compiler driver before they reach the preprocessor, and-Wpforcibly skips that step.
The preprocessor's direct interface is undocumented and subject to change, so whenever possible you should avoid -Wp and let the driver handle the options instead. Trust the driver, bestie ๐ซถ
-Xpreprocessor optionโ Passesoptionalong to the preprocessor. This is your go-to for system-specific preprocessor options that GCC doesn't recognize ๐
If you want to pass an option that takes an argument, you have to use -Xpreprocessor twice, once for the option and once for the argument.
-no-integrated-cppโ By default, GCC does preprocessing as part of input tokenization and parsing (so smooth ๐). With this option, preprocessing becomes its own separate pass before compilation. The appropriate language front end (cc1for C,cc1plusfor C++, andcc1objfor Objective-C) gets invoked twice instead, once for preprocessing only and once for actual compilation of the preprocessed input. This can come in clutch with the-Bor-wrapperoptions if you want an alternate preprocessor or extra processing of the source between normal preprocessing and compilation โจ-flarge-source-filesโ Tells GCC to expect large source files, at the expense of slower compilation and higher memory usage ๐ข
Here's the deal: GCC normally tracks both column numbers and line numbers within 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. That means diagnostics for later lines won't include column numbers. It also means options like -Wmisleading-indentation stop working at that point, although the compiler prints a note if this happens ๐ญ Passing -flarge-source-files significantly increases the number of source lines GCC can process before it stops tracking columns.
๐ Passing Options to the Assembler ๐
You can pass options to the assembler, so go off ๐
-Wa,optionโ Passesoptionto the assembler. Ifoptionhas commas, it gets split into multiple options at the commas.-Xassembler optionโ Passesoptionto the assembler too. Use this for system-specific assembler options that GCC doesn't recognize ๐ง
If you want to pass an option that takes an argument, you have to use -Xassembler twice, once for the option and once for the argument.
๐ฆ Options for Linking ๐ฆ
These options come into play when the compiler links object files into an executable output file. They're meaningless if the compiler isn't doing a link step, so don't waste your energy on them ๐ โโ๏ธ
object-file-nameโ A file name that doesn't end in a special recognized suffix is considered to name an object file or library. (The linker tells objects and libraries apart by looking at the file contents.) If linking happens, these object files are used as input to the linker.-c,-S,-Eโ If any of these options is used, the linker doesn't run, so object file names shouldn't 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 useful to set the type manually ๐ง Here's what each type does:execโ Code generation produces a static binary. In this case-fpicand-fpieare both disabled.dynโ Code generation produces a shared library. In this case-fpicor-fPICis preserved, but not enabled automatically. This lets you build shared libraries without position-independent code on architectures where that's possible, i.e. on x86.pieโ Code generation produces an-fpieexecutable. This gets similar optimizations asexec, except-fpieisn't disabled if it was specified at compilation time.relโ The compiler assumes incremental linking is happening. The sections containing intermediate code for link-time optimization are merged, pre-optimized, and output to the resulting object file. If-ffat-lto-objectsis specified, binary code is also produced for future non-LTO linking. The object file from incremental linking is smaller than a static library made from the same object files, and at link time it also loads faster than a static library, assuming most objects in the library get used.nolto-relโ Configures the compiler for incremental linking where code generation is forced, a final binary is produced, and the intermediate code for later link-time optimization is stripped. When multiple object files get linked together, the resulting code is better optimized than with link-time optimizations disabled (cross-module inlining happens, for example), but most of the benefits of whole program optimizations are lost.
During the incremental link (by -r), the linker plugin defaults to rel. With current interfaces to GNU Binutils, it's not possible to incrementally link LTO objects and non-LTO objects into a single mixed object file. If any object file in an incremental link can't be used for link-time optimization, the linker plugin issues a warning and uses nolto-rel. To keep whole program optimization, it's recommended to link those objects into a static library instead. Alternatively, you can use H.J. Lu's binutils with support for mixed objects ๐ธ
-fuse-ld=bfdโ Uses the bfd linker instead of the default linker ๐-fuse-ld=goldโ Uses the gold linker instead of the default linker โญ-fuse-ld=lldโ Uses the LLVM lld linker instead of the default linker ๐-fuse-ld=moldโ Uses the Modern Linker (mold) instead of the default linker ๐ง-llibrary,-l libraryโ Searches the library namedlibrarywhen linking. (The second version, with the library as a separate argument, is only there for POSIX compliance and isn't recommended ๐)
The -l option gets passed directly to the linker by GCC, so check 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 the shared library unless the -static option is used.
Where you write this option in the command actually matters ๐ The linker searches and processes libraries and object files in the order they're specified. So foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
-lobjcโ You need this special case of the-loption to link an Objective-C or Objective-C++ program ๐-nostartfilesโ Doesn't use the standard system startup files when linking. The standard system libraries are still used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used.-nodefaultlibsโ Doesn'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, such as-static-libgccor-shared-libgcc, are ignored. The standard startup files are still used normally, unless-nostartfilesis used.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These entries are usually resolved by entries in libc. When this option is specified, these entry points should be supplied through some other mechanism, so keep that in mind ๐ฌ
-nolibcโ Doesn't use the C library or the system libraries tightly coupled with it when linking. It still links with the startup files, libgcc, or toolchain-provided language support libraries such as libgnat, libgfortran, or libstdc++, 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. It's meant for bare-board targets where there really is no C library available ๐ค-nostdlibโ Doesn't use the standard system startup files or libraries when linking. No startup files get used, only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as-static-libgccor-shared-libgcc, are ignored ๐ซถ
Okay bestie, so the compiler can sneakily call memcmp, memset, memcpy, and memmove all on its own ๐. Those are usually handled by libc, but when this option is on, you have to supply those entry points some other way ๐
.
One of the standard libraries that -nostdlib and -nodefaultlibs skip is libgcc.a ๐. It's a library of internal helper subroutines GCC uses to work around quirks of certain machines, or to meet special needs for some languages โจ.
Lowkey, you almost always still need libgcc.a even when you're trying to dodge the other standard libraries ๐ซถ. So when you use -nostdlib or -nodefaultlibs, you should usually add -lgcc too. That way you won't have any unresolved references to GCC's internal library subroutines ๐. (An example of one of those is __main, which makes sure C++ constructors get called ๐.)
-e entry,--entry=entryโ sets the program entry point to entry ๐ช. The linker reads this argument, and the GNU linker accepts either a symbol name or an address ๐ง.-pieโ makes a dynamically linked position independent executable on targets that support it ๐ฆ. For predictable results, you also need to use the same set of options you used for compilation (-fpie,-fPIE, or model suboptions) when you pass this linker option ๐.-no-pieโ no PIE for you ๐ . It won't make a dynamically linked position independent executable.-static-pieโ makes a static position independent executable on targets that support it ๐ธ. It's kinda like a static executable, but it can be loaded at any address without needing a dynamic linker โจ. Same deal as-pie: match the compilation options (-fpie,-fPIE, or model suboptions) for predictable results ๐.-pthreadโ links with the POSIX threads library ๐งต. This works on GNU/Linux targets, most other Unix derivatives, and also x86 Cygwin and MinGW targets ๐. On some targets it also sets flags for the preprocessor, so use it consistently for both compiling and linking ๐ .-rโ produces a relocatable object as output ๐งฉ. This is also known as partial linking ๐ฆ.-rdynamicโ passes-export-dynamicto the ELF linker on targets that support it ๐ฅ. This tells the linker to add all symbols to the dynamic symbol table, not just the used ones โจ. You need it for some uses ofdlopen, or to get backtraces from inside a program ๐.-sโ removes all symbol table and relocation information from the executable ๐งน.-staticโ on systems that support dynamic linking, this overrides-pieand stops linking with the shared libraries ๐ซ. On other systems, it does nothing ๐คท.-sharedโ produces a shared object that you can later link with other objects to form an executable ๐ง. Not every system supports this one. For predictable results, match the compilation options (-fpic,-fPIC, or model suboptions) when you use this linker option.[1]-shared-libgcc,-static-libgccโ on systems that provide libgcc as a shared library, these force the use of the shared or static version, respectively ๐ญ. If no shared version of libgcc was built when the compiler was configured, these have no effect.
There are a few situations where an app 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 those libraries, plus the app itself, should use the shared libgcc ๐ซถ.
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable ๐. C++ programs typically use exceptions, so that's the right move โ
.
But if 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 of libgcc, so it links with the static version by default ๐ง . This lets exceptions propagate through those shared libraries without incurring relocation costs at library load time โก.
However, if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ driver, or using -shared-libgcc, so that it's linked with the shared libgcc ๐จ.
-static-libasanโ when-fsanitize=addressis used to link a program, the GCC driver automatically links against libasan ๐ต๏ธ. If libasan is available as a shared library and-staticisn't used, it links against the shared version.-static-libasantells the GCC driver to link libasan statically, without necessarily linking other libraries statically ๐ง.-static-libtsanโ when-fsanitize=threadis used to link a program, the GCC driver automatically links against libtsan ๐งต. If libtsan is available as a shared library and-staticisn't used, it links against the shared version.-static-libtsantells the GCC driver to link libtsan statically, without necessarily linking other libraries statically ๐ง.-static-liblsanโ when-fsanitize=leakis used to link a program, the GCC driver automatically links against liblsan ๐ซง. If liblsan is available as a shared library and-staticisn't used, it links against the shared version.-static-liblsantells the GCC driver to link liblsan statically, without necessarily linking other libraries statically ๐ง.-static-libubsanโ when-fsanitize=undefinedis used to link a program, the GCC driver automatically links against libubsan ๐ซ . If libubsan is available as a shared library and-staticisn't used, it links against the shared version.-static-libubsantells 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, it links against the shared version, which is normally fine ๐. Sometimes, though, you want to freeze the libstdc++ version your program uses without going all the way to a fully static link ๐ง.-static-libstdc++tells theg++driver to link libstdc++ statically, without necessarily linking other libraries statically ๐.-symbolicโ binds references to global symbols when building a shared object ๐. It warns about any unresolved references (unless overridden by the link editor option-Xlinker -z -Xlinker defs) โ ๏ธ. Only a few systems support this one ๐ฅฒ.-T scriptโ 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 to the linker ๐ ๏ธ. Use this to supply system-specific linker options that GCC doesn't recognize ๐ .
If you want to pass an option that takes a separate argument, you must use -Xlinker twice, once for the option and once for the argument ๐ฏ. For example, to pass -assert definitions, you write -Xlinker -assert -Xlinker definitions. Writing -Xlinker "-assert definitions" does NOT work, because it passes the entire string as a single argument, and that's not what the linker expects ๐
โโ๏ธ.
When using the GNU linker, it's usually more convenient to pass arguments to linker options with the option=value syntax instead of as separate arguments ๐ง . For example, you can write -Xlinker -Map=output.map 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 ๐. 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 ๐บ๏ธ. With the GNU linker, you can get the same effect with-Wl,-Map=output.mapโจ.
NOTE: In Ubuntu 8.10 and later versions, for LDFLAGS, the option-Wl,-z,relrois used. To disable it, use-Wl,-z,norelro๐จ.
-u symbolโ pretends the symbol symbol is undefined, to force linking of the library modules that define it ๐ญ. You can use-umultiple times with different symbols to force loading of additional library modules ๐ซ.-z keywordโ-zis passed straight on to the linker along with the keyword. Check the documentation for your linker to see the permitted values and what they mean ๐.
๐๏ธ Options for Directory Search
These options specify the directories to search for header files, for libraries, and for parts of the compiler ๐.
-I dir,-iquote dir,-isystem dir,-idirafter dirโ adds the 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 specified with -iquote only apply to the quote form of the directive, #include "file" ๐ฌ. Directories specified with -I, -isystem, or -idirafter apply to lookup for both #include "file" and #include <file> directives ๐.
You can specify any number or combination of these options on the command line to search for header files in several directories ๐งบ. The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first.
- okay so for the quote form of the include directive (
#include "file"), the-iquotedirectories get searched left-to-right, in the order they show up on the command line โจ - next up, the
-Idirectories get scanned left-to-right ๐ฆ - then the
-isystemdirectories get scanned left-to-right too ๐ - then the standard system directories get scanned ๐ธ
- last but not least, the
-idirafterdirectories get scanned left-to-right ๐ซถ
bestie, you can use -I to override a system header file and swap in your own version, bc these directories get searched before the standard system header file directories ๐ but (and this is a big one) don't use this option to add directories with vendor-supplied system header files. use -isystem for that ๐
The -isystem and -idirafter options also mark the directory as a system directory, so it gets the same special treatment as the standard system directories โจ
If a standard system include directory, or a directory given with -isystem, is also given with -I, the -I option gets ignored ๐ The directory still gets searched, but as a system directory at its normal spot in the system include chain. This is so GCC's procedure to fix buggy system headers and the ordering for the #include_next directive don't get accidentally messed with ๐ง 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 one is deprecated, so yeah, we're not really using it anymore
Heads up:-I-is deprecated. Please use-iquoteinstead for-Idirectories that come before the-I-, and remove the-I-option.
Any directories given with -I before -I- only get searched for headers requested with #include "file". They are not searched for #include <file>. If extra directories are given with -I after the -I-, those get searched for all #include directives.
In addition, -I- stops the directory of the current file from being used as the first search directory for #include "file". There is no way to override this effect of -I-.
-iprefix prefixโ setsprefixas the prefix for later-iwithprefixoptions ๐ if the prefix stands for a directory, 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 where-Iwould go, and-iwithprefixputs it where-idirafterwould go-isysroot dirโ this is like--sysroot, but it only applies to header files (except on Darwin targets, where it applies to both header files and libraries) ๐ฆ check the--sysrootoption for more info-imultilib dirโ usesdiras a subdirectory of the directory containing target-specific C++ headers ๐-nostdincโ don't search the standard system directories for header files ๐ only the directories you explicitly give with-I,-iquote,-isystem, and/or-idirafter(plus the directory of the current file, if appropriate) get searched-nostdinc++โ skip the C++-specific standard directories when searching for header files, but still search the other standard directories ๐ (this one is used when building the C++ library)-iplugindir=dirโ sets the directory to search for plugins passed by-fplugin=nameinstead of-fplugin=path/name.so๐ง this isn't meant for regular users; only the driver passes it-Ldirโ adds directorydirto the list of directories to be searched for-l๐ธ-Bprefixโ this is where you tell the compiler where to find its own executables, libraries, include files, and data files ๐
The compiler driver program runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for each program it tries to run, both with and without machine/version/ for the corresponding target machine and compiler version.
For each subprogram to be run, the compiler driver first tries the -B prefix, if any. If that name isn't found, or if -B isn't specified, the driver tries two standard prefixes, /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those results in a file name that is found, the unmodified program name is searched for using the directories specified in your PATH environment variable.
The compiler checks to see if the path provided by -B refers to a directory, and if necessary it adds a directory separator character at the end of the path.
-B prefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into -L options for the linker. They also apply to include files in the preprocessor, because the compiler translates these options into -isystem options for the preprocessor. In this case, the compiler appends include to the prefix.
The runtime support file libgcc.a can also be searched for using the -B prefix, if needed. If it isn't found there, the two standard prefixes above are tried, and that is all. The file is 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, if the path provided by -B is [dir/]stageN/, where N is a number in the range 0 to 9, then it is replaced by [dir/]include. This is to help with boot-strapping the compiler ๐
-no-canonical-prefixesโ don't expand any symbolic links, resolve references to/../or/./, or make the path absolute when generating a relative prefix ๐ฆ--sysroot=dirโ usesdiras the logical root directory for headers and libraries ๐ for example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it instead searchesdir/usr/includeanddir/usr/lib
If you use both this option and the -isysroot option, then the --sysroot option applies to libraries, but the -isysroot option applies to header files.
The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker does not support this option, the header file aspect of --sysroot still works, but the library aspect does not.
--no-sysroot-suffixโ for some targets, a suffix gets added to the root directory specified with--sysroot, depending on the other options used, so headers may be found indir/suffix/usr/includeinstead ofdir/usr/include๐ this option turns off adding that suffix
โจ Options for Code Generation Conventions โจ
These machine-independent options control the interface conventions used in code generation ๐
Most of them have both positive and negative forms; the negative form of -ffoo is -fno-foo. Only one of the forms is listed below, 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 reuse only for user defined local variables with names, andnonedisables stack reuse completely. The default value isall. You need this option 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 extending local lifetime is likely to break with the stack reuse optimization ๐ญ
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example:
struct A
{
A(int k) : i(k), j(k) { }
int i;
int j;
};
A *ap;
void foo(const A& ar)
{
ap = &ar;
}
void bar()
{
foo(A(10)); // temp object's lifetime ends when foo returns
{
A a(20);
....
}
ap->i+= 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
}
The lifetime of a compiler generated temporary is well defined by the C++ standard. When the lifetime of a temporary ends, and if the temporary lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range 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 the aggressive stack reuse can lead to runtime errors ๐ This option is used to control the temporary stack reuse optimization โจ
-ftrapvโ generates traps for signed overflow on addition, subtraction, and multiplication operations ๐-ftrapvand-fwrapvoverride each other, so 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: okay bestie, this one tells the compiler to assume that signed addition, subtraction and multiplication overflow wraps around using twos-complement representation ๐ง It turns some optimizations on and others off โจ
-ftrapv and -fwrapv are lowkey rivals, so -ftrapv -fwrapv on the command line means -fwrapv wins ๐ But only the active options count, so -ftrapv -fwrapv -fno-wrapv leaves -ftrapv in charge ๐
-fwrapv-pointer: the pointer version ๐ฆ It assumes pointer arithmetic overflow on addition and subtraction wraps around using twos-complement representation. It also disables some optimizations that would otherwise assume pointer overflow is invalid ๐-fstrict-overflow: this one is giving opposite energy ๐ It implies-fno-wrapv -fno-wrapv-pointer, and when you negate it, it implies-fwrapv -fwrapv-pointer๐-fexceptions: enables exception handling ๐ฅ It generates the extra code needed to propagate exceptions. On some targets this also means GCC generates frame unwind information for all functions, which can add a lot of data size overhead, though it doesn't change execution speed ๐ญ
If you don't specify this option, GCC turns it on by default for languages like C++ that normally need exception handling, and turns it off for languages like C that don't ๐ธ You might still need to enable it when compiling C code that has to play nicely with exception handlers written in C++ ๐ซถ You might also want to disable it if you're compiling older C++ programs that don't use exception handling.
-fnon-call-exceptions: generates code that lets trapping instructions throw exceptions โก Heads up, this needs platform-specific runtime support that doesn't exist everywhere. It also only lets trapping instructions (memory references or floating-point instructions) throw exceptions. It can't throw exceptions from arbitrary signal handlers like "SIGALRM" ๐ โโ๏ธ-fdelete-dead-exceptions: instructions that might throw exceptions but don't otherwise contribute to the program's execution can be optimized away ๐๏ธ This is enabled by default for the Ada compiler, which the Ada language specification allows. Optimization passes that remove dead exceptions are turned on independently at different optimization levels.-funwind-tables: similar to-fexceptions, except it only generates any needed static data and doesn't touch the generated code in any other way ๐ฆ You usually don't need to turn this on yourself. A language processor that needs this handling will enable 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 garbage collector showing up mid-run ๐-fno-gnu-unique: this one is a whole plot ๐ With a recent GNU assembler and C library, the C++ compiler uses the "STB_GNU_UNIQUE" binding so that definitions of template static data members and static local variables in inline functions stay unique, even with "RTLD_LOCAL" in the mix. That's needed so a library used by two different "RTLD_LOCAL" plugins doesn't disagree about the binding of a symbol. The tradeoff? It makesdlcloseget ignored for affected DSOs ๐ฌ So if your program relies on reinitializing a DSO throughdlcloseanddlopen, you can use-fno-gnu-unique.-fpcc-struct-return: returns "short" "struct" and "union" values in memory, like longer ones, instead of in registers ๐งบ It's less efficient, but the perk is that files compiled by GCC can be intercallable with files built by other compilers, especially the Portable C Compiler (pcc) ๐ค
The exact convention for returning structures in memory depends on the target configuration macros.
Short structures and unions are the ones whose size and alignment match some integer type.
Warning: code compiled with-fpcc-struct-returnis not binary compatible with code compiled with-freg-struct-return. Only use it if you need to conform to a non-default application binary interface ๐จ
-freg-struct-return: returns "struct" and "union" values 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 goes with whichever convention is standard for the target. If there isn't a standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases GCC gets to choose the standard, and it picked the more efficient register return option ๐
Warning: code compiled with-freg-struct-returnis not binary compatible with code compiled with-fpcc-struct-return. Only use it if you need to conform to a non-default application binary interface ๐จ
-fshort-enums: gives an "enum" type only as many bytes as it needs for its declared range of possible values ๐ Specifically, the "enum" type becomes equivalent to the smallest integer type with enough room.
Warning: -fshort-enums makes GCC generate code that isn't binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface ๐จ
-fshort-wchar: overrides the underlying type for "wchar_t" to be "short unsigned int" instead of the target's default ๐ This one is useful for building programs that run under WINE.
Warning: -fshort-wchar makes GCC generate code that isn't binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface ๐จ
-fcommon: in C code, this controls where global variables defined without an initializer get placed. These are called tentative definitions in the C standard ๐ง They're different from declarations of a variable with the "extern" keyword, which don't allocate storage.
The default is -fno-common, which means the compiler places uninitialized global variables in the BSS section of the object file. This stops the linker from merging tentative definitions, so you get a multiple-definition error if the same variable is accidentally defined in more than one compilation unit ๐
โโ๏ธ
-fcommon puts uninitialized global variables in a common block instead. That lets the linker resolve all tentative definitions of the same variable across different compilation units to the same object, or to a non-tentative definition. It's inconsistent with C++, and on many targets it costs some speed and code size on global variable references ๐ฌ It's mainly useful for getting legacy code to link without errors.
-fno-ident: ignores the "#ident" directive ๐-finhibit-size-directive: doesn't output a ".size" assembler directive, or anything else that would cause trouble if the function gets split in the middle with the two halves placed far apart in memory ๐งฉ This is used when compiling crtstuff.c. Unless you're doing that, you shouldn't need it ๐-fverbose-asm: puts extra commentary into the generated assembly 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 out the extra info. 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.
Check out this C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
Compiling it to (x86_64) assembly with -S, and sending the result straight to stdout with -o -:
gcc -S test.c -fverbose-asm -Os -o -
gives output similar to this:
.file "test.c"
# GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
[...snip...]
# options passed:
[...snip...]
.text
.globl test
.type test, @function
test:
.LFB0:
.cfi_startproc
# test.c:4: int total = 0;
xorl %eax, %eax # <retval>
# test.c:6: for (i = 0; i < n; i++)
xorl %edx, %edx # i
.L2:
# test.c:6: for (i = 0; i < n; i++)
cmpl %edi, %edx # n, i
jge .L5 #,
# test.c:7: total += i * i;
movl %edx, %ecx # i, tmp92
imull %edx, %ecx # i, tmp92
# test.c:6: for (i = 0; i < n; i++)
incl %edx # i
# test.c:7: total += i * i;
addl %ecx, %eax # tmp92, <retval>
jmp .L2 #
.L5:
# test.c:10: }
ret
.cfi_endproc
.LFE0:
.size test, .-test
.ident "GCC: (GNU) 7.0.0 20160809 (experimental)"
.section .note.GNU-stack,"",@progbits
The comments are meant for humans rather than machines, so the exact format of them is subject to change ๐
-frecord-gcc-switchesโ okay so this one makes the compiler stash the exact command line you used to invoke it inside the object file it's making ๐งพโจ It's only implemented on some targets, and the exact format depends on the target and binary file format, but it usually shows up as a section full of ASCII text ๐ Don't mix it up with-fverbose-asm, though. That one only drops info into the assembler output as comments, so it never reaches the object file ๐ And see also-grecord-gcc-switchesfor another way to store compiler options in the object file ๐-fpicโ main character energy for shared libraries ๐ This generates position-independent code (PIC) that's suitable for a shared library, as long as the target machine supports it. The code reaches every constant address through a global offset table (GOT). The dynamic loader fills in the GOT entries when the program starts (the dynamic loader isn't part of GCC, it's part of the operating system, bestie ๐ ). If the GOT size for the linked executable goes over a machine-specific maximum, the linker throws an error saying-fpicdoesn't work, and in that case you just recompile with-fPICinstead ๐ญ (The maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit ๐ซถ.)
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โ the upgraded version ๐ If it's supported for the target machine, this 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โ these two are giving similar vibes to-fpicand-fPIC๐ง The difference is that the generated position-independent code can only be linked into executables, not shared libraries ๐ Usually these are used to compile code that will get linked using the-pieGCC option ๐
Both -fpie and -fPIE define the macros "__pie__" and "__PIE__". The macros have the value 1 for -fpie and 2 for -fPIE โจ
-fno-pltโ no PLT for external function calls in position-independent code, bestie ๐ โโ๏ธ Instead, the callee address gets loaded at call sites from the GOT, and then the code branches to it ๐ซถ This leads to more efficient code because it gets rid of PLT stubs and exposes GOT loads to optimizations ๐ฅ On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in a specific register, this gives the compiler more register allocation freedom ๐ Heads up, though: lazy binding requires use of the PLT, so with-fno-pltall external symbols are resolved at load time ๐
Alternatively, the function attribute "noplt" can be used to avoid calls through the PLT for specific external functions ๐ฆ
In position-dependent code, a few targets also convert calls to functions that are marked to not use the PLT so they use the GOT instead ๐
-fno-jump-tablesโ don't use jump tables forswitchstatements, even where they'd be more efficient than other code generation strategies ๐ This one is handy alongside-fpicor-fPICwhen you're building code that forms part of a dynamic linker and can't reference the address of a jump table ๐ On some targets, jump tables don't require a GOT, so this option isn't needed there โจ-fno-bit-testsโ same energy as above, but for bit tests. Don't use them forswitchstatements, even where they'd be more efficient than other code generation strategies ๐-ffixed-regโ this one is the boss move ๐ Treat the register named reg as a fixed register, so the generated code should never refer to it (except maybe as a stack pointer, frame pointer, or in some other fixed role) ๐
reg has to be the name of a register. The accepted register names are machine-specific and are defined in the REGISTER_NAMES macro in the machine description macro file ๐ง
This flag doesn't have a negative form, because it specifies a three-way choice ๐
-fcall-used-regโ treat the register named reg as an allocable register that gets clobbered by function calls ๐ฆ It may be allocated for temporaries or variables that don't live across a call. Functions compiled this way do not save and restore the register reg ๐ซถ
It is an error to use this flag with the frame pointer or stack pointer ๐ Using this flag for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results.
โ ๏ธ Don't do it, babe. Using this flag on registers with fixed pervasive roles in the machine's execution model produces disastrous results.
This flag doesn't have a negative form, because it specifies a three-way choice ๐
-fcall-saved-regโ treat the register named reg as an allocable register that gets saved by functions ๐ธ It may be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restore the register reg if they use it โจ
It is an error to use this flag with the frame pointer or stack pointer ๐ Using this flag for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results.
๐ A different sort of disaster happens if you use this flag on a register that function values may be returned in.
This flag doesn't have a negative form, because it specifies a three-way choice ๐
-fpack-struct[=n]โ without a value, this packs all structure members together with no holes ๐ฆ When you give a value (which must be a small power of two), structure members get packed according to that value, which is the maximum alignment (so objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location ๐
โ ๏ธ Heads up, bestie: -fpack-struct makes GCC generate code that isn't binary compatible with code generated without that switch ๐ญ It also makes the code suboptimal, so only use it to conform to a non-default application binary interface ๐ซถ
-fleading-underscoreโ this and its counterpart,-fno-leading-underscore, forcibly change the way C symbols are represented in the object file ๐งธ One use is to help link with legacy assembly code ๐
โ ๏ธ -fleading-underscore makes GCC generate code that isn't binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface, and know that not all targets provide complete support for this switch ๐
-ftls-model=modelโ alter the thread-local storage model that gets used ๐งต The model argument 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 that aren't visible outside of the translation unit, or if-fpicisn't given on the command line ๐ซถ
Without -fpic, the default is initial-exec. With -fpic, the default is global-dynamic โจ
-ftrampolinesโ for targets that normally need trampolines for nested functions, this always generates them instead of using descriptors ๐ฆ For targets that don't need them, like HP-PA or IA-64, it does nothing ๐
A trampoline is a small piece of code that gets created at run time on the stack when the address of a nested function is taken. It's used to call the nested function indirectly. Because of that, it requires the stack to be made executable for the program to work properly ๐ญ
-fno-trampolines is enabled by default on a language-by-language basis, so the compiler can avoid generating trampolines when it works out that's safe, and replace them with descriptors ๐ง Descriptors are made up of data only, but the generated code has to be prepared to deal with them. As of this writing, -fno-trampolines is enabled by default only for Ada ๐
โ ๏ธ 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 ๐
-fvisibility=[default|internal|hidden|protected]โ okay, this one is a whole vibe ๐ It sets the default ELF image symbol visibility to the option you pick. All symbols get marked with this unless they're overridden within the code. Using this feature 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, default always means public, i.e., available to be linked against from outside the shared object ๐ protected and internal are pretty useless in real-world usage, so the only other commonly used option is hidden ๐
If -fvisibility isn't specified, the default is default, i.e., every symbol is made public ๐ธ
A good explanation of the benefits of ensuring ELF symbols have the correct visibility is given by "How To Write Shared Libraries" by Ulrich Drepper (which can be found at <https://www.akkadia.org/drepper/>) ๐ A superior solution, made possible by this option, to marking things hidden when the default is public is to make the default hidden and mark things public instead ๐ซถ This is the norm with DLLs on Windows. With -fvisibility=hidden and __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 ๐
Okay so bestie, visibility is a whole vibe ๐
If you're adding it to code that already exists, #pragma GCC visibility is your best friend ๐ You wrap the declarations you want to control with #pragma GCC visibility push(hidden) and close it with #pragma GCC visibility pop ๐ฆ Visibility is part of the API contract, so new code should always say what its visibility is whenever it isn't the default. Anything only used inside the local DSO should be marked hidden explicitly, which avoids PLT indirection overheads ๐ญ It also makes the code super readable and self-documenting, so the whole team can see what's going on at a glance โจ Also, thanks to the ISO C++ rules, operator new and operator delete have to be default visibility, no exceptions ๐
Heads up though: headers from outside your project, especially system headers and headers from other libraries you use, might not be expecting anything other than default visibility ๐ If that happens, you may need to put #pragma GCC visibility push(default) right before including them.
extern declarations aren't affected by -fvisibility, which means a ton of your code can be recompiled with -fvisibility=hidden and you won't have to change a thing ๐ธ Lowkey though, calls to extern functions with no explicit visibility go through the PLT, so it's way more effective to use __attribute ((visibility)) and/or #pragma GCC visibility to tell the compiler which extern declarations should be treated as hidden ๐ฅ
Also, -fvisibility does affect C++ vague linkage entities. So if an exception class is getting thrown between DSOs, you have to mark it with default visibility explicitly so the type_info nodes get unified between the DSOs ๐
If you want the full tea on all of these techniques, their benefits, and how to use them, check out <http://gcc.gnu.org/wiki/Visibility> ๐ง
-fstrict-volatile-bitfieldsโ forces volatile bit-field accesses to be a single access at the width of the field's type ๐
This is the option you want when accesses to volatile bit-fields (or other structure fields, though the compiler usually respects those types anyway) need to be one single access at the width of the field's type, aligned to a natural alignment if that's possible. For example, targets with memory-mapped peripheral registers might need every access to be 16 bits wide. With this flag, you can declare all the peripheral bit-fields as unsigned short (assuming short is 16 bits on those targets) to force GCC into 16-bit accesses, instead of a maybe-more-efficient 32-bit access ๐
If this option is disabled, the compiler goes for the most efficient instruction it can find ๐ง In the example above, that might be a 32-bit load, even though it touches bytes that don't contain any part of the bit-field, or memory-mapped registers that have nothing to do with the one being updated. Yikes ๐ฌ
When something like the packed attribute is applied to a structure field, it might not be possible to access that field with a single read or write that's correctly aligned for the target machine. In that case, GCC falls back to generating multiple accesses, rather than code that will 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 the bits of the field's type as bit-field members ๐
The default value of this option is determined by the application binary interface (ABI) for the target processor ๐
-fsync-libcallsโ controls whether any out-of-line instance of the__syncfamily can be used to implement the C++11__atomicfamily ๐ฆ
The default is enabled, so the only useful form of this option is -fno-sync-libcalls ๐
This option is used in the implementation of the libatomic runtime library โจ
โจ GCC Developer Options โจ
This section is all about command-line options that are mainly interesting to GCC developers, like options that help with compiler testing and investigating compiler bugs and compile-time performance problems ๐ That includes options that produce debug dumps at various points in the compilation, options that print statistics like memory use and execution time, and options that print info about GCC's configuration, like where it searches for libraries ๐ Honestly, you should rarely need any of these for ordinary compilation and linking tasks, 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 omitted, GCC builds a default dump file name by concatenating the base dump file name, a pass number, a phase letter, and the pass name โจ The base dump file name is the name of the output file the compiler produced, if you explicitly specified one and it isn't an executable. Otherwise, it's the source file name ๐ง The pass number comes from the order passes are registered with the compiler's pass manager. That's usually the same as the order of execution, 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 are created in the directory of the output file ๐ซถ
-fcallgraph-info,-fcallgraph-info=MARKERSโ makes the compiler output callgraph information for your program, one per object file ๐
The info is generated in the common VCG format. You can decorate it with extra per-node and/or per-edge information by adding a comma-separated list of markers. When the su marker is specified, the callgraph is decorated with stack usage information, which is equivalent to -fstack-usage ๐ When the da marker is specified, the callgraph is decorated with information about dynamically allocated objects ๐
When you're compiling with -flto, no callgraph information gets output along with the object file ๐ At LTO link time, -fcallgraph-info may generate multiple callgraph information files right 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 letters ๐ฅ
This is for debugging the RTL-based passes of the compiler, so it's very much a deep dive ๐ง Some -dletters switches have a different meaning when -E is used for preprocessing โ ๏ธ
Debug dumps can be enabled with a -fdump-rtl switch or with some -d option letters. Here are the possible letters you can use in pass and letters, and what they mean ๐
-fdump-rtl-alignmentsโ dumps after branch alignments have been computed ๐-fdump-rtl-asmconsโ dumps after fixing RTL statements that have unsatisfied in/out constraints ๐ ๏ธ-fdump-rtl-auto_inc_decโ dumps after auto-inc-dec discovery. This pass only runs on architectures that have auto inc or auto dec instructions ๐ฏ-fdump-rtl-barriersโ dumps after cleaning up the barrier instructions ๐งน-fdump-rtl-bbpartโ dumps after partitioning hot and cold basic blocks ๐ฅโ๏ธ-fdump-rtl-bbroโ dumps after block reordering ๐-fdump-rtl-btl1,-fdump-rtl-btl2โ these enable dumping after the two branch target load optimization passes ๐ฆ-fdump-rtl-bypassโ dumps after jump bypassing and control flow optimizations ๐ฆ-fdump-rtl-combineโ dumps after the RTL instruction combination pass ๐งฉ-fdump-rtl-compgotosโ dumps after duplicating the computed gotos ๐-fdump-rtl-ce1,-fdump-rtl-ce2,-fdump-rtl-ce3โ these enable dumping after the three if conversion passes ๐-fdump-rtl-cprop_hardregโ dumps after hard register copy propagation ๐-fdump-rtl-csaโ dumps after combining stack adjustments ๐ฅ-fdump-rtl-cse1,-fdump-rtl-cse2โ these enable dumping after the two common subexpression elimination passes ๐ช-fdump-rtl-dceโ dumps after the standalone dead code elimination passes ๐๏ธ-fdump-rtl-dbrโ dumps after delayed branch scheduling โณ-fdump-rtl-dce1,-fdump-rtl-dce2โ these 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 enable dumping after the two forward propagation passes โก๏ธ-fdump-rtl-gcse1,-fdump-rtl-gcse2โ these enable dumping after global common subexpression elimination ๐-fdump-rtl-init-regsโ 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 enable dumping after the basic block scheduling passes ๐๏ธ-fdump-rtl-reeโ ๐งน Dumps right after sign/zero extension elimination, so you can see the cleanup happen.-fdump-rtl-seqabstrโ ๐ Dumps after common sequence discovery, once the repeated code gets spotted.-fdump-rtl-shortenโ โ๏ธ Dumps after branches get shortened.-fdump-rtl-siblingโ ๐ฏ Dumps after sibling call optimizations.-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ ๐ฐ These five switches each give you a dump after one of five rounds of instruction splitting. Bestie, that's five slices of the same cake ๐ญ-fdump-rtl-smsโ ๐ถ Dumps after modulo scheduling. This pass only runs on some architectures, so don't panic if it's missing ๐-fdump-rtl-stackโ ๐ฅ Dumps after GCC's "flat register file" registers get converted into the x87's stack-like registers. This pass only runs on x86 variants ๐ป-fdump-rtl-subreg1,-fdump-rtl-subreg2โ ๐งฉ These two dump after the two subreg expansion passes, one each.-fdump-rtl-unshareโ ๐ Dumps after all RTL has been unshared.-fdump-rtl-vartrackโ ๐ Dumps after variable tracking.-fdump-rtl-vregsโ ๐ Dumps after virtual registers have been turned into hard registers.-fdump-rtl-webโ ๐ธ๏ธ Dumps after live range splitting.-fdump-rtl-regclass,-fdump-rtl-subregs_of_mode_init,-fdump-rtl-subregs_of_mode_finish,-fdump-rtl-dfinit,-fdump-rtl-dfinishโ ๐ซฅ These dumps are defined, but they always produce empty files, so no cap, don't waste your time on them.
โ ๏ธ Heads up: all five of those empty-file dumps are a total vibe check fail. They exist, but they will always give you nothing ๐ญ
-da,-fdump-rtl-allโ ๐ Produces every dump listed above. Maximum chaos, maximum files.-dAโ ๐๏ธ Annotates the assembler output with miscellaneous debugging information.-dDโ ๐ Dumps all macro definitions at the end of preprocessing, on top of the normal output.-dHโ ๐ Produces a core dump whenever an error occurs. Iconic energy, but it's giving a lot of files.-dpโ ๐ท๏ธ Annotates the assembler output with a comment saying which pattern and alternative got used. The length and cost of each instruction get printed too.-dPโ ๐ Dumps the RTL in the assembler output as a comment before each instruction. This also turns on the-dpannotation, so it's two-for-one bestie ๐ซถ-dxโ ๐ง Just generates RTL for a function instead of compiling it. This is usually used with-fdump-rtl-expand.-fdump-debugโ ๐ Dumps the debugging information generated during the debug generation phase.-fdump-earlydebugโ ๐ฑ Dumps the debugging information generated during the early debug generation phase.-fdump-noaddrโ ๐ When you're doing debugging dumps, this suppresses address output. It makes runningdiffon dumps way more doable when the compiler binaries differ, or when the text / bss / data / heap / stack / dso start locations differ.-freport-bugโ ๐จ If an internal compiler error (ICE) happens, this collects and dumps debug information into a temporary file for you.-fdump-unnumberedโ ๐ข When you're doing debugging dumps, this suppresses instruction numbers and address output. It makesdiffway easier for compiler invocations with different options, especially with and without-g.-fdump-unnumbered-linksโ ๐ When doing debugging dumps (see the-doption above), this suppresses instruction numbers for the links to the previous and next instructions in a sequence.-fdump-ipa-switch,-fdump-ipa-switch-optionsโ ๐ง These control the dumping at various stages of inter-procedural analysis language tree to a file. The file name is made by appending a switch-specific suffix to the source file name, and it gets created in the same directory as the output file. Here are the possible dumps:allโ enables all inter-procedural analysis dumps ๐cgraphโ dumps info about call-graph optimization, unused function removal, and inlining decisions ๐ธ๏ธinlineโ dumps after function inlining ๐ฆ
You can also add -optimized, -missed, -note, or -all, which mean the same thing as they do for -fopt-info. They default to -optimized if you skip them.
For example, -fdump-ipa-inline-optimized-missed will emit info on callsites that got inlined, and callsites that didn't ๐
By default, the dump has messages about successful optimizations (the same as -optimized), plus low-level details about the analysis ๐
-fdump-langโ ๐ฃ๏ธ Dumps language-specific information. The file name is made by appending.langto the source file name.-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ ๐๏ธ These control the dumping of language-specific information. The options and filename parts work the same way as they do in the-fdump-treeoption. Here are the switch values you can use:allโ enables all language-specific dumps ๐classโ dumps class hierarchy information. Virtual table information gets emitted unless you specifyslim. This is C++ only ๐moduleโ dumps module information. The optionslineno(locations),graph(reachability),blocks(clusters),uid(serialization),alias(mergeable),asmname(Elrond),eh(mapper) &vops(macros) may give you extra info. This is C++ only ๐rawโ dumps the raw internal tree data. This is C++ only ๐งฑ
-fdump-passesโ ๐ Prints the list of optimization passes that the current command-line options turn on and off, straight to stderr.-fdump-statistics-optionโ ๐ Enables and controls dumping of pass statistics into a separate file. The file name is made by appending a suffix that ends in.statisticsto the source file name, and it's created in the same directory as the output file. With the -option form,-statssums the counters over the whole compilation unit, while-detailsdumps every event as the passes generate it. With no option, the default is to sum counters for each function compiled.-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filenameโ ๐ณ These control the dumping at various stages of processing the intermediate language tree 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 works with every dump, and the ones that don't make sense get ignored. These options are available:addressโ prints the address of each node. This is usually not meaningful, since it changes depending on the environment and source file. Its main use is tying a dump file to a debug environment ๐asmnameโ ifDECL_ASSEMBLER_NAMEhas been set for a given decl, uses that in the dump instead ofDECL_NAME. Its main use is working backward from mangled names in the assembly file ๐slimโ when dumping front-end intermediate representations, stops members of a scope or body of a function from being dumped just because that scope was reached. Those items only get dumped when some other path reaches them directly. When dumping pretty-printed trees, this skips the bodies of control structures. When dumping RTL, it prints the RTL in slim (condensed) form instead of the default LISP-like representation ๐งrawโ prints a raw representation of the tree. By default, trees get pretty-printed into a C-like representation ๐งพdetailsโ enables more detailed dumps (not every dump option honors this). It also includes info from the optimization passes ๐ฌstatsโ enables dumping various statistics about the pass (not every dump option honors this) ๐blocksโ enables showing basic block boundaries (disabled in raw dumps) ๐งฑgraphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a representation of the control flow graph tofile.passid.pass.dot, which is suitable for viewing with GraphViz. Each function in the file gets pretty-printed as a subgraph, so GraphViz can render them all in a single plot ๐ธ๏ธ This option only works for RTL dumps right now, and the RTL is always dumped in slim form.vopsโ enables showing virtual operands for every statement ๐งฎlinenoโ enables showing line numbers for statements ๐uidโ enables showing the unique ID (DECL_UID) for each variable ๐verboseโ enables showing the tree dump for each statement ๐ehโ enables showing the EH region number holding each statement ๐scevโ enables showing scalar evolution analysis details ๐optimizedโ enables showing optimization information (only available in certain passes) โmissedโ enables showing missed optimization information (only available in certain passes) โnoteโ enables other detailed optimization information (only available in certain passes) ๐๏ธallโ turns on all options, exceptraw,slim,verboseandlineno๐optallโ turns on all optimization options, i.e.,optimized,missed, andnote๐
Okay, so, 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 distinct invocations of the same pass ๐ - To turn on 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 too. If you don't specify one, GCC creates it as described below ๐ - Okay so step three is hunting down the pass dump ๐ It lives in a file whose name has three parts glued together with periods ๐ง: first the name of the source file you asked GCC to compile, then a numeric suffix for the pass number with a
tfor tree passes (or anrfor RTL passes ๐), and finally the pass code. For example, the Early VRP pass dump might be sitting inmyfile.c.038t.evrpin your current working directory ๐. Bestie, real talk: those numeric codes are NOT stable ๐ญ they can change from one version of GCC to another.
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ this is the optimization dump flag and it's giving main character energy ๐ It controls the optimization dumps coming from the various optimization passes. If you use the-optionsform, options is a list of--separated option keywords that pick the dump details and the optimizations you care about.
The keywords sort into three groups, and you can mix and match them ๐
- options describing what kinds of messages should be emitted,
- options describing the verbosity of the dump, and
- options describing which optimizations should be included.
Within each group you can freely mix keywords, since they don't overlap ๐ซถ Just know that if things conflict, the later option on the command line wins ๐
The following options control which kinds of messages get emitted:
optimizedโ prints info when an optimization is successfully applied ๐ฅ Each pass gets to decide what info is relevant. For example, the vectorizer passes print the source location of loops that got successfully vectorized.missedโ prints info about missed optimizations ๐ Individual passes control what goes into the output.noteโ prints verbose info about optimizations, like certain transformations and more detailed messages about decisions ๐งallโ prints detailed optimization info, which includesoptimized,missed, andnote๐
The following option controls the dump verbosity:
internalsโ by default only "high-level" messages get emitted ๐ This one unlocks the extra, more detailed messages, which are mostly of interest to GCC developers ๐ค
One or more of these keywords can be used to describe a group of optimizations:
ipaโ enables dumps from all interprocedural optimizations ๐ฆloopโ enables dumps from all loop optimizations ๐inlineโ enables dumps from all inlining optimizations โจompโ enables dumps from all OMP (Offloading and Multi Processing) optimizations ๐vecโ enables dumps from all vectorization optimizations ๐ธoptallโ enables dumps from all optimizations ๐ This is a superset of the optimization groups listed above.
If options is omitted, it defaults to optimized-optall, which means dumping messages about successful optimizations from all the passes, while skipping the messages treated as "internals" ๐ง
If you provide a filename, the dumps from all the applicable optimizations get concatenated into that file. Otherwise the dump goes to stderr. You can pass several -fopt-info options, but only one of them can include a filename. If other filenames are provided, all but the first such option get ignored ๐
Heads up! The output filename gets overwritten when there are multiple translation units ๐ญ If you want combined output from multiple translation units, use stderr instead.
Here's the example where the optimization info goes to stderr ๐
gcc -O3 -fopt-info
This one outputs the missed optimization report from all the passes into missed.all ๐
gcc -O3 -fopt-info-missed=missed.all
And this one prints info about missed optimization opportunities from the vectorization passes on stderr ๐
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 slay however you like ๐
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
As another example, this one outputs info about missed optimizations as well as optimized locations from all the inlining passes into inline.txt ๐ฆ
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
Finally, consider this one ๐
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Here the two output filenames vec.miss and loop.opt are in conflict, since only one output file is allowed ๐ฉ In this case only the first option takes effect and the subsequent options get ignored. So only vec.miss is produced, containing dumps from the vectorizer about missed opportunities.
-fsave-optimization-recordโ writes aSRCFILE.opt-record.json.gzfile detailing what optimizations were performed, for the optimizations that support-fopt-info๐
Experimental alert! โ ๏ธ This option is experimental, and the format of the data inside the compressed JSON file is subject to change ๐
It's roughly equivalent to a machine-readable version of -fopt-info-all, as a collection of messages with source file, line number, and column number. Each message also gets these extra goodies ๐
- the execution count of the code being optimized, plus metadata about whether that 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 gets inlined into several different places (which might themselves be inlined), you can tell the copies apart ๐ช
- objects identifying the parts of the message that refer to expressions, statements, or symbol-table nodes, which of these categories they are, and, when available, their source code location ๐
- the GCC pass that emitted the message, and
- the location in GCC's own code from which the message was emitted ๐คฏ
Some messages are logically nested within other messages too, reflecting implementation details of the optimization passes ๐ซถ
-fsched-verbose=nโ on targets that use instruction scheduling, this controls how much debugging output the scheduler prints to the dump files ๐- For
ngreater than zero, it outputs the same info as-fdump-rtl-sched1and-fdump-rtl-sched2๐ธ - For
ngreater than one, it also outputs basic block probabilities, detailed ready list info, and unit/insn info โจ - For
ngreater than two, it includes RTL at the abort point, plus control-flow and regions info ๐ - And for
nover four,-fsched-verbosealso includes dependence info ๐คฏ
- For
-fenable-kind-pass,-fdisable-kind-pass=range-listโ a set of options for explicitly disabling and enabling optimization passes ๐ง They're meant for debugging GCC itself.
Compiler users should stick to the regular options for enabling and disabling passes instead, bestie ๐
-fdisable-ipa-passโ disables the IPA pass called pass. If the same pass gets statically invoked in the compiler multiple times, append a sequential number starting from 1 to the pass name ๐ข-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ disables the RTL pass called pass. Same numbering rule as above. range-list is a comma-separated list of function ranges or assembler names ๐ Each range is a number pair separated by a colon, and it's inclusive at both ends. If the range is trivial, the number pair can be simplified to a single number. If a function's call graph node uid falls within one of the specified ranges, the pass is disabled for that function ๐ฆ The uid shows up in the function header of a dump file, and you can dump the pass names by using-fdump-passes๐-fdisable-tree-pass,-fdisable-tree-pass=range-listโ disables the tree pass called pass. Check-fdisable-rtl-passfor how the option arguments work ๐ณ-fenable-ipa-passโ enables the IPA pass called pass. Same numbering rule applies for repeated invocations ๐-fenable-rtl-pass,-fenable-rtl-pass=range-listโ enables the RTL pass called pass. See-fdisable-rtlfor the option argument description and examples ๐ซ-fenable-tree-pass,-fenable-tree-pass=range-listโ enables the tree pass called pass. See-fdisable-rtlfor the description of option arguments ๐ฒ
Here are some examples showing how to use these options ๐
# disable ccp1 for all functions
-fdisable-tree-ccp1
# disable complete unroll for function whose cgraph node uid is 1
-fenable-tree-cunroll=1
# disable gcse2 for functions at the following ranges [1,1],
# [300,400], and [400,1000]
# disable gcse2 for functions foo and foo2
-fdisable-rtl-gcse2=foo,foo2
# disable early inlining
-fdisable-tree-einline
# disable ipa inlining
-fdisable-ipa-inline
# enable tree full unroll
-fenable-tree-unroll
-fchecking,-fchecking=nโ enables internal consistency checking ๐ง The default depends on the compiler configuration.-fchecking=2enables further internal consistency checking that might affect code generation ๐-frandom-seed=stringโ this gives GCC a seed to use instead 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. Use-frandom-seedto produce reproducibly identical object files ๐ซถ The string can be a number (decimal, octal, or hex) or an arbitrary string, which gets converted to a number by computing CRC32 โจ
Make sure the string is different for every file you compile, bestie ๐โจ
-save-tempsโ okay so this one is keep-the-receipts energy ๐งพ๐ It stores the usual "temporary" intermediate files permanently instead of tossing them, and names them as auxiliary output files, as described under-dumpbaseand-dumpdir๐ฆ When you combine it with the-xoption,-save-tempsis sensible enough to avoid overwriting an input source file that has the same extension as an intermediate file ๐ If you need that intermediate file, rename the source file before using-save-temps๐ซถ-save-temps=cwdโ literally just-save-tempswith a twist, it's equivalent to:
-save-temps -dumpdir ./.
-save-temps=objโ this one is equivalent to-save-temps -dumpdir outdir/๐ Here,outdir/is the directory of the output file you named after-o, including any directory separators. If you don't use-o, then-save-temps=objacts exactly like-save-temps=cwd๐-time[=file]โ main character energy โฑ๏ธ This reports the CPU time taken by each subprocess in the compilation sequence. For C source files, that's the compiler proper and the assembler (plus the linker, if linking is happening) ๐ธ
Without an output file, the output looks like this:
# cc1 0.12 0.01
# as 0.00 0.01
The first number on each line is the "user time," which is the time spent running the program itself. The second number is the "system time," which is the time spent in operating system routines on the program's behalf. Both numbers are in seconds โญ
With an output file, the output gets 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 "system time" get moved before the program name, and the options passed to the program are shown too, so you can later tell which file was being compiled and with which options ๐ง
-fdump-final-insns[=file]โ dumps the final internal representation (RTL) to file ๐ฅ If you leave out the optional argument (or file is.), the dump file gets named by appending.gkdto the dump base name, see-dumpbase๐ฆ-fcompare-debug[=opts]โ bestie, this one is a whole vibe ๐ If no error happens during compilation, the compiler runs a second time with opts and-fcompare-debug-secondadded to the arguments for that second compilation. It dumps the final internal representation in both compilations and prints an error if they differ ๐ If you omit the equal sign, the default-gtogglegets used โจ
The environment variable GCC_COMPARE_DEBUG, if it's defined, non-empty, and nonzero, implicitly enables -fcompare-debug ๐ If GCC_COMPARE_DEBUG is set to a string starting with a dash, that string is used for opts. Otherwise, the default -gtoggle is used ๐
-fcompare-debug=, with the equal sign but without opts, is equivalent to -fno-compare-debug. That one disables the dumping of the final representation and the second compilation, and it even stops GCC_COMPARE_DEBUG from taking effect ๐
โโ๏ธ
To verify full coverage during -fcompare-debug testing, set GCC_COMPARE_DEBUG to something like -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any real compilation (rather than preprocessing, assembly, or linking) ๐งช If you just want a warning, setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do the trick ๐
-fcompare-debug-secondโ this one gets passed to the compiler implicitly for the second compilation requested by-fcompare-debug๐ซง It comes along with options that silence warnings, and it leaves out other options that would make the compiler produce output to files or to standard output as a side effect. Dump files and preserved temporary files get renamed to include the extra.gkextension during the second compilation, so they don't overwrite the ones from the first run ๐ฆ
When this option is passed to the compiler driver, the first compilation gets skipped. That makes it useful for pretty much nothing except debugging the compiler proper ๐
-gtoggleโ this flips debug info like a light switch ๐ก It turns generation of debug info off if leaving out this option would generate it, or turns it on at level 2 otherwise. Where you put it on the command line doesn't matter. It takes effect after all the other options are processed, and it only does so once, no matter how many times you give it ๐ซถ It's mainly meant to be used with-fcompare-debug๐-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-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 consumed by each pass when it finishes โณ-ftime-report-detailsโ records the time consumed by infrastructure parts separately for each pass ๐-fira-verbose=nโ controls how verbose the dump file for the integrated register allocator is ๐๏ธ The default value is5. If the value n is greater or equal to10, the dump output gets sent to stderr, using the same format as n minus10๐ธ-flto-reportโ prints a report with internal details on how the link-time optimizer is working ๐ง The contents of this report vary 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โ like-flto-report, but only prints for the WPA phase of link-time optimization ๐ฏ-fmem-reportโ makes the compiler print some statistics about permanent memory allocation when it finishes ๐ง-fmem-report-wpaโ makes the compiler print statistics about permanent memory allocation for the WPA phase only ๐ง โจ-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ makes the compiler print some statistics about permanent memory allocation, either before or after interprocedural optimization ๐ช-fprofile-reportโ makes the compiler print some statistics about the consistency of the (estimated) profile and the effect of individual passes ๐-fstack-usageโ okay this is so useful ๐ฅน It makes the compiler output stack usage information for the program, on a per-function basis. The filename for the dump is made by appending.suto the auxname. The auxname is generated from the name of the output file, if it's explicitly specified 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 qualifier static 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 are made in the function. The second field is this fixed number of bytes.
The qualifier dynamic means the function manipulates the stack dynamically ๐ On top of the static allocation described above, stack adjustments get made in the body of the function, for example to push and pop arguments around function calls. If the qualifier bounded is also present, the amount of these adjustments is bounded at compile time, and the second field is an upper bound on the total amount of stack the function uses. If bounded isn't present, the amount of these 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-list is a comma-separated list of tuples in the formname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]. These set the name of the counter and a list of closed intervals. Thelower_boundis optional and is zero-initialized if it isn't set. For example, with-fdbg-cnt=dce:2-4:10-11,tail_call:10,dbg_cnt(dce)returns true only for the second, third, fourth, tenth, and eleventh invocation. Fordbg_cnt(tail_call), true is returned for the first 10 invocations ๐ชฉ-print-file-name=libraryโ prints the full absolute name of the library file library that would be used when linking, and then stops ๐บ๏ธ With this option, GCC doesn't compile or link anything. It just prints the file name ๐-print-multi-directoryโ prints the directory name that matches 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@instead of-, with no spaces between multiple switches. This is supposed to make shell processing easier ๐-print-multi-os-directoryโ prints the path to the OS libraries for the selected multilib, relative to somelibsubdirectory ๐ช If the OS libraries are in thelibsubdirectory and no multilibs are used, this is usually just.. If the OS libraries are inlibsuffixsibling directories, it prints something like../lib64,../lib, or../lib32. If the OS libraries are inlib/subdirsubdirectories, it prints something likeamd64,sparcv9, orev6๐-print-multiarchโ prints the path to the 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 this:
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirsโ prints the name of the configured installation directory and a list of the program and library directories gcc searches, and then stops ๐๏ธ Nothing else happens after that โจ
okay so this bit is lowkey the most important part bestie ๐
if gcc yells installation problem, cannot exec cpp0: No such file or directory at you, it means the compiler pieces (like cpp0) aren't where gcc is looking for them ๐ญ you can either move cpp0 and friends to the spot gcc expects, OR set the GCC_EXEC_PREFIX environment variable to the folder where you installed everything. and periodt, don't forget the trailing / ๐ซถ
-print-sysrootโ okay this one prints the target sysroot directory that gets used during compilation โจ it's the one you set at configure time or with the--sysrootoption, and it might come with an extra suffix that depends on your compilation options. if there's no target sysroot at all? it just prints nothing ๐-print-sysroot-headers-suffixโ prints the suffix that gets tacked onto the target sysroot when gcc goes hunting for headers ๐ and if your compiler wasn't configured with one, it throws an error instead. either way it doesn't do anything else, no cap ๐-dumpmachineโ prints the compiler's target machine (likei686-pc-linux-gnu) and then stops right there ๐ฆ-dumpversionโ prints the compiler version (think3.0,6.3.0or7) and then bounces, nothing else โจ this is the version that shows up in filesystem paths and specs, and depending on how the compiler was configured, it can be:- just one number (the major version) ๐ธ
- two numbers separated by a dot (major and minor) ๐
- three numbers separated by dots (major, minor and patchlevel) ๐
-dumpfullversionโ prints the full compiler version and then stops ๐ the output is always three numbers separated by dots: major, minor and patchlevel. no exceptions, it's giving consistency ๐-dumpspecsโ prints the compiler's built-in specs and that's it ๐ง this one is used when GCC itself is being built, so it's kinda behind-the-scenes energy ๐
๐ธ Machine-Dependent Options ๐ธ
okay so every target machine that GCC supports can have its very own options ๐ these let you do stuff like compile for a specific processor variant or ABI, or control optimizations that only make sense for that machine โจ by convention, the names of machine-specific options start with -m, so look out for those ๐
some configurations also support extra target-specific options too, usually so the compiler can play nice with other compilers on the same platform ๐ซถ
๐ฆ AArch64 Options ๐ฆ
these options are defined for AArch64 implementations, so if you're working on that architecture, this is your moment ๐ฅ
-mabi=nameโ generates code for the specified data model ๐ the valid values are:ilp32for the SysV-like data model whereint,long intand pointers are all 32 bits ๐ธlp64for the SysV-like data model whereintis 32 bits, butlong intand pointers are 64 bits ๐
the default depends on your specific target configuration ๐ and be careful, the LP64 and ILP32 ABIs are not link-compatible! you have to compile your entire program with the same ABI and link it with a compatible set of libraries, or it's gonna be a whole mess ๐
-mbig-endianโ generates big-endian code ๐ this is the default when GCC is configured for anaarch64_be-*-*target-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers โจ this stops the compiler from touching floating-point and Advanced SIMD registers, but it doesn't put any restrictions on the assembler-mlittle-endianโ generates little-endian code ๐ this is the default when GCC is configured for anaarch64-*-*target but not anaarch64_be-*-*one-mcmodel=tinyโ generates code for the tiny code model ๐ฆ the program and its statically defined symbols have to be within 1MB of each other. programs can be statically or dynamically linked-mcmodel=smallโ generates code for the small code model ๐ the program and its statically defined symbols have to be within 4GB of each other. programs can be statically or dynamically linked, and this is the default code model โจ-mcmodel=largeโ generates code for the large code model ๐ it makes no assumptions about addresses and sizes of sections, but programs can only be statically linked. also,-mcmodel=largeis incompatible with-mabi=ilp32,-fpicand-fPIC, so don't mix them ๐ซ-mstrict-align,-mno-strict-alignโ these let you avoid (or allow) generating memory accesses that might not be aligned on a natural object boundary, as the architecture specification describes ๐ง-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ omit or keep the frame pointer in leaf functions ๐ธ the first one (omitting it) is the default behaviour-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ these generate stack protection code using a canary atguard๐ฅ the supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register- with the
sysregchoice,-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsetspecify which system register to use as the base register for reading the canary, plus the offset from that base register ๐ - there is no default register or offset here, because this is entirely for use within the Linux kernel ๐ง
- with the
-mtls-dialect=descโ uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables ๐ this is the default-mtls-dialect=traditionalโ uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐-mtls-size=sizeโ specifies the bit size of immediate TLS offsets ๐ the valid values are12,24,32and48. this option requires binutils 2.26 or newer โจ-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ enables or disables the workaround for ARM Cortex-A53 erratum number 835769 ๐ฆ this involves inserting a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419โ enables or disables the workaround for ARM Cortex-A53 erratum number 843419 ๐ this erratum workaround is made at link time, so this option only passes the corresponding flag to the linker-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ enables or disables the reciprocal square root approximation ๐ง this only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. when enabled, it reduces the precision of reciprocal square root results to about 16 bits for single precision and to 32 bits for double precision โก-mlow-precision-sqrt,-mno-low-precision-sqrtโ enables or disables the square root approximation ๐ธ this only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. when enabled, it reduces the precision of square root results to about 16 bits for single precision and to 32 bits for double precision. and if it's enabled, it implies-mlow-precision-recip-sqrt๐ฅ-mlow-precision-div,-mno-low-precision-divโ enables or disables the division approximation ๐ this only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. when enabled, it reduces the precision of division results to about 16 bits for single precision and to 32 bits for double precision ๐-mtrack-speculation,-mno-track-speculationโ enables or disables generation of extra code that tracks speculative execution through conditional branches ๐ฆ the tracking state can then be used by the compiler when expanding calls to"__builtin_speculation_safe_copy", so it can generate a more efficient code sequence ๐ง-moutline-atomics,-mno-outline-atomicsโ enables or disables calls to out-of-line helpers that implement atomic operations ๐ these helpers figure out at runtime whether the LSE instructions from ARMv8.1-A can be used. if they can't, they fall back to the load/store-exclusive instructions that are present in the base ARMv8.0 ISA ๐- this option only applies when you're compiling for the base ARMv8.0 instruction set ๐ if you're using a later revision, like
-march=armv8.1-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 โจ
- this option only applies when you're compiling for the base ARMv8.0 instruction set ๐ if you're using a later revision, like
-march=nameโ specifies the name of the target architecture and, optionally, one or more feature modifiers ๐ this option has the form-march=arch{+[no]feature}*
the table below (well, a list now, lol) summarizes the permissible values for arch and the features they enable by default ๐
armv8-a(Armv8-A) โ includes by default+fp,+simd๐ธarmv8.1-a(Armv8.1-A) โ includes by defaultarmv8-a,+crc,+lse,+rdma๐armv8.2-a(Armv8.2-A) โ includes by defaultarmv8.1-a๐ฆarmv8.3-a(Armv8.3-A) โ includes by defaultarmv8.2-a,+pauthโจarmv8.4-a(Armv8.4-A) โ includes by defaultarmv8.3-a,+flagm,+fp16fml,+dotprod๐ฅarmv8.5-a(Armv8.5-A) โ includes by defaultarmv8.4-a,+sb,+ssbs,+predres๐armv8.6-a(Armv8.6-A) โ includes by defaultarmv8.5-a,+bf16,+i8mm๐armv8-r(Armv8-R) โ includes by defaultarmv8-r๐ง
the value native is available on native AArch64 GNU/Linux and makes the compiler pick the architecture of the host system ๐ซถ this option has no effect if the compiler is unable to recognize the architecture of the host system.
the permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. if you specify conflicting feature modifiers, the right-most feature is used, so the last one wins ๐
GCC uses name to figure out what kind of instructions it can emit when generating assembly code ๐ if -march is specified without -mtune or -mcpu also being specified, the code gets tuned to perform well across a range of target processors that implement the target architecture ๐ธ
-mtune=nameโ specifies the name of the target processor that GCC should tune the performance of the code for โจ the permissible values for this option are:
generic, cortex-a35, cortex-a53, cortex-a55, cortex-a57,
cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae,
cortex-a77, cortex-a65, cortex-a65ae, cortex-a34, cortex-a78,
cortex-a78ae, cortex-a78c, ares, exynos-m1, emag, falkor,
neoverse-512tvb, neoverse-e1, neoverse-n1, neoverse-n2,
neoverse-v1,neoverse-v2, grace, qdf24xx, saphira, phecda, xgene1,
vulcan, octeontx, octeontx81, octeontx83, octeontx2, octeontx2t98,
octeontx2t96 octeontx2t93, octeontx2f95, octeontx2f95n,
octeontx2f95mm, a64fx, thunderx, thunderxt88, thunderxt88p1,
thunderxt81, tsv110, thunderxt83, thunderx2t99, thunderx3t110, zeus,
cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35,
cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55,
cortex-r82, cortex-x1, ampere1, ampere1a, cobalt-100 and native.
the values cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55 and cortex-a76.cortex-a55 are giving big.LITTLE realness ๐. They tell GCC to tune for a big.LITTLE system ๐.
the value neoverse-512tvb is the main character here ๐. It tells GCC to tune for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle. ngl that's a lot of words, so here's the vibe: GCC is tuning for Neoverse cores that can run 4 128-bit Advanced SIMD arithmetic instructions a cycle, plus an equivalent number of SVE arithmetic instructions per cycle (2 for 256-bit SVE, 4 for 128-bit SVE) ๐
. It's more general than tuning for one specific core like Neoverse V1, but more specific than the default tuning described below โจ.
additionally, on native AArch64 GNU/Linux systems, the value native tunes performance to the host system ๐ซถ. This option has no effect if the compiler can't recognise the processor of the host system ๐.
where none of -mtune=, -mcpu= or -march= are specified, the code is tuned to perform well across a range of target processors ๐.
this option cannot be suffixed by feature modifiers ๐
-mcpu=nameโ Pick the target processor, optionally with one or more feature modifiers tacked on ๐. The form is-mcpu=cpu{+[no]feature}*, where the values forcpuare the same ones you'd get with-mtune. The values forfeatureare documented in the sub-section onaarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you give conflicting feature modifiers, the right-most one wins ๐.- GCC uses
nameto figure out what kind of instructions it can emit when generating assembly (as if by-march), and which processor to tune performance for (as if by-mtune). If you use this with-marchor-mtune, those take precedence over the matching part of this option ๐. -mcpu=neoverse-512tvbis special ๐ฆ. It doesn't refer to one specific core. Instead it refers to all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle. Unless you override it with-march,-mcpu=neoverse-512tvbgenerates code that can run on a Neoverse V1 core, since Neoverse V1 is the first Neoverse core with these properties. Unless you override it with-mtune,-mcpu=neoverse-512tvbtunes code the same way as-mtune=neoverse-512tvb๐ธ.
- GCC uses
-moverride=stringโ Overrides the tuning decisions the back-end makes in response to a-mtune=switch ๐. The syntax, semantics and accepted values forstringaren't guaranteed to stay consistent across releases.
โ ๏ธ This option is only intended to be useful when developing GCC. Don't go poking at it in your everyday builds, bestie.
-mverbose-cost-dumpโ Turns on verbose cost model dumping in the debug dump files ๐. This one's only here for debugging the compiler itself ๐ง.-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ Enables or disables PC-relative literal loads ๐. With this option, literal pools are accessed using a single instruction and emitted after each function. That limits the maximum size of functions to 1MB ๐ซ . It's enabled by default for-mcmodel=tiny.-msign-return-address=scopeโ Picks the function scope that return address signing gets applied to ๐. The permissible values are:noneโ disables return address signing.non-leafโ enables pointer signing for functions which are not leaf functions.allโ enables pointer signing for all functions.
The default value is none. 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 types of branch protection features. If a feature has additional tuning options,standardsets it to its standard level.pac-ret[+leaf]turns on return address signing to its standard level. That means signing functions that save the return address to memory (non-leaf functions will practically always do this) using the a-key. The optional argumentleafcan be used to extend the signing to include leaf functions. The optional argumentb-keycan be used to sign the functions with the B-key instead of the A-key.btiturns on the branch target identification mechanism โจ.
-mharden-sls=optsโ Enables compiler hardening against straight line speculation (SLS) ๐.optsis a comma-separated list of the following options:retbrblr
In addition, -mharden-sls=all enables all SLS hardening, while -mharden-sls=none disables all SLS hardening ๐
.
-msve-vector-bits=bitsโ Sets how many bits live in an SVE vector register ๐ฆ. It only has an effect when SVE is enabled.- GCC supports two forms of SVE code generation. "Vector-length agnostic" output works with any size of vector register. "Vector-length specific" output lets GCC make assumptions about the vector length when that's useful for optimisation reasons ๐ง .
- The possible values of
bitsarescalable,128,256,512,1024and2048. Specifyingscalableselects vector-length agnostic output. At present,-msve-vector-bits=128also generates vector-length agnostic output for big-endian targets. All other values generate vector-length specific code ๐. - The behaviour of these values may change in future releases, and no value except
scalableshould be relied on for producing code that's portable across different hardware SVE vector lengths. ๐จ - The default is
-msve-vector-bits=scalable, which produces vector-length agnostic code ๐ซถ.
๐ฆ -march and -mcpu Feature Modifiers ๐ฆ
feature modifiers used with -march and -mcpu can be any of the following, and each one also has an inverse, nofeature โจ.
crcโ Enables the CRC extension. This is on by default for-march=armv8.1-a๐.cryptoโ Enables the Crypto extension. This also turns on Advanced SIMD and floating-point instructions ๐.fpโ Enables floating-point instructions. This is on by default for all possible values for options-marchand-mcpu๐ธ.simdโ Enables Advanced SIMD instructions. This also turns on floating-point instructions. It's on by default for all possible values for options-marchand-mcpu๐ฅ.sveโ Enables Scalable Vector Extension instructions. This also turns on 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 turns on floating-point instructions ๐.fp16fmlโ Enables the FP16 fmla extension. This also turns on FP16 extensions and floating-point instructions. It's enabled by default for-march=armv8.4-a. Using this option 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's passed on to the assembler, so inline asm statements can use instructions from the RcPc extension ๐ง.dotprodโ Enables the Dot Product extension. This also turns on Advanced SIMD instructions ๐.aesโ Enables the Armv8-aaesandpmullcrypto extension. This also turns on Advanced SIMD instructions ๐.sha2โ Enables the Armv8-asha2crypto extension. This also turns on Advanced SIMD instructions ๐.sha3โ Enables thesha512andsha3crypto extension. This also turns on Advanced SIMD instructions. Using this option with architectures prior to Armv8.2-A is not supported ๐.sm4โ Enables thesm3andsm4crypto extension. This also turns on Advanced SIMD instructions. Using this option with architectures prior to Armv8.2-A is not supported ๐ซ .profileโ Enables the Statistical Profiling extension. This option only enables the extension at the assembler level and does not affect code generation ๐.rngโ Enables the Armv8.5-a Random Number instructions. This option only enables the extension at the assembler level and does not affect code generation ๐ฒ.memtagโ Enables the Armv8.5-a Memory Tagging Extensions. Using this option with architectures prior to Armv8.5-A is not supported ๐ท๏ธ.sbโ Enables the Armv8-a Speculation Barrier instruction. This option only enables the extension at the assembler level and does not affect code generation. It's enabled by default for-march=armv8.5-a๐ก๏ธ.ssbsโ Enables the Armv8-a Speculative Store Bypass Safe instruction. This option only enables the extension at the assembler level and does not affect code generation. It's enabled by default for-march=armv8.5-aโจ.predresโ Enables the Armv8-a Execution and Data Prediction Restriction instructions. This option only enables the extension at the assembler level and does not affect code generation. It's enabled by default for-march=armv8.5-a๐ .sve2โ Enables the Armv8-a Scalable Vector Extension 2. 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 turns on Advanced SIMD and floating-point instructions. It's enabled by default for-march=armv8.6-a. Using this option 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 option 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 option with architectures prior to Armv8.2-A is not supported ๐.bf16โ ๐ okay so this one turns on brain half-precision floating-point instructions! โจ It also switches on Advanced SIMD and floating-point instructions too. It's on by default for-march=armv8.6-a, so you're already set if you're using that. ๐ซถ
๐จ Using this with architectures older than Armv8.2-A is not supported, so please don't do that bestie ๐
flagmโ ๐ฆ Enables the Flag Manipulation instructions Extension.pauthโ ๐ Enables the Pointer Authentication Extension.
Okay so crypto implies aes, sha2, and simd, and simd implies fp. ๐ฅ The other way around, nofp implies nosimd, which implies nocrypto, noaes and nosha2. It's giving chain reaction ๐
โจ Adapteva Epiphany Options โจ
These -m options are defined for Adapteva Epiphany ๐ธ
-mhalf-reg-fileโ ๐ธ Don't allocate any register in the range"r32"..."r63". That way your code can run on hardware variants that don't have these registers at all.-mprefer-short-insn-regsโ ๐ง Prefers registers that let the compiler generate short instructions. Heads up though, this can bump up the instruction count, so overall code size might go down or up. ๐คทโโ๏ธ-mbranch-cost=numโ ๐ Sets the cost of branches to roughlynum"simple" instructions. This is only a heuristic, so it's not guaranteed to give consistent results across releases. Not a promise, just a vibe ๐-mcmoveโ โญ Turns on the generation of conditional moves.-mnops=numโ ๐ EmitsnumNOPs before every other generated instruction. Very spacious ๐-mno-soft-cmpsfโ ๐ For single-precision floating-point comparisons, this emits an"fsub"instruction and tests the flags. It's faster than a software comparison, BUT it can give incorrect results when NaNs are involved, or when two different small numbers are compared and their difference works out to zero. The default is-msoft-cmpsf, which uses slower software comparisons that are IEEE-compliant. Slower but correct is the move โจ
โ ๏ธ Be careful with -mno-soft-cmpsf if you're dealing with NaNs or tiny numbers. Your results could be wrong, bestie.
-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 range"sp+0...sp+7"can be used by leaf functions without stack allocation. Values other than8or16are untested and unlikely to work. Also, this option changes the ABI, so compiling a program with a different stack offset than the libraries were built with generally does not work.
๐จ This changes the ABI! Mixing stack offsets with your libraries usually breaks things, so be very careful here.
This option is handy if you want to test whether a different stack offset gives you better code. But if you want to actually build working programs with a different stack offset, the recommended move is to configure the toolchain with the appropriate --with-stack-offset=num option ๐ ๏ธ
-mno-round-nearestโ ๐ฆ Makes the scheduler assume the rounding mode has been set to truncating. The default is-mround-nearest.-mlong-callsโ ๐ข If not otherwise specified by an attribute, this assumes all calls might be beyond the offset range of the"b"/"bl"instructions. So it loads the function address into a register before doing a call that would otherwise be direct. This is the default.-mshort-callsโ โก If not otherwise specified by an attribute, this assumes all direct calls are in range of the"b"/"bl"instructions, so those instructions get used for direct calls. The default is-mlong-calls.-msmall16โ ๐ท Assumes addresses can be loaded as 16-bit unsigned values. This doesn't apply to function addresses where-mlong-callssemantics are in effect.-mfp-mode=modeโ ๐ Sets the prevailing mode of the floating-point unit. This decides the floating-point mode that's provided and expected at function call and return time. Matching this to the mode you mostly need at function start can make your programs smaller and faster by avoiding unnecessary mode switches. ๐๏ธ
mode can be set to one of these values:
callerโ Any mode at function entry is valid, and it gets retained or restored when the function returns, and when it calls other functions. This is the move for libraries or other compilation units you want to drop into different programs with different prevailing FPU modes. A single object file is super convenient, even though you pay a bit in size and speed for the extra mode switching you might need compared to a more specific choice.truncateโ The mode used for floating-point calculations with truncating (round towards zero) rounding mode. That includes conversion from floating point to integer.round-nearestโ The mode used for floating-point calculations with round-to-nearest-or-even rounding mode.intโ The mode used to 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โ ๐งฉ Code generation tweaks that turn off, respectively, splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses. The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify.-mnovect-doubleโ ๐ญ Changes the preferred SIMD mode toSImode. The default is-mvect-double, which usesDImodeas the preferred SIMD mode.-max-vect-align=numโ ๐ The maximum alignment for SIMD vector mode types.numcan be4or8, and the default is8. This is an ABI change, even though lots of library function interfaces are unaffected if they don't use SIMD vector modes in places that affect the size and/or alignment of relevant types.
๐จ Yep, this is an ABI change, so handle it with care ๐
-msplit-vecmove-earlyโ ๐ Splits vector moves into single word moves before reload. In theory this can give better register allocation, but so far the reverse seems to be generally the case. Theory vs. reality, bestie ๐ญ-m1reg-regโ ๐ฏ Specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster. Allowable values forregarer43andr63, which fix that register for this purpose, andnone, which means no register is used for this. The default is-m1reg-none.
โจ AMD GCN Options โจ
These options are defined specifically for the AMD GCN port ๐
-march=gpu,-mtune=gpuโ ๐ฅ Sets the architecture type or tuning forgpu. Supported values forgpuare:fijiโ 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 suited to devices with the SRAM-ECC feature enabled, disabled, or either mode. Some devices let you enable this per-process. 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). Beware, there may be lots of threads and limited memory available ๐ The size of the stack allocation may also affect run-time performance. The default is32KBwhen using OpenACC or OpenMP, and1MBotherwise.-mxnackโ ๐ฆ Compiles binaries suited to devices with the XNACK feature enabled. Some devices always require XNACK, and some let the user configure it. The compiled code must match the device mode. The default is-mno-xnack. Right now this option is a placeholder for support that isn't implemented yet, so it's a bit of a promise for later ๐
โจ ARC Options โจ
The following options control the architecture variant that code is 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 to use 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. 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 with"norm"instructions enabled.arc600_mul32x16โ Compiles for ARC 600 CPU with"norm"and 32x16-bit multiply instructions enabled.arc600_mul64โ Compiles for ARC 600 CPU with"norm"and"mul64"-family instructions enabled.arc601_normโ Compiles for ARC 601 CPU with"norm"instructions enabled.arc601_mul32x16โ Compiles for ARC 601 CPU with"norm"and 32x16-bit multiply instructions enabled.arc601_mul64โ Compiles for ARC 601 CPU with"norm"and"mul64"-family instructions enabled.nps400โ Compiles for ARC 700 on 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โ ๐ โโ๏ธ Disables"lr"and"sr"instructions from using FPX extension aux registers.-meaโ ๐งฎ Generates extended arithmetic instructions. Currently only"divaw","adds","subs", and"sat16"are supported. This is only valid for-mcpu=ARC700.-mno-mpyโ ๐ โโ๏ธ Do NOT generate thempy-family instructions for ARC700. ngl this one is deprecated, so it's basically retired ๐-mmul32x16โ โจ Generates 32x16-bit multiply and multiply-accumulate instructions. Main character multiply energy ๐-mmul64โ ๐ฅ Generatesmul64andmulu64instructions. Only valid for-mcpu=ARC600, so don't try it anywhere else ๐-mnormโ ๐ง Generatesnorminstructions. It's already on by default if-mcpu=ARC700is in effect, so you're set ๐-mspfp,-mspfp-compactโ ๐ธ Generates single-precision FPX instructions, tuned for the compact implementation.-mspfp-fastโ โก Generates single-precision FPX instructions, tuned for the fast implementation.-msimdโ ๐ Turns on ARC SIMD instructions through target-specific builtins. Only valid for-mcpu=ARC700.-msoft-floatโ ๐ซถ This one gets ignored. It's only here for compatibility, bestie. Software floating-point code is emitted by default, and that default can be overridden by FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision.-mswapโ ๐ Generatesswapinstructions.-matomicโ โ๏ธ Unlocks the locked load/store conditional extension, which the compiler uses to build the atomic memory built-in functions. Not available for ARC 6xx or ARC EM cores ๐-mdiv-remโ โ Enablesdivandreminstructions for ARCv2 cores.-mcode-densityโ ๐ Enables code density instructions for ARC EM. It's on by default for ARC HS, so ARC HS users are already winning.-mll64โ ๐พ Enables double load/store operations for ARC HS cores.-mtp-regno=regnoโ ๐งต Sets the thread pointer register number.-mmpy-option=multoโ ๐งฎ Compiles ARCv2 code with a multiplier design option. You can passmultoas either a string or a number.wlh1is the default. The recognized values are:0ornoneโ No multiplier at all. Rough, but valid ๐1orwโ 16x16 multiplier, fully pipelined. Enablesmpywandmpyuw.2orwlh1โ 32x32 multiplier, fully pipelined (1 stage). On top of that, it enablesmpy,mpyu,mpym,mpymu, andmpy_s. This is the default ๐3orwlh2โ 32x32 multiplier, fully pipelined (2 stages). Also enablesmpy,mpyu,mpym,mpymu, andmpy_s.4orwlh3โ Two 16x16 multipliers, blocking, sequential. Also enablesmpy,mpyu,mpym,mpymu, andmpy_s.5orwlh4โ One 16x16 multiplier, blocking, sequential. Also enablesmpy,mpyu,mpym,mpymu, andmpy_s.6orwlh5โ One 32x4 multiplier, blocking, sequential. Also enablesmpy,mpyu,mpym,mpymu, andmpy_s.7orplus_dmpyโ ARC HS SIMD support ๐8orplus_macdโ ARC HS SIMD support ๐9orplus_qmacwโ ARC HS SIMD support ๐
โ ๏ธ This option is only available for ARCv2 cores.
-mfpu=fpuโ ๐ฆ Turns on specific floating-point hardware extensions for ARCv2 cores. The supported values forfpuare:fpusโ Enables single-precision floating-point hardware extensions.fpudโ Enables double-precision floating-point hardware extensions. The single-precision extension comes along for the ride too. Not available for ARC EM.fpudaโ Enables double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision extension is enabled as well. Only available for ARC EM.fpuda_divโ Enables double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point, square-root, and divide extensions are enabled too. Only available for ARC EM.fpuda_fmaโ Enables double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point and fused multiply and add extensions are enabled too. Only available for ARC EM.fpuda_allโ Enables double-precision floating-point hardware extensions using double-precision assist instructions. Every single-precision floating-point hardware extension is enabled too. Only available for ARC EM.fpus_divโ Enables single-precision floating-point, square-root, and divide hardware extensions.fpud_divโ Enables double-precision floating-point, square-root, and divide hardware extensions. This includesfpus_div. Not available for ARC EM.fpus_fmaโ Enables single-precision floating-point and fused multiply and add hardware extensions.fpud_fmaโ Enables double-precision floating-point and fused multiply and add hardware extensions. This includesfpus_fma. Not available for ARC EM.fpus_allโ Enables all single-precision floating-point hardware extensions.fpud_allโ Enables all single- and double-precision floating-point hardware extensions. Not available for ARC EM.
-mirq-ctrl-saved=register-range, blink, lp_countโ ๐ก๏ธ Picks the general-purpose registers that the processor automatically saves and restores on interrupt entry and exit. The register-range is written as two registers separated by a dash. The range always starts atr0, and the upper limit is thefpregister.blinkandlp_countare optional. This option is only valid for ARC EM and ARC HS cores.-mrgf-banked-regs=numberโ ๐ฆ Sets how many registers get replicated into the second register bank when entering a fast interrupt. Fast interrupts are the ones at 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 permitted values are4,8,16, and32.-mlpc-width=widthโ ๐ข Sets the width of thelp_countregister. Valid values for width are8,16,20,24,28, and32bits, and the default is a fixed 32 bits. If the width is less than 32, the compiler won't try to turn loops in your program into the zero-delay loop mechanism unless it knows thatlp_countcan actually hold the loop counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for various needs. This option defines the macro__ARC_LPC_WIDTH__with the value of width.-mrf16โ ๐ Tells the compiler to generate code for a 16-entry register file. This option defines the__ARC_RF16__preprocessor macro.-mbranch-indexโ ๐ช Enables use ofbiorbihinstructions to implement jump tables.
The following options are passed through to the assembler, and also define preprocessor macro symbols.
-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 thearclinuxemulation. This is enabled by default in tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets when profiling is not requested.-marclinux_profโ ๐ Passed through to the linker to specify use of thearclinux_profemulation. This is enabled by default in tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets 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, which is the offset available for an unconditional branch-and-link instruction. 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 forarc-linux-uclibcandarceb-linux-uclibctargets ๐
โจ OPTIONS โจ
-G num๐ง โ Okay, bestie, this one tells GCC to tuck externally-visible data into a small data section, but only if that data is no bigger thannumbytes. The defaultnumis 4 for any ARC config, or 8 when you've got double load/store operations ๐-mno-sdata๐ธ โ Nosdatareferences for you! This is the default for toolchains built forarc-linux-uclibcandarceb-linux-uclibctargets ๐ซถ-mvolatile-cache๐ โ Volatile references get ordinary cached memory accesses. This is the default, so you're already slaying โจ-mno-volatile-cache๐ฆ โ Turns on cache bypass for volatile references instead ๐
The following options fine tune code generation ๐
-malign-callโญ โ Does alignment optimizations forcallinstructions ๐-mauto-modify-reg๐ โ Lets you use pre/post modify with register displacement ๐ฅ-mbbit-peepholeโจ โ Enables bbit peephole2 ๐-mno-brcc๐ โ Disables a target-specific pass inarc_reorgthat would generate compare-and-branch (brcc) instructions. It doesn't touch the ones the combiner pass makes, though, so those are still on the table ๐-mcase-vector-pcrel๐ฆ โ Uses PC-relative switch case tables so case table shortening can happen. This is the default for-Os๐-mcompact-casesi๐ธ โ Enables the compactcasesipattern. It's the default for-Os, only works on ARCv1 cores, and is deprecated, so, not gonna lie, it's on its way out ๐-mno-cond-exec๐ โ Disables the ARCompact-specific pass that generates conditional execution instructions
Okay, the tea on -mno-cond-exec ๐ซ: the target-independent conditional execution pass is kinda lacking because of delay slot scheduling and the way operand numbers, literal sizes, instruction lengths, and conditional execution all interact. So the ARC port keeps a special pass around that digs for more conditional execution opportunities after register allocation, branch shortening, and delay slot scheduling are done. It usually (not always!) improves performance and code size, but it costs extra compilation time, which is exactly why there's an option to switch it off ๐ญ If call instructions are blowing past their allowable offset range because they got conditionalized, try -mmedium-calls instead ๐ง
-mearly-cbranchsi๐ โ Enables pre-reload use of thecbranchsipattern โจ-mexpand-adddi๐ฅ โ Expandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. Deprecated, so use it at your own risk ๐-mindexed-loadsโ ๏ธ โ Enables indexed loads. Be careful, because some optimizers then assume indexed stores exist, and they don't, so this can get messy ๐-mlra๐งช โ Enables Local Register Allocation. It's still experimental for ARC, so by default the compiler uses standard reload (that's-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 often get shortened by calling a special function in libgcc. That's called a millicode call. These calls can cause performance issues, 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 only work on CPUs with the code-density feature ๐-mmixed-code๐ โ Tweaks register allocation to help with 16-bit instruction generation. The upside is a smaller average instruction size, the downside is more instructions overall โญ-mq-class๐ฅฑ โ Deprecated. Enables q instruction alternatives, and it's 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 too ๐ฅ-msize-level=level๐ โ Fine-tunes size optimization around instruction lengths and alignment. Here are the recognized values forlevel:0โ No size optimization. This level is deprecated and treated like1๐1โ Short instructions get used opportunistically โจ2โ On top of level 1, alignment of loops and of code after barriers gets dropped ๐ซถ3โ On top of level 2, optional data alignment gets dropped, and the option Os is enabled ๐ฅ
It defaults to 3 when -Os is in effect. Otherwise, if 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๐งฎ โ The cost to assume for a multiply instruction, with 4 being equal to a normal instruction โจ-munalign-prob-threshold=probability๐ โ Sets the probability threshold for unaligning branches. When you're tuning for ARC700 and optimizing for speed, branches without a filled delay slot are preferably emitted unaligned and long, unless profiling shows the branch is taken with a probability belowprobability. The default is(REG_BR_PROB_BASE/2), i.e.5000๐
The following options are maintained for backward compatibility, but are 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 deprecated now. Big-endian code is supported by configuring GCC to build thearceb-elf32andarceb-linux-uclibctargets, where big endian is the default ๐-mlittle-endian,-EL๐ โ Compiles code for little-endian targets. Using these is deprecated now. Little-endian code is supported by configuring GCC to build thearc-elf32andarc-linux-uclibctargets, where little endian is the default ๐-mbarrel_shifterโ Replaced by-mbarrel-shifter๐-mdpfp_compactโ Replaced by-mdpfp-compact๐-mdpfp_fastโ Replaced by-mdpfp-fast๐-mdsp_packaโ Replaced by-mdsp-packa๐-mEAโ Replaced by-mea๐-mmac_24โ Replaced by-mmac-24๐-mmac_d16โ Replaced by-mmac-d16๐-mspfp_compactโ Replaced by-mspfp-compact๐-mspfp_fastโ Replaced by-mspfp-fast๐-mtune=cpuโ The valuesarc600,arc601,arc700andarc700-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 complies with the ARM Procedure Call Standard for all functions, even when it isn't strictly needed for the code to run correctly. Pairing it with-fomit-frame-pointermeans stack frames don't get generated for leaf functions. The default is-mno-apcs-frame, and this option is deprecated ๐ฅ-mapcs๐ฅ โ A synonym for-mapcs-frame. It's deprecated too ๐-mthumb-interwork๐ โ Generates code that supports calling between the ARM and Thumb instruction sets. Without it, on pre-v5 architectures, the two instruction sets can't be reliably used inside one program. The default is-mno-thumb-interwork, since turning this on generates slightly larger code. In AAPCS configurations this option is meaningless ๐-mno-sched-prolog๐งญ โ Stops instructions in the function prologue from getting reordered, or merged with instructions in the function's body. That means every function starts with a recognizable set of instructions (or one of a small set of different function prologues), so you can use that info to find where functions start inside an executable piece of code. The default is-msched-prolog๐-mfloat-abi=name๐ โ Picks which floating-point ABI to use. The permissible values aresoft,softfpandhard:softโ GCC generates output with library calls for floating-point operations ๐softfpโ Lets you generate code with hardware floating-point instructions, but still uses the soft-float calling conventions ๐งฉhardโ Generates floating-point instructions and uses FPU-specific calling conventions โก
The default depends on your specific target configuration.
Heads up, bestie ๐จ: the hard-float and soft-float ABIs are not link-compatible. You have to compile your entire program with the same ABI, and link it with a compatible set of libraries, or things will get messy fr fr.
-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 compiling for a little-endian processor ๐-mbe8,-mbe32๐งฌ โ When you're linking a big-endian image, these pick between the BE8 and BE32 formats. They have no effect on little-endian images and get ignored there. The default depends on the selected target architecture: for ARMv6 and later it's BE8, and for older architectures it's BE32. ARM has deprecated the BE32 format ๐ฅฒ-march=name[+extension...]๐๏ธ โ Specifies the name of the target ARM architecture. GCC uses this name to figure out what kinds of instructions it's allowed to emit when generating assembly code. You can use this option together with-mcpu=or instead of it โจ
Okay so 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, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, armv8.1-m.main, iwmmxt and iwmmxt2. ๐โจ
Additionally, the following architectures, which lack support for the Thumb execution state, are recognized but support is deprecated: armv4.
๐ Heads up, bestie: armv4 is still accepted, but it's deprecated, so don't build your whole life around it. ๐ฅ
Many of the architectures support extensions ๐ These can be added by appending +extension to the architecture name. Extension options are processed in order and capabilities accumulate, so they stack up like a good outfit ๐ An extension will also enable any necessary base extensions upon which it depends. For example, the +crypto extension will always enable the +simd extension. The exception to the additive construction is for extensions that are prefixed with +no...: these extensions disable the specified option and any other extensions that may depend on the presence of that extension. Main character energy, but make it a kill switch ๐
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. ๐ญ The +nofp basically erases +simd before it even gets a chance to show up.
Most extension names are generically named, but their effect depends on the architecture they're applied to. For example, the +simd option can be applied to both armv7-a and armv8-a architectures, but it will enable the original ARMv7-A Advanced SIMD (Neon) extensions for armv7-a and the ARMv8-A variant for armv8-a. Same name, different glow-up โจ
The list below shows the supported extensions for each architecture. Architectures not mentioned do not support any extensions. ๐ธ
armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk ๐ฆ
+fpโ The VFPv2 floating-point instructions. The extension+vfpv2can be used as an alias for this extension.+nofpโ Disable the floating-point instructions. ๐ โโ๏ธ
armv7 ๐
The common subset of the ARMv7-A, ARMv7-R and ARMv7-M architectures. ๐ซถ
+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers. The extension+vfpv3-d16can be used as an alias for this extension. Note that floating-point is not supported by the base ARMv7-M architecture, but is compatible with both the ARMv7-A and ARMv7-R architectures. ๐+nofpโ Disable the floating-point instructions.
armv7-a ๐
+mpโ The multiprocessing extension. ๐ง+secโ The security extension. ๐+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers. The extension+vfpv3-d16can be used as an alias for this extension.+simdโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions. The extensions+neonand+neon-vfpv3can be used as aliases for this extension.+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers.+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations.+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and the half-precision floating-point conversion operations.+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers.+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations.+neon-vfpv4โ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions.+nosimdโ Disable the Advanced SIMD instructions (does not disable floating point).+nofpโ Disable the floating-point and Advanced SIMD instructions. ๐
armv7ve ๐
The extended version of the ARMv7-A architecture with support for virtualization. Very sus-in-a-good-way energy ๐
+fpโ The VFPv4 floating-point instructions, with 16 double-precision registers. The extension+vfpv4-d16can be used as an alias for this extension.+simdโ The Advanced SIMD (Neon) v2 and the VFPv4 floating-point instructions. The extension+neon-vfpv4can be used as an alias for this extension.+vfpv3-d16โ The VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers.+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations.+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and the half-precision floating-point conversion operations.+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers.+neonโ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions. The extension+neon-vfpv3can be used as an alias for this extension.+neon-fp16โ The Advanced SIMD (Neon) v1 and the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations.+nosimdโ Disable the Advanced SIMD instructions (does not disable floating point).+nofpโ Disable the floating-point and Advanced SIMD instructions.
armv8-a โจ
+crcโ The Cyclic Redundancy Check (CRC) instructions. ๐งผ+simdโ The ARMv8-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions. ๐+nocryptoโ Disable the cryptographic instructions.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.
armv8.1-a ๐
+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions.+nocryptoโ Disable the cryptographic instructions.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.
armv8.2-a, armv8.3-a ๐
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions.+fp16fmlโ The half-precision floating-point fmla extension. This also enables the half-precision floating-point extension and Advanced SIMD and floating-point instructions.+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions.+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions.+dotprodโ Enable the Dot Product extension. This also enables Advanced SIMD instructions.+nocryptoโ Disable the cryptographic extension.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.+i8mmโ 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions.+bf16โ Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions.
armv8.4-a ๐ฆ
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension and the half-precision floating-point fmla extension.+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions as well as the Dot Product extension.+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension.+nocryptoโ Disable the cryptographic extension.+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions.+sbโ Speculation Barrier Instruction.+predresโ Execution and Data Prediction Restriction Instructions.+i8mmโ 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions.+bf16โ Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions.
armv8.5-a ๐
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions as well as the Dot Product extension and the half-precision floating-point fmla extension.+simdโ okay so this one switches on the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension. ๐โจ+cryptoโ the cryptographic instructions ๐. This also turns on the Advanced SIMD and floating-point instructions, and the Dot Product extension. Iconic multitasking ๐+nocryptoโ disables the cryptographic extension. Bye bye, crypto ๐+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions all at once. Major drama, use with care ๐+i8mmโ 8-bit Integer Matrix Multiply instructions ๐งฎ. It also enables Advanced SIMD and floating-point instructions, so you get the whole squad ๐ซถ+bf16โ 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, the Dot Product extension, and the half-precision floating-pointfmlaextension. Main character energy, no cap โญ+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 as well as the Dot Product extension ๐+nocryptoโ disables the cryptographic extension ๐+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions. It's giving a full reset ๐งน+i8mmโ 8-bit Integer Matrix Multiply instructions ๐งฎ. Also enables Advanced SIMD and floating-point instructions ๐+bf16โ Brain half-precision floating-point instructions ๐ง . Also enables Advanced SIMD and floating-point instructions ๐ฆ
๐ armv7-r
+fp.spโ the single-precision VFPv3 floating-point instructions ๐. You can also use+vfpv3xdas an alias for this extension, so pick your fave ๐+fpโ the VFPv3 floating-point instructions with 16 double-precision registers โจ. You can use+vfpv3-d16as an alias for this one too ๐ง+vfpv3xd-d16-fp16โ the single-precision VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐ธ+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐ฅ+nofpโ disables the floating-point extension ๐ โโ๏ธ+idivโ the ARM-state integer division instructions โ+noidivโ disables the ARM-state integer division extension ๐
๐ armv7e-m
+fpโ the single-precision VFPv4 floating-point instructions โญ+fpv5โ the single-precision FPv5 floating-point instructions ๐ฅ+fp.dpโ the single- and double-precision FPv5 floating-point instructions ๐+nofpโ disables the floating-point extensions ๐ซถ
๐ armv8.1-m.main
+dspโ the DSP instructions ๐ถ+mveโ the M-Profile Vector Extension (MVE) integer instructions ๐ฆ+mve.fpโ the M-Profile Vector Extension (MVE) integer instructions and the 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โ these turn on the Custom Datapath Extension (CDE) on selected coprocessors ๐งฉ. Which coprocessors you get depends on the numbers you give in the options, and those numbers have to be 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 ๐งฉ. The numbers in the options, from 0 to 7, decide which coprocessors get it ๐ข
๐ง 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 tells the compiler to auto-detect the architecture of the build computer ๐ต๏ธโโ๏ธ. Lowkey this only works on GNU/Linux right now, and not every architecture gets recognized ๐ญ. If the auto-detect doesn't work out, the option just has no effect ๐ซ .
๐ -mtune=name
This option picks the name of the target ARM processor that GCC should tune the performance of your code for ๐ฏ. Some ARM implementations can run better when you use this option, so it's worth a look ๐ . These are the permissible names:
arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110,
strongarm1100, 0strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t,
arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi,
arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s,
arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s,
arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9,
cortex-a12, cortex-a15, cortex-a17, cortex-a32, cortex-a35, cortex-a53,
cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76,
cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, ares,
cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-m0,
cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7, cortex-m23,
cortex-m33, cortex-m35p, cortex-m55, cortex-x1, cortex-m1.small-multiply,
cortex-m0.small-multiply, cortex-m0plus.small-multiply, exynos-m1, marvell-pj4,
neoverse-n1, neoverse-n2, neoverse-v1, xscale, iwmmxt, iwmmxt2, ep9312, fa526,
fa626, fa606te, fa626te, fmp626, fa726te, xgene1
Also, this option can tell GCC to tune your code for a big.LITTLE system ๐ง ๐. These are the permissible names for that:
cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a57.cortex-a53,
cortex-a72.cortex-a53, cortex-a72.cortex-a35, cortex-a73.cortex-a53,
cortex-a75.cortex-a55, cortex-a76.cortex-a55
-mtune=generic-arch tells GCC to tune the performance for a blend of processors within the architecture arch ๐. The goal is code that runs well on the most popular processors right now, balancing the optimizations that help some CPUs in the range while avoiding the performance pitfalls of others ๐ซถ. The effects of this option may change in future GCC versions, since CPU models come and go ๐ฆ.
-mtune accepts the same extension options as -mcpu, but the extension options don't change how the generated code gets tuned ๐.
-mtune=native tells the compiler to auto-detect the CPU of the build computer ๐. Same deal as before: this is only supported on GNU/Linux for now, and not all architectures are recognized ๐ฌ. If the auto-detect doesn't work, the option has no effect ๐ค.
๐ -mcpu=name[+extension...]
This picks the name of the target ARM processor ๐ธ. GCC uses that name to figure out the target ARM architecture (as if you'd set it with -march) and the ARM processor type to tune for performance (as if you'd set it with -mtune) ๐
. If you use -march or -mtune together with this option, those two win for their own part of the job ๐ฅ.
Lots of the supported CPUs have optional architectural extensions ๐งฉ. When they do, those extensions are usually turned on by default. But if there are implementations that lack an extension, you can use the extension syntax to turn off the ones that are missing ๐ โโ๏ธ.
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 overrides the floating-point and SIMD extension instructions that would otherwise be available ๐จ.
For example, cortex-a9 shows up in three major 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 the 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-r52andcortex-m7๐ท+nosimdโ disables the SIMD instructions (but keeps the floating-point ones) ongeneric-armv7-a,cortex-a5,cortex-a7andcortex-a9๐ง+cryptoโ okay bestie, this one switches on the cryptographic instructions ๐โจ forcortex-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. Iconic ๐
Okay so the generic-armv7-a pseudo target is giving main character energy ๐ by defaulting to VFPv3 with 16 double-precision registers. It accepts these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16 and neon-vfpv4. Their meanings are the same as the extensions for -march=armv7-a, no cap ๐ซถ
-mcpu=generic-arch is also allowed, and it's the same as -march=arch -mtune=generic-arch. Check -mtune for the full tea ๐
-mcpu=native tells the compiler to auto-detect the CPU of the build computer ๐ง Lowkey this only works on GNU/Linux right now, and not every architecture gets recognized. If the auto-detect doesn't work out, the option just does nothing ๐ฅฒ
-mfpu=nameโ this one describes what floating-point hardware (or hardware emulation) the target has ๐ 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-armv8andcrypto-neon-fp-armv8. Also,neonis just an alias forneon-vfpv3, andvfpis an alias forvfpv2โจ
auto is the default and it's kinda special ๐ฆ It makes the compiler pick the floating-point and Advanced SIMD instructions based on the settings of -mcpu and -march.
If the hardware you picked includes the NEON extension (like -mfpu=neon), heads up: floating-point operations won't be generated by GCC's auto-vectorization pass unless -funsafe-math-optimizations is also specified ๐ This is because NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic (denormal values get treated as zero, specifically), so using NEON instructions might lead to a loss of precision ๐
You can also set the fpu name at function level with the target("fpu=") function attributes or pragmas ๐
-mfp16-format=nameโ pick the format of the"__fp16"half-precision floating-point type ๐ The permissible names arenone,ieeeandalternative. The default isnone, and in that case the"__fp16"type isn't defined at all ๐ญ-mstructure-size-boundary=nโ this rounds up the sizes of all structures and unions to a multiple of the number of bits you set here ๐ The permissible values are8,32and64. The default varies between toolchains, but for the COFF targeted toolchain it's8. A value of64is only allowed if the underlying ABI supports it.
Going bigger can make faster, more efficient code, but it can also make your program bigger ๐ง Different values are potentially incompatible. Code compiled with one value can't necessarily work with code or libraries compiled with another value, if they swap info using structures or unions.
โ ๏ธ This option is deprecated. Bestie, don't build your whole life around it ๐
-mabort-on-noreturnโ generates a call to the function"abort"at the end of a"noreturn"function ๐ธ It runs if the function tries to return.-mlong-calls,-mno-long-callsโ this tells the compiler to do function calls by loading the function's address into a register first, and then making a subroutine call on that register ๐ฆ You need this switch if the target function lives outside the 64-megabyte addressing range of the offset-based version of the subroutine call instruction.
Even with this switch on, not every function call becomes a long call ๐ The heuristic is that static functions, functions with the "short_call" attribute, functions inside the scope of a #pragma no_long_calls directive, and functions whose definitions were already compiled within the current compilation unit don't get turned into long calls. The exceptions are that weak function definitions, functions with the "long_call" attribute or the "section" attribute, and functions inside the scope of a #pragma long_calls directive always get turned into long calls.
This feature isn't enabled by default ๐
โโ๏ธ Specifying -mno-long-calls restores the default behavior, and so does putting the function calls inside the scope of a #pragma long_calls_off directive. Also, these switches have no effect on how the compiler generates code for function calls made via function pointers ๐
-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โ specifies the register to use for PIC addressing โจ For the standard PIC base case, the default is any suitable register the compiler decides on. For the single PIC base case, the default isR9if the target is EABI based or stack-checking is enabled. Otherwise the default isR10.-mpic-data-is-text-relativeโ assumes the displacement between the text and data segments is fixed at static link time ๐ This permits using PC-relative addressing operations to access data known to be in the data segment. For non-VxWorks RTP targets this option is enabled by default. When it's disabled on those targets, it'll enable-msingle-pic-baseby default.-mpoke-function-nameโ writes the name of each function into the text section, right before the function prologue ๐ฅ The generated code is kinda like this:
t0
.ascii "arm_poke_function_name", 0
.align
t1
.word 0xff000000 + (t1 - t0)
arm_poke_function_name
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
When you do a stack backtrace, code can 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, then we know there's a function name embedded right before this location, with a length of ((pc[-3]) & 0xff000000) ๐โจ
-mthumb,-marmโ picks between generating code that runs in ARM state and code that runs in Thumb state ๐ Most configurations default to ARM state, but that default can be changed by configuring GCC with the--with-mode=stateconfigure option.
You can also override ARM and Thumb mode for each function with the target("thumb") and target("arm") function attributes or pragmas ๐ฆ
-mflip-thumbโ switches ARM/Thumb modes on alternating functions ๐ This one is only here for regression testing of mixed Thumb/ARM code generation, so it's not meant for ordinary code compiling. Please don't use it for your everyday stuff, bestie ๐ญ-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 header switches to Thumb mode before the rest of the function runs. This lets these functions get called from non-interworking code. This option isn't valid in AAPCS configurations, because interworking is already enabled by default there ๐-mcaller-super-interworkingโ lets calls via function pointers (including virtual functions) run correctly, no matter whether the target code was compiled for interworking or not ๐ There's a small overhead in the cost of executing a function pointer if you turn this on. Also not valid in AAPCS configurations, since interworking is enabled by default there too ๐ซถ-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 from"cp15"directly (supported in thearm6karchitecture); andauto, which uses the best available method for the selected processor. The default setting isautoโจ-mtls-dialect=dialectโ specifies the dialect to use for accessing thread local storage ๐ Two dialects are supported,gnuandgnu2. Thegnudialect selects the original GNU scheme for supporting local and global dynamic TLS models. Thegnu2dialect selects the GNU descriptor scheme, which gives better performance for shared libraries ๐ฅ The GNU descriptor scheme is compatible with the original scheme, but it does require new assembler, linker and library support. Initial and local exec TLS models 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 when"ldrd"instructions with overlapping destination and base registers are used ๐ญ This option avoids generating those instructions. It's enabled by default when-mcpu=cortex-m3is specified.-munaligned-access,-mno-unaligned-accessโ enables (or disables) reading and writing of 16- and 32-bit values from addresses that aren't 16- or 32-bit aligned ๐ง By default, unaligned access is disabled for all pre-ARMv6, all ARMv6-M and for ARMv8-M Baseline architectures, and enabled for all other architectures. If unaligned access isn't enabled, then words in packed data structures get accessed one byte at a time ๐ฅน
The ARM attribute Tag_CPU_unaligned_access ๐ฆ gets set in the generated object file to either true or false, depending on how this option is set. If unaligned access is turned on, the preprocessor symbol __ARM_FEATURE_UNALIGNED gets defined too โจ. It's giving "tell the other tools what I'm up to" energy ๐
.
-mneon-for-64bitsโ ๐ This one is deprecated and literally does nothing, bestie. Zero effect. ๐-mslow-flash-dataโ ๐ง Assumes that loading data from flash is slower than fetching instructions, so it keeps literal loads to a minimum for better performance. This is only supported when compiling for ARMv7 M-profile, it's off by default, and it conflicts with-mword-relocations๐.-masm-syntax-unifiedโ ๐ธ Assumes that inline assembler uses unified asm syntax. The default is currently off, which means divided syntax. This option has no impact on Thumb2, but it may change in future releases of GCC ๐. > Divided syntax should be considered deprecated, so maybe start thinking about moving on ๐ .-mrestrict-itโ ๐ Restricts IT block generation so it follows the rules of ARMv8-A. IT blocks can only contain a single 16-bit instruction from a select set of instructions. This is on by default for ARMv8-A Thumb mode โจ.-mprint-tune-infoโ ๐ Prints CPU tuning information as a comment in the assembler file. This is only used for regression testing of the compiler and is not meant for ordinary code compiling ๐ โโ๏ธ. It's disabled by default.-mverbose-cost-dumpโ ๐ Enables verbose cost model dumping in the debug dump files. This is provided for debugging the compiler ๐ ๏ธ.-mpure-codeโ ๐ Doesn't allow constant data to be placed in code sections. Also, when compiling for ELF object format, it gives all text sections the ELF processor-specific section attributeSHF_ARM_PURECODE. This is only available when generating non-pic code for M-profile targets ๐.-mcmseโ ๐ก๏ธ Generates secure code following the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification", which you can find at<https://developer.arm.com/documentation/ecm0359818/latest/>๐.-mfix-cmse-cve-2021-35465โ ๐จ Mitigates a potential security issue with the "VLLDM" instruction on some M-profile devices when using CMSE (CVE-2021-365465). This is enabled by default when-mcpu=is used with "cortex-m33", "cortex-m35p" or "cortex-m55". To turn the mitigation off, use-mno-fix-cmse-cve-2021-35465๐ซถ.-mfdpic,-mno-fdpicโ ๐ฆ Selects the FDPIC ABI, which uses 64-bit function descriptors to represent pointers to functions. When the compiler is configured for "arm-*-uclinuxfdpiceabi" targets, this is on by default and implies-fPIEif none of the PIC/PIE-related options are given. On other targets, it only turns on the FDPIC-specific code generation features, so you should explicitly provide the PIC/PIE-related options as needed ๐ง .
Static linking is not supported, because it would still involve the dynamic linker when the program self-relocates. If that behavior is acceptable to you, use -static and -Wl,-dynamic-linker options ๐.
The opposite -mno-fdpic option is useful (and required) for building the Linux kernel with the same ("arm-*-uclinuxfdpiceabi") toolchain you used for your userland programs ๐.
โจ AVR Options โจ
Here's the AVR squad ๐ง. These options are defined for AVR implementations:
-mmcu=mcuโ ๐ง Specifies the Atmel AVR instruction set architecture (ISA) or MCU type.- The default for this option is
avr2๐. - GCC supports the following AVR devices and ISAs ๐:
"avr2"โ "Classic" devices with up to 8 KiB of program memory. mcu ="attiny22", "attiny26", "at90s2313", "at90s2323", "at90s2333", "at90s2343", "at90s4414", "at90s4433", "at90s4434", "at90c8534", "at90s8515", "at90s8535""avr25"โ "Classic" devices with up to 8 KiB of program memory and with the "MOVW" instruction. mcu ="attiny13", "attiny13a", "attiny24", "attiny24a", "attiny25", "attiny261", "attiny261a", "attiny2313", "attiny2313a", "attiny43u", "attiny44", "attiny44a", "attiny45", "attiny48", "attiny441", "attiny461", "attiny461a", "attiny4313", "attiny84", "attiny84a", "attiny85", "attiny87", "attiny88", "attiny828", "attiny841", "attiny861", "attiny861a", "ata5272", "ata6616c", "at86rf401""avr3"โ "Classic" devices with 16 KiB up to 64 KiB of program memory. mcu ="at76c711", "at43usb355""avr31"โ "Classic" devices with 128 KiB of program memory. mcu ="atmega103", "at43usb320""avr35"โ "Classic" devices with 16 KiB up to 64 KiB of program memory and with the "MOVW" instruction. mcu ="attiny167", "attiny1634", "atmega8u2", "atmega16u2", "atmega32u2", "ata5505", "ata6617c", "ata664251", "at90usb82", "at90usb162""avr4"โ "Enhanced" devices with up to 8 KiB of program memory. mcu ="atmega48", "atmega48a", "atmega48p", "atmega48pa", "atmega48pb", "atmega8", "atmega8a", "atmega8hva", "atmega88", "atmega88a", "atmega88p", "atmega88pa", "atmega88pb", "atmega8515", "atmega8535", "ata6285", "ata6286", "ata6289", "ata6612c", "at90pwm1", "at90pwm2", "at90pwm2b", "at90pwm3", "at90pwm3b", "at90pwm81""avr5"โ "Enhanced" devices with 16 KiB up to 64 KiB of program memory. mcu ="atmega16", "atmega16a", "atmega16hva", "atmega16hva2", "atmega16hvb", "atmega16hvbrevb", "atmega16m1", "atmega16u4", "atmega161", "atmega162", "atmega163", "atmega164a", "atmega164p", "atmega164pa", "atmega165", "atmega165a", "atmega165p", "atmega165pa", "atmega168", "atmega168a", "atmega168p", "atmega168pa", "atmega168pb", "atmega169", "atmega169a", "atmega169p", "atmega169pa", "atmega32", "atmega32a", "atmega32c1", "atmega32hvb", "atmega32hvbrevb", "atmega32m1", "atmega32u4", "atmega32u6", "atmega323", "atmega324a", "atmega324p", "atmega324pa", "atmega325", "atmega325a", "atmega325p", "atmega325pa", "atmega328", "atmega328p", "atmega328pb", "atmega329", "atmega329a", "atmega329p", "atmega329pa", "atmega3250", "atmega3250a", "atmega3250p", "atmega3250pa", "atmega3290", "atmega3290a", "atmega3290p", "atmega3290pa", "atmega406", "atmega64", "atmega64a", "atmega64c1", "atmega64hve", "atmega64hve2", "atmega64m1", "atmega64rfr2", "atmega640", "atmega644", "atmega644a", "atmega644p", "atmega644pa", "atmega644rfr2", "atmega645", "atmega645a", "atmega645p", "atmega649", "atmega649a", "atmega649p", "atmega6450", "atmega6450a", "atmega6450p", "atmega6490", "atmega6490a", "atmega6490p", "ata5795", "ata5790", "ata5790n", "ata5791", "ata6613c", "ata6614q", "ata5782", "ata5831", "ata8210", "ata8510", "ata5702m322", "at90pwm161", "at90pwm216", "at90pwm316", "at90can32", "at90can64", "at90scr100", "at90usb646", "at90usb647", "at94k", "m3000""avr51"โ "Enhanced" devices with 128 KiB of program memory. mcu ="atmega128", "atmega128a", "atmega128rfa1", "atmega128rfr2", "atmega1280", "atmega1281", "atmega1284", "atmega1284p", "atmega1284rfr2", "at90can128", "at90usb1286", "at90usb1287""avr6"โ "Enhanced" devices with 3-byte PC, i.e. with more than 128 KiB of program memory. mcu ="atmega256rfr2", "atmega2560", "atmega2561", "atmega2564rfr2""avrxmega2"โ "XMEGA" devices with more than 8 KiB and up to 64 KiB of program memory. mcu ="atxmega8e5", "atxmega16a4", "atxmega16a4u", "atxmega16c4", "atxmega16d4", "atxmega16e5", "atxmega32a4", "atxmega32a4u", "atxmega32c3", "atxmega32c4", "atxmega32d3", "atxmega32d4", "atxmega32e5""avrxmega3"โ "XMEGA" devices with up to 64 KiB of combined program memory and RAM, and with program memory visible in the RAM address space. mcu ="attiny202", "attiny204", "attiny212", "attiny214", "attiny402", "attiny404", "attiny406", "attiny412", "attiny414", "attiny416", "attiny417", "attiny804", "attiny806", "attiny807", "attiny814", "attiny816", "attiny817", "attiny1604", "attiny1606", "attiny1607", "attiny1614", "attiny1616", "attiny1617", "attiny3214", "attiny3216", "attiny3217", "atmega808", "atmega809", "atmega1608", "atmega1609", "atmega3208", "atmega3209", "atmega4808", "atmega4809""avrxmega4"โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory. mcu ="atxmega64a3", "atxmega64a3u", "atxmega64a4u", "atxmega64b1", "atxmega64b3", "atxmega64c3", "atxmega64d3", "atxmega64d4""avrxmega5"โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory and more than 64 KiB of RAM. mcu ="atxmega64a1", "atxmega64a1u""avrxmega6"โ "XMEGA" devices with more than 128 KiB of program memory. mcu ="atxmega128a3", "atxmega128a3u", "atxmega128b1", "atxmega128b3", "atxmega128c3", "atxmega128d3", "atxmega128d4", "atxmega192a3", "atxmega192a3u", "atxmega192c3", "atxmega192d3", "atxmega256a3", "atxmega256a3b", "atxmega256a3bu", "atxmega256a3u", "atxmega256c3", "atxmega256d3", "atxmega384c3", "atxmega384d3""avrxmega7"โ "XMEGA" devices with more than 128 KiB of program memory and more than 64 KiB of RAM. mcu ="atxmega128a1", "atxmega128a1u", "atxmega128a4u""avrtiny"โ "TINY" Tiny core devices with 512 B up to 4 KiB of program memory. mcu ="attiny4", "attiny5", "attiny9", "attiny10", "attiny20", "attiny40""avr1"โ This ISA is implemented by the minimal AVR core and is supported for the assembler only ๐ฃ. mcu ="attiny11", "attiny12", "attiny15", "attiny28", "at90s1200"
- The default for this option is
-mabsdataโ ๐ฆ Assumes that all data in static storage can be accessed by LDS / STS instructions. This only has an effect on reduced Tiny devices like ATtiny40. See also the "absdata" AVR Variable Attributes,variable attribute ๐งพ.-maccumulate-argsโ ๐งบ Accumulates outgoing function arguments and acquires/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 ๐.
okay so popping the arguments off the stack after a function call can be super pricey on AVR ๐ธ, which means letting the stack space pile up can actually lead to smaller executables ๐ฆ. The arguments don't have to get removed from the stack after each call, so no cap, it's giving galaxy brain ๐ง โจ
This option can lead to reduced code size for functions that make a bunch of calls to functions that take 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 and epilogues get expanded as calls to the appropriate subroutines, so the code size comes out smaller ๐ง-mdouble=bits,-mlong-double=bitsโ sets the size (in bits) of the"double"or"long double"type, respectively ๐ Possible values forbitsare32and64. Whether or not a specific value forbitsis allowed depends on the--with-double=and--with-long-double=configure options (https://gcc.gnu.org/install/configure.html#avr), and the same applies for the default values of the options.-mgas-isr-prologuesโ ISRs are allowed to 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). This feature is turned on by default if optimization is on (but not with-Og, see Optimize Options), and if GNU Binutils supports PR21683 (https://sourceware.org/PR21683).-mint8โ assume"int"is an 8-bit integer ๐ This affects the sizes of all types: a"char"is 1 byte, an"int"is 1 byte, a"long"is 2 bytes, and a"long long"is 4 bytes.
โ ๏ธ Heads up, please note this option does not conform to the C standards, but it does result in smaller code size.
-mmain-is-OS_taskโ don't save registers in"main"๐ This has the same effect as attaching the"OS_task"attribute (see AVR Function Attributes) to"main". It's activated per default if optimization is on.-mn-flash=numโ assume the flash memory has a size ofnumtimes 64 KiB โจ-mno-interruptsโ the generated code is not compatible with hardware interrupts ๐ The upside is that code size comes out smaller.-mrelaxโ tries to swap aCALL(resp.JMP) for the shorterRCALL(resp.RJMP) instruction, if applicable ๐ฆ Setting-mrelaxjust adds the--mlink-relaxoption to the assembler's command line and the--relaxoption to the linker's command line.
Jump relaxing is performed by the linker, because jump offsets aren't known until the code is located ๐บ๏ธ So the assembler code the compiler generates stays the same, but the instructions in the executable may differ from the instructions in the assembler code.
Relaxing must be turned on if linker stubs are needed, see the section on "EIND" and linker stubs below.
-mrmwโ assume the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT๐ฅ-mshort-callsโ assumeRJMPandRCALLcan target the whole program memory ๐ธ This option is used internally for multilib selection. It is not an optimization option, and you don't need to set it by hand.-msp8โ treat the stack pointer register as an 8-bit register, i.e. assume the high byte of the stack pointer is zero ๐ In general, you don't need to set this option by hand.
This option is used internally by the compiler to select and build multilibs for architectures avr2 and avr25. These architectures mix devices with and without SPH. For any setting other than -mmcu=avr2 or -mmcu=avr25, the compiler driver adds or removes this option from the compiler proper's command line, because the compiler then knows if the device or architecture has an 8-bit stack pointer and thus no SPH register or not.
-mstrict-Xโ use the address registerXthe way the hardware proposes ๐ง That meansXis only used in indirect, post-increment or pre-decrement addressing.
Without this option, the X register may be used in the same way as Y or Z, which then gets emulated by additional instructions. For example, loading a value with X+const addressing, with a small non-negative const < 64 into a register Rn, is performed as:
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 ๐ง The user takes responsibility for supplying the subprocesses (compiler proper, assembler and linker) with appropriate command line options. This means the user has to supply her private device specs file by means of-specs=path-to-specs-file. There is no more need for the option-mmcu=mcu.
This option can also serve as a replacement for the older way of specifying custom device-specs files, which needed -B some-path to point to a directory containing a folder named "device-specs", which contains a specs file named "specs-mcu", where mcu was specified by -mmcu=mcu.
-Waddr-space-convertโ warn about conversions between address spaces in the case where the resulting address space is not contained in the incoming address space โ ๏ธ-Wmisspelled-isrโ warn if the ISR is misspelled, i.e. without the__vectorprefix. Enabled by default. ๐
โจ "EIND" and Devices with More Than 128 Ki Bytes of Flash โจ
Pointers in the implementation are 16 bits wide. The address of a function or label is 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 space, there's a special function register called EIND ๐ It serves as the most significant part of the target address when EICALL or EIJMP instructions are used.
Indirect jumps and calls on these devices are handled as follows by the compiler, and they come with some limitations ๐
- The compiler never sets
EIND. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or might readEINDdirectly in order to emulate an indirect call/jump by means of aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved/restored in function or interrupt service routine prologue/epilogue. - For indirect calls to functions and computed goto, the linker generates stubs. Stubs are jump pads, sometimes also called trampolines. Thus, the indirect call/jump jumps to such a stub. 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, a custom linker script has to be used in order 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 is legitimate for user-specific startup code to set up
EINDearly, for example by means of initialization code located in section.init3. Such code runs prior to the general startup code that initializes RAM and calls constructors, but after the bit of startup code from AVR-LibC 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 final location of that label is in a code segment outside the segment where the stubs are located.
- The address of a label is taken by means of the
Like so, for the first condition:
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The compiler emits such
gsmodifiers for code labels in the following situations:- Taking the address of a function or code label.
- Computed goto.
- If prologue-save function is used, see the
-mcall-prologuescommand-line option. - Switch/case dispatch tables. If you do not want such dispatch tables, you can specify the
-fno-jump-tablescommand-line option. - C and C++ constructors/destructors called during startup/shutdown.
- If the tools hit a gs() modifier explained above.
- Jumping to non-symbolic addresses like so is not supported:
int main (void)
{
/* Call function at word address 0x2 */
return ((int(*)(void)) 0x2)();
}
Instead, a stub has to be set up, i.e. the function has to be called through a symbol (func_4 in the example):
int main (void)
{
extern int func_4 (void);
/* Call function at byte address 0x4 */
return func_4();
}
and the application be linked with -Wl,--defsym,func_4=0x4. Alternatively, func_4 can be defined in the linker script.
๐ฆ Handling of the "RAMPD", "RAMPX", "RAMPY" and "RAMPZ" Special Function Registers
Okay so bestie, some AVR chips have more memory than a 16-bit pointer can reach ๐ญ To get past that 64 KiB wall, the chip uses a little "RAMP" register as the high part of the address ๐
The X, Y, Z address registers get glued to RAMPX, RAMPY, RAMPZ (respectively) to make one wide address โจ And RAMPD teams up with direct addressing, same energy ๐ฆ
- The startup code sets all the
RAMPspecial function registers to zero ๐ธ - If an AVR Named Address Spaces, named address space other than generic or
__flashis used,RAMPZgets set as needed before the operation ๐ - If the device supports RAM bigger than 64 KiB and the compiler has to change
RAMPZto pull off an operation,RAMPZgets reset to zero afterwards ๐งน - If the device has a specific
RAMPregister, the ISR prologue/epilogue saves and restores that SFR and sets it to zero in case the ISR code might (implicitly) use it ๐ซถ
๐ 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. Do not skip this, bestie!
โจ AVR Built-in Macros โจ
GCC defines several built-in macros so your code can test for the presence or absence of features ๐ง Almost any of the following built-in macros are deduced from device capabilities and thus triggered by the -mmcu= command-line option ๐
For even more AVR-specific built-in macros see AVR Named Address Spaces and AVR Built-in Functions ๐
"__AVR_ARCH__"
Built-in macro that resolves to a decimal number that identifies the architecture and depends on the -mmcu=mcu option. Possible values are:
2, 25, 3, 31, 35, 4, 5, 51, 6formcu="avr2","avr25","avr3","avr31","avr35","avr4","avr5","avr51","avr6", respectively100, 102, 103, 104, 105, 106, 107formcu="avrtiny","avrxmega2","avrxmega3","avrxmega4","avrxmega5","avrxmega6","avrxmega7", respectively
If mcu specifies a device, this built-in macro is set accordingly. For example, with -mmcu=atmega8 the macro is defined to 4 ๐
"__AVR_Device__"
Setting -mmcu=device defines this built-in macro, which reflects the device's name ๐ฆ For example, -mmcu=atmega8 defines the built-in macro "__AVR_ATmega8__", -mmcu=attiny261a defines "__AVR_ATtiny261A__", etc.
The built-in macros' names follow the scheme "__AVR_Device__" where Device is the device name as from the AVR user manual. The difference between Device in the built-in macro and device in -mmcu=device is that the latter is always lowercase ๐
If device is not a device but only a core architecture like avr51, this macro is not defined.
"__AVR_DEVICE_NAME__"
Setting -mmcu=device defines this built-in macro to the device's name. For example, with -mmcu=atmega8 the macro is defined to "atmega8" ๐ธ
If device is not a device but only a core architecture like avr51, this macro is not defined.
"__AVR_XMEGA__"
The device / 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 to perform 16-bit register-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. This also means that 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 stack pointer (SP) register is treated as 8-bit respectively 16-bit register by the compiler. The definition of these macros is affected by -mtiny-stack ๐
"__AVR_HAVE_SPH__" and "__AVR_SP8__"
The device has the SPH (high part of stack pointer) special function register or has an 8-bit stack pointer, respectively. The definition of these macros is affected by -mmcu= and in the cases of -mmcu=avr2 and -mmcu=avr25 also by -msp8 ๐ธ
"__AVR_HAVE_RAMPD__", "__AVR_HAVE_RAMPX__", "__AVR_HAVE_RAMPY__" and "__AVR_HAVE_RAMPZ__"
The device has the "RAMPD", "RAMPX", "RAMPY", "RAMPZ" special function register, respectively ๐ซถ
"__NO_INTERRUPTS__"
This macro reflects the -mno-interrupts command-line option ๐
"__AVR_ERRATA_SKIP__" and "__AVR_ERRATA_SKIP_JMP_CALL__"
Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum ๐ Skip instructions are "SBRS", "SBRC", "SBIS", "SBIC" and "CPSE". The second macro is only defined if "__AVR_HAVE_JMP_CALL__" is also set.
"__AVR_ISA_RMW__"
The device has Read-Modify-Write instructions (XCH, LAC, LAS and LAT) ๐ฅ
"__AVR_SFR_OFFSET__=offset"
Instructions that can address I/O special function registers directly, like IN, OUT, SBI, etc., may use a different address than an instruction that accesses RAM, like LD or STS. This offset depends on the device architecture and has to be subtracted from the RAM address in order to get the respective I/O address ๐ง
"__AVR_SHORT_CALLS__"
The -mshort-calls command line option is set โจ
"__AVR_PM_BASE_ADDRESS__=addr"
Some devices support reading from flash memory by means of LD* instructions. The flash memory is seen in the data address space at an offset of "__AVR_PM_BASE_ADDRESS__". If this macro is not defined, this feature is not available. If 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 attribute "progmem" and "pgm_read_*" ๐
"__WITH_AVRLIBC__"
The compiler is configured to be used together with AVR-Libc. See the --with-avrlibc configure option ๐
"__HAVE_DOUBLE_MULTILIB__"
Defined if -mdouble= acts as a multilib option ๐ฆ
"__HAVE_DOUBLE32__" and "__HAVE_DOUBLE64__"
Defined if the compiler supports 32-bit double resp. 64-bit double. The actual layout is specified by option -mdouble= ๐
"__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__"
Reflects the "--with-libf7={libgcc|math|math-symbols}" configure option ("https://gcc.gnu.org/install/configure.html#avr") โจ
๐ฆ Blackfin Options ๐ฆ
-mcpu=cpu[-sirevision]โ Okay, this one picks your target Blackfin processor ๐ฅ Right now,cpucan be one ofbf512,bf514,bf516,bf518,bf522,bf523,bf524,bf525,bf526,bf527,bf531,bf532,bf533,bf534,bf536,bf537,bf538,bf539,bf542,bf544,bf547,bf548,bf549,bf542m,bf544m,bf547m,bf548m,bf549m,bf561,bf592. The optionalsirevisionis the silicon revision of the target chip, and any workarounds for that revision get enabled ๐ Ifsirevisionisnone, no workarounds are enabled. Ifsirevisionisany, 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. Ifsirevisionisnone,"__SILICON_REVISION__"is not defined. Ifsirevisionisany,"__SILICON_REVISION__"is defined to be0xffff. If this optionalsirevisionis not used, GCC assumes the latest known silicon revision of the targeted Blackfin processor ๐ GCC defines a preprocessor macro for the specifiedcpu. For thebfin-elftoolchain, this option causes the hardware BSP provided by libgloss to be linked in if-msimis not given. Without this option,bf532is used as the processor by default. Note that support forbf561is incomplete. Forbf561, only the preprocessor macro is defined ๐-msimโ Specifies that the program will be run on the simulator ๐ง This causes the simulator BSP provided by libgloss to be linked in. This option has effect only forbfin-elftoolchain. Certain other options, such as-mid-shared-libraryand-mfdpic, imply-msim๐-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions ๐ธ This avoids the instructions to save, set up and restore frame pointers and makes an extra register available in leaf functions ๐ซถ-mspecld-anomalyโ When enabled, the compiler ensures that the generated code does not contain speculative loads after jump instructions ๐ If this option is used,"__WORKAROUND_SPECULATIVE_LOADS"is defined ๐ฆ-mno-specld-anomalyโ Don't generate extra code to prevent speculative loads from occurring ๐-mcsync-anomalyโ When enabled, the compiler ensures that the generated code does not containCSYNCorSSYNCinstructions too soon after conditional branches โจ If this option is used,"__WORKAROUND_SPECULATIVE_SYNCS"is defined ๐-mno-csync-anomalyโ Don't generate extra code to preventCSYNCorSSYNCinstructions from occurring too soon after a conditional branch ๐ง-mlow64kโ When enabled, the compiler is free to take advantage of the knowledge that the entire program fits into the low 64k of memory ๐-mno-low64kโ ๐ธ Okay so this one tells the compiler to assume the program can be arbitrarily large ๐. It's the default, so you're already getting it.-mstack-check-l1โ ๐ก๏ธ Turns on stack checking using info the uClinux kernel stashes in L1 scratchpad memory. Lowkey clutch. โจ-mid-shared-libraryโ ๐ฆ Generates code that supports shared libraries through the library ID method. This is how you get execute in place and shared libraries in an environment with no virtual memory management ๐. It implies-fPIC, and with abfin-elftarget it also implies-msim๐ .-mno-id-shared-libraryโ ๐ โโ๏ธ Generates code that doesn't assume ID-based shared libraries are in use. This is the default, bestie.-mleaf-id-shared-libraryโ ๐ Supports shared libraries through the library ID method, but assumes this library or executable won't link against any other ID shared libraries. Because of that promise, the compiler gets to use faster code for jumps and calls ๐๏ธ.-mno-leaf-id-shared-libraryโ ๐ข Doesn't assume the code won't link against any ID shared libraries. The result is slower code for jump and call instructions. Not the vibe, but it's the safe bet.-mshared-library-id=nโ ๐ข Sets the identification number of the ID-based shared library being compiled. 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โ ๐งฉ Generates code that lets the data segment live in a different area of memory from the text segment. This is giving execute in place in an environment without virtual memory management, because it gets rid of relocations against the text section ๐ซถ.-mno-sep-dataโ ๐ฆ Generates code that assumes the data segment follows the text segment. This is the default.-mlong-calls,-mno-long-callsโ ๐ Tells the compiler to make function calls by first loading the function's address into a register, then doing a subroutine call on that register. You need this if the target function lives outside the 24-bit addressing range of the offset-based subroutine call instruction ๐. This feature is not enabled by default, and-mno-long-callsbrings back the default behaviour. Heads up: these switches do nothing for function calls made through function pointers ๐.-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 in the name of performance ๐.-minline-pltโ ๐ช Enables inlining of PLT entries in function calls to functions that aren't known to bind locally. Fair warning: it has no effect unless you also use-mfdpic๐ซ .-mmulticoreโ ๐ง Builds a standalone application for multicore Blackfin processors. This makes the compiler use start files and link scripts that support multicore, and it defines the macro"__BFIN_MULTICORE"๐. It can only be used with-mcpu=bf561[-sirevision].- It can be paired with
-mcoreaor-mcorebfor the one-application-per-core model. Without either of those, you get the single-application/dual-core model ๐ฏ. In that model, Core B's main function should be named"coreb_main". - Skip this option entirely and you get the single-core application model ๐ฑ.
- It can be paired with
-mcoreaโ ๐ ฐ๏ธ Builds a standalone application for Core A of BF561 when you're using the one-application-per-core model. It uses the right start files and link scripts for Core A and defines"__BFIN_COREA". This one can only be used alongside-mmulticore๐.-mcorebโ ๐ ฑ๏ธ Same energy as-mcorea, but for Core B of BF561. It defines"__BFIN_COREB", and when you use it,"coreb_main"should be used instead of"main"๐. It also needs-mmulticore.-msdramโ ๐พ Builds a standalone application for SDRAM. The start files and link scripts put your app into SDRAM and define"__BFIN_SDRAM". Make sure your loader initialises SDRAM before it loads 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โ ๐๏ธ Specifies the name of the target architecture. GCC uses this to decide which kinds of instructions it can 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โ ๐ฅ๏ธ Chooses startup files and a linker script that suit the simulator.-msdata=defaultโ ๐๏ธ Puts small global and static data into the.neardatasection, which is pointed to by registerB14๐. Small uninitialised global and static data goes into the.bsssection, which sits right next to.neardata. Small read-only data goes into the.rodatasection. The sections for big chunks of data are.fardata,.farand.const๐งณ.-msdata=allโ ๐ Puts all data, not just the small stuff, into the sections reserved for small data, and uses addressing relative to theB14register to get to them.-msdata=noneโ ๐ซ Makes no use of the small-data sections and uses absolute addresses to access all data. All initialised global and static data goes in.fardata, all uninitialised data goes in.far, and all constant data goes in.const๐ .
๐ฆ CRIS Options ๐ฆ
These options are defined specifically for the CRIS ports ๐.
-march=architecture-type,-mcpu=architecture-typeโ ๐ ๏ธ Generates code for the specified architecture. The choices for architecture-type arev3,v8andv10, which correspond to ETRAX 4, ETRAX 100, and ETRAX 100 LX respectively. The default isv0.-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 themulsandmuluinstructions for CPU models where it applies. This option is active by default.-mpdebugโ ๐ Enables CRIS-specific verbose debug-related information in the assembly code. It also turns off the#NO_APPformatted-code indicator that goes to the assembler at the start of the assembly file ๐.-mcc-initโ ๐ฆ Doesn't use condition-code results from previous instructions. It always emits compare and test instructions before any use of 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 options (theno-ones eliminate it) arrange for the stack frame, individual data and constants to be aligned to the maximum single data access size for the chosen CPU model. The default is 32-bit alignment. ABI details, like structure layout, are not affected by these ๐.-m32-bit,-m16-bit,-m8-bitโ ๐ข Similar to the stack, data and const align options above, these make the stack frame, writable data and constants all 32-bit, 16-bit or 8-bit aligned. The default is 32-bit alignment.-mno-prologue-epilogue,-mprologue-epilogueโ ๐จ With-mno-prologue-epilogue, the normal function prologue and epilogue that set up the stack frame are left out, and no return instructions or return sequences get generated.
โ ๏ธ Bestie, read this one twice. Only use -mno-prologue-epilogue alongside careful visual inspection of the compiled code. No warnings or errors are generated when call-saved registers need saving, or when storage for local variables needs allocating. Nothing will warn you, so you're on your own ๐.
-melfโ ๐ซฅ A legacy no-op option, so it does nothing.-simโ ๐ฎ Links with the input-output functions from a simulator library. Code, initialised data and zero-initialised data are allocated consecutively ๐งต.-sim2โ ๐งญ Works like-sim, but also passes linker options that locate initialised data at0x40000000and zero-initialised data at0x80000000โจ.
๐ธ CR16 Options ๐ธ
These options are defined specifically for the CR16 ports ๐.
-mmacโ ๐งฎ Enables the use of multiply-accumulate instructions. It's disabled by default.-mcr16cplus,-mcr16cโ ๐ง Generates code for the CR16C or CR16C+ architecture. The CR16C+ architecture is the default.-msimโ ๐ฅ๏ธ Links the librarylibsim.a, which is compatible with the simulator. This only applies to the ELF compiler.-mint32โ ๐ข Chooses a 32-bit wide integer type.-mbit-opsโ ๐๏ธ Generates"sbit"and"cbit"instructions for bit manipulations.-mdata-model=modelโ ๐งณ Chooses a data model. The choices for model arenear,farormedium, andmediumis the default. Note thatfaris not valid with-mcr16c, since 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 areck801,ck802,ck803,ck807, andck810. The default isck810๐.
Bestie, the -mcpu=cpu flag is how you tell GCC which C-SKY target processor you're building for ๐
. The 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, and ck810ftv ๐ธ
-mbig-endian,-EB,-mlittle-endian,-ELโ Pick your byte order! Big-endian or little-endian, your call ๐ง. Little-endian is the default, so if you don't pick, you get that โจ-mfloat-abi=nameโ This one chooses which floating-point ABI you're vibing with. Your options aresoft,softfp, andhard๐softmakes GCC spit out library calls for all the floating-point math. No hardware floating-point stuff, just library calls, fr fr.softfplets GCC use the hardware floating-point instructions, but it still follows the soft-float calling conventions ๐ฆhardgives you floating-point instructions and FPU-specific calling conventions. Full hardware glow-up ๐ฅ
The default depends on your specific target configuration, so check what you're working with first ๐
Heads up, 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 disaster ๐
-mhard-float,-msoft-floatโ Pick hardware or software floating-point implementations. The default is soft float ๐-mdouble-float,-mno-double-floatโ When-mhard-floatis in effect, this turns on generation of double-precision float instructions. It's the default except when you're compiling for CK803 ๐-mfdivdu,-mno-fdivduโ When-mhard-floatis in effect, this enables generation of"frecipd","fsqrtd", and"fdivd"instructions. Also the default except when compiling for CK803 โจ-mfpu=fpuโ Choose your floating-point processor! This one only works with-mhard-float. The values forfpuare:fpv2_sf, which is equivalent to-mno-double-float -mno-fdivdufpv2, which is-mdouble-float -mno-divdufpv2_divd, which is-mdouble-float -mdivdu
-melrw,-mno-elrwโ Turns the extended"lrw"instruction on or off. It defaults to on for CK801 and off for everything else ๐-mistack,-mno-istackโ Enable interrupt stack instructions. The default is off. Also,-mistackis required if you want to handle the"interrupt"and"isr"function attributes ๐-mmpโ Enable multiprocessor instructions. Default is off ๐-mcpโ Enable coprocessor instructions. Default is off ๐ฆ-mcacheโ Enable coprocessor instructions. Default is off ๐ธ-msecurityโ Enable C-SKY security instructions. Default is off ๐ฅ-mtrustโ Enable C-SKY trust instructions. Default is off ๐-mdsp,-medsp,-mvdspโ Enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively. All of these default to off ๐ง-mdiv,-mno-divโ Generate divide instructions. Default is off ๐-msmart,-mno-smartโ Generate code for Smart Mode, which only uses registers numbered 0-7 so you can use 16-bit instructions. This is ignored for CK801, where it's already the required behavior, and it defaults to on for CK802. For other targets, the default is off ๐ซถ-mhigh-registers,-mno-high-registersโ Generate code using the high registers numbered 16-31. This isn't supported on CK801, CK802, or CK803, but it's enabled by default for other processors โญ-manchor,-mno-anchorโ Generate code using global anchor symbol addresses ๐-mpushpop,-mno-pushpopโ Generate code using"push"and"pop"instructions. This one defaults to on ๐-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ Generate code using"stm"and"ldm"instructions. This isn't supported on CK801, but it's enabled by default on other processors ๐-mconstpool,-mno-constpoolโ Create constant pools in the compiler instead of handing that job off to the assembler. This is the default and it's required for correct code generation on CK801 and CK802. It's optional on other processors ๐ง-mstack-size,-mno-stack-sizeโ Emit".stack_size"directives for each function in the assembly output. This defaults to off ๐-mccrt,-mno-ccrtโ Generate code for the C-SKY compiler runtime instead of libgcc. Defaults to off ๐ฆ-mbranch-cost=nโ Set the branch costs to roughlyninstructions. The default is 1 โจ-msched-prolog,-mno-sched-prologโ Permit scheduling of function prologue and epilogue sequences. Okay, real talk, this one is a little risky:
Using this option can result in code that isn't compliant with the C-SKY V2 ABI prologue requirements, and that code might not be debuggable or backtraceable. It's disabled by default, so leave it off unless you know exactly why you need it ๐
-msimโ Links the librarylibsemi.a, which is compatible with the simulator. This only applies to the ELF compiler ๐ธ
๐ฆ Darwin Options ๐ฆ
These options are defined for all architectures running the Darwin operating system ๐
FSF GCC on Darwin doesn't make "fat" object files. Instead, it makes an object file for the single architecture that GCC was built to target. Apple's GCC on Darwin does make "fat" files if you use multiple -arch options. It does this by running the compiler or linker multiple times and then joining the results together with lipo ๐
The subtype of the file you create (like ppc7400, ppc970, or i686) gets decided by the flags that specify the ISA GCC is targeting, like -mcpu or -march. If you want to override that, the -force_cpusubtype_ALL option can do it โจ
The Darwin tools act differently when they hit an ISA mismatch, so let's break it down ๐ง
- The assembler,
as, only lets you use instructions that are valid for the subtype of the file it's generating. So you can't put 64-bit instructions in appc750object file, sorry not sorry ๐ - The linker for shared libraries,
/usr/bin/libtool, fails and prints an error if you ask it to create a shared library with a less restrictive subtype than its input files. For example, trying to put appc970object file in appc7400library 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 get scanned left-to-right ๐
A framework directory is just a directory with frameworks in it. A framework is a directory with a Headers and/or PrivateHeaders directory sitting directly inside it, and its name ends in .framework. The name of a framework is that directory's name without the .framework part. Headers for the framework live in one of those two directories, and Headers gets searched first ๐
A subframework is a framework directory that lives inside a framework's Frameworks directory. Includes of subframework headers can only show up in a header of the framework that contains the subframework, or in a sibling subframework header. Two subframeworks are siblings if they live in the same framework ๐ฏ
A subframework shouldn't share a name with a framework, and if it does, you'll get a warning. Right now, a subframework can't have subframeworks of its own, but that might get extended in the future ๐
The standard frameworks live in /System/Library/Frameworks and /Library/Frameworks. An example include looks like this, where Framework is the framework's name and header.h lives in the PrivateHeaders or Headers directory:
#include <Framework/header.h>
-iframeworkdirโ This is like-F, except the directory gets treated as a system directory ๐ง The big difference is that with-iframework, the compiler won't warn you about constructs inside header files found throughdir. This option is only valid for the C family of languages ๐-gusedโ Emit debugging information for symbols that are used. If you're using the stabs debugging format, this enables-feliminate-unused-debug-symbols. It's ON by default ๐ฆ-gfullโ Emit debugging information for all symbols and types. Go big or go home ๐ฅ-fconstant-cfstringsโ This is just an alias for-mconstant-cfstrings๐ธ-mconstant-cfstringsโ When the NeXT runtime is being used (which is the default on these systems), this overrides any-fconstant-string-classsetting. It also makes"@"...""literals get laid out as constant CoreFoundation strings ๐-mmacosx-version-min=versionโ The earliest version of MacOS X that this executable will run on isversion. Typical values supported forversioninclude12,10.12, and10.5.8๐
If the compiler was built to use the system's headers by default, then the default for this option is the system version the compiler is running on. Otherwise, the default is to make choices that are compatible with as many systems and code bases as possible โจ
-mkernelโ Turns on kernel development mode! This sets-static,-fno-common,-fno-use-cxa-atexit,-fno-exceptions,-fno-non-call-exceptions,-fapple-kext,-fno-weak, and-fno-rtti, where applicable. For PowerPC targets, it also sets-mno-altivec,-msoft-float,-fno-builtin, and-mlong-branch๐-mone-byte-boolโ Overrides the defaults for"bool"so thatsizeof(bool)==1. By default,sizeof(bool)is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86, so this option has no effect on x86 ๐
Warning, bestie! The -mone-byte-bool switch makes GCC generate code that isn't binary compatible with code generated without it. You may need to recompile all the other modules in your program, including the system libraries. Only use this switch to conform to a non-default data model ๐
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ Generate code that's perfect 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. Checkman ld(1)for more info ๐-arch_errors_fatalโ Makes errors about files with the wrong architecture fatal, so they stop the build instead of just being a vibe ๐ญ-bind_at_loadโ marks the output file so the dynamic linker binds all undefined references when the file gets loaded or launched โจ-bundleโ makes a Mach-o bundle format file ๐ฆ Seeman ld(1)for the full tea.-bundle_loader executableโ names the executable that will load the output file being linked ๐ Seeman ld(1)for more info.-dynamiclibโ when you pass this, GCC makes a dynamic library instead of an executable at link time, using the Darwin libtool command ๐ฆ-force_cpusubtype_ALLโ gives GCC's output file the ALL subtype, instead of one controlled by-mcpuor-march๐-allowable_client client_nameโ passed to the Darwin linker ๐-client_nameโ passed to the Darwin linker ๐-compatibility_versionโ passed to the Darwin linker ๐-current_versionโ passed to the Darwin linker ๐-dead_stripโ passed to the Darwin linker ๐-dependency-fileโ passed to the Darwin linker ๐-dylib_fileโ passed to the Darwin linker ๐-dylinker_install_nameโ passed to the Darwin linker ๐-dynamicโ passed to the Darwin linker ๐-exported_symbols_listโ passed to the Darwin linker ๐-filelistโ passed to the Darwin linker ๐-flat_namespaceโ passed to the Darwin linker ๐-force_flat_namespaceโ passed to the Darwin linker ๐-headerpad_max_install_namesโ passed to the Darwin linker ๐-image_baseโ passed to the Darwin linker ๐-initโ passed to the Darwin linker ๐-install_nameโ passed to the Darwin linker ๐-keep_private_externsโ passed to the Darwin linker ๐-multi_moduleโ passed to the Darwin linker ๐-multiply_definedโ passed to the Darwin linker ๐-multiply_defined_unusedโ passed to the Darwin linker ๐-noall_loadโ passed to the Darwin linker ๐-no_dead_strip_inits_and_termsโ passed to the Darwin linker ๐-nofixprebindingโ passed to the Darwin linker ๐-nomultidefsโ passed to the Darwin linker ๐-noprebindโ passed to the Darwin linker ๐-noseglinkeditโ passed to the Darwin linker ๐-pagezero_sizeโ passed to the Darwin linker ๐-prebindโ passed to the Darwin linker ๐-prebind_all_twolevel_modulesโ passed to the Darwin linker ๐-private_bundleโ passed to the Darwin linker ๐-read_only_relocsโ passed to the Darwin linker ๐-sectalignโ passed to the Darwin linker ๐-sectobjectsymbolsโ passed to the Darwin linker ๐-whyloadโ passed to the Darwin linker ๐-seg1addrโ passed to the Darwin linker ๐-sectcreateโ passed to the Darwin linker ๐-sectobjectsymbolsโ passed to the Darwin linker ๐-sectorderโ passed to the Darwin linker ๐-segaddrโ passed to the Darwin linker ๐-segs_read_only_addrโ passed to the Darwin linker ๐-segs_read_write_addrโ passed to the Darwin linker ๐-seg_addr_tableโ passed to the Darwin linker ๐-seg_addr_table_filenameโ passed to the Darwin linker ๐-seglinkeditโ passed to the Darwin linker ๐-segprotโ passed to the Darwin linker ๐-segs_read_only_addrโ passed to the Darwin linker ๐-segs_read_write_addrโ passed to the Darwin linker ๐-single_moduleโ passed to the Darwin linker ๐-staticโ passed to the Darwin linker ๐-sub_libraryโ passed to the Darwin linker ๐-sub_umbrellaโ passed to the Darwin linker ๐-twolevel_namespaceโ passed to the Darwin linker ๐-umbrellaโ passed to the Darwin linker ๐-undefinedโ passed to the Darwin linker ๐-unexported_symbols_listโ passed to the Darwin linker ๐-weak_reference_mismatchesโ passed to the Darwin linker ๐-whatsloadedโ passed to the Darwin linker ๐
These are all passed along to the Darwin linker, and the Darwin linker man page describes them in detail ๐๐
๐ DEC Alpha Options ๐
These -m options are defined for the DEC Alpha implementations, so if you're on an Alpha, these are your people ๐ง
-mno-soft-float,-msoft-floatโ use (or skip) the hardware floating-point instructions for floating-point operations. When-msoft-floatis specified, functions inlibgcc.ado the floating-point work instead. Unless they get replaced by routines that emulate the floating-point operations, or compiled in a way that makes them call those emulation routines, these routines end up issuing floating-point operations. If you're compiling for an Alpha without floating-point operations, you must make sure the library is built so it doesn't call them ๐ Heads up: Alpha implementations without floating-point operations are still required to have floating-point registers.-mfp-reg,-mno-fp-regsโ generates code that uses (or doesn't use) the floating-point register set.-mno-fp-regsimplies-msoft-float. If the floating-point register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results get passed in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value that's called by code compiled with-mno-fp-regsmust also be compiled with that option. A typical use of this option is building a kernel that doesn't use, and hence doesn't need to save and restore, any floating-point registers ๐ฅ
โ ๏ธ Non-standard calling sequence alert: anything calling -mno-fp-regs code with a floating-point argument or return value has to be compiled with that option too.
-mieeeโ the Alpha architecture has floating-point hardware built for maximum performance, and it's mostly compliant with the IEEE floating-point standard. Full compliance needs software help though ๐ This option generates fully IEEE-compliant code, except the inexact-flag isn't maintained (see below). When it's turned on, the preprocessor macro"_IEEE_FP"is defined during compilation. The resulting code is less efficient, but it can correctly support denormalized numbers and exceptional IEEE values such as not-a-number and plus/minus infinity. Other Alpha compilers call this option-ieee_with_no_inexact.-mieee-with-inexactโ like-mieee, except the generated code also maintains the IEEE inexact-flag. Turning this on makes the code implement fully-compliant IEEE math. In addition to"_IEEE_FP","_IEEE_FP_EXACT"is defined as a preprocessor macro. On some Alpha implementations the resulting code may run significantly slower than the code generated by default. 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โ controls which floating-point related traps are enabled ๐ฆ Other Alpha compilers call this option-fptm trap-mode. The trap mode can be set to one of four values:nโ this is the default (normal) setting. The only traps enabled are the ones that can't be disabled in software (e.g., division by zero trap).uโ on top of the traps enabled byn, underflow traps are enabled as well.suโ likeu, but the instructions are marked as safe for software completion (see Alpha architecture manual for details).suiโ likesu, but inexact traps are enabled as well.
-mfp-rounding-mode=rounding-modeโ selects the IEEE rounding mode ๐ Other Alpha compilers call this option-fprm rounding-mode. The rounding-mode can be one of:nโ normal IEEE rounding mode. Floating-point numbers are rounded towards the nearest machine number, or towards the even machine number in case of a tie.mโ round towards minus infinity.cโ chopped rounding mode. Floating-point numbers are rounded towards zero.dโ dynamic rounding mode. A field in the floating-point control register (fpcr, see Alpha architecture reference manual) controls the rounding mode in effect. The C library initializes this register for rounding towards plus infinity. Thus, unless your program modifies thefpcr,dcorresponds to round towards plus infinity.
-mtrap-precision=trap-precisionโ in the Alpha architecture, floating-point traps are imprecise ๐ญ That means without software assistance it's impossible to recover from a floating trap, and program execution normally 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 your application's requirements, you can pick a different level of precision:pโ program precision. This option is the default, and means a trap handler can only identify which program caused a floating-point exception.fโ function precision. The trap handler can determine the function that caused a floating-point exception.iโ instruction precision. The trap handler can determine the exact instruction that caused a floating-point exception.
Other Alpha compilers provide the equivalent options called -scope_safe and -resumption_safe.
-mieee-conformantโ marks the generated code as IEEE conformant ๐
โ ๏ธ Don't 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 checks whether a 32- or 64-bit integer constant can be built from smaller constants in two or three instructions. If it can't, it outputs the constant as a literal and generates code to load it from the data segment at run time. Use this option to require GCC to build all integer constants using code, even if it takes more instructions (the maximum is six). You typically use this option to build a shared library dynamic loader. Since it's a shared library itself, it must relocate itself in memory before it can find the variables and constants in its own data segment โจ-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ indicates 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 specified via-mcpu=option, or that of the CPU on which GCC was built if none is specified.-mfloat-vax,-mfloat-ieeeโ generates code that uses (or doesn't use) VAX F and G floating-point arithmetic instead of IEEE single and double precision ๐ธ-mexplicit-relocs,-mno-explicit-relocsโ older Alpha assemblers provided no way to generate symbol relocations except via assembler macros, and 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 is built and sets the default accordingly ๐-msmall-data,-mlarge-dataโ when-mexplicit-relocsis in effect, static data is accessed via gp-relative relocations. When-msmall-datais used, objects 8 bytes long or smaller are placed in a small data area (the".sdata"and".sbss"sections) and accessed via 16-bit relocations off of the$gpregister. This limits the size of the small data area to 64KB, but allows the variables to be accessed directly via a single instruction. The default is-mlarge-data. With this option, the data area is limited to just below 2GB. Programs that 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,-fpicimplies-msmall-data, and-fPICimplies-mlarge-data๐-msmall-text,-mlarge-text: okay so-msmall-texttells the compiler to assume the code of the whole program (or shared library) fits in 4MB, which means it's reachable with a branch instruction ๐ง. When-msmall-datais used, the compiler can assume all local symbols share the same$gpvalue, so a function call drops from 4 instructions to 1. Iconic efficiency ๐ โจ
The default is -mlarge-text. ๐ธ
-mcpu=cpu_type: this sets the instruction set and instruction scheduling parameters for machine typecpu_type๐. You can name the EV style or use the chip number. GCC has scheduling parameters for the EV4, EV5, and EV6 families and picks its default instruction set from whatever processor you specify. If you don't name a processor, GCC defaults to the processor the compiler was built on ๐ฆ.
Supported values for cpu_type are:
ev4,ev45,21064: schedules as an EV4 and has no instruction set extensions ๐ev5,21164: schedules as an EV5 and has no instruction set extensions ๐ev56,21164a: schedules as an EV5 and supports theBWXextension ๐pca56,21164pc,21164PC: schedules as an EV5 and supports theBWXandMAXextensions ๐ev6,21264: schedules as an EV6 and supports theBWX,FIX, andMAXextensions ๐ฅev67,21264a: schedules as an EV6 and supports theBWX,CIX,FIX, andMAXextensions ๐
Native toolchains also support the value native, which picks the best architecture option for the host processor. -mcpu=native has no effect if GCC doesn't recognize the processor ๐ซถ.
-mtune=cpu_type: this sets only the instruction scheduling parameters for machine typecpu_type. The instruction set stays exactly the same ๐.
Native toolchains also support the value native, which picks the best architecture option for the host processor. -mtune=native has no effect if GCC doesn't recognize the processor ๐.
-mmemory-latency=time: this sets the latency the scheduler should assume for typical memory references as the application sees them. It's super dependent on the app's memory access patterns and the size of the external cache on the machine ๐ง .
Valid options for time are:
number: a decimal number representing clock cycles โฑ๏ธL1,L2,L3,main: the compiler has estimates of clock cycles for "typical" EV4 & EV5 hardware for the Level 1, 2, and 3 caches (also called Dcache, Scache, and Bcache), as well as main memory. Heads up,L3is only valid for EV5 ๐.
โจ eBPF Options โจ
-mframe-limit=bytes: this sets the hard limit for frame sizes, in bytes ๐ธ. Right now the value you specify should be less than or equal to32767. It defaults to whatever limit is imposed by the version of the Linux kernel being targeted ๐ง.-mkernel=version: this is the minimum kernel version that will run the compiled program ๐. GCC uses it to figure out which instructions to use, which kernel helpers to allow, and so on. Right nowversioncan be one of4.0,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,4.10,4.11,4.12,4.13,4.14,4.15,4.16,4.17,4.18,4.19,4.20,5.0,5.1,5.2,latest, ornative๐ฆ.-mbig-endian: generates code for a big-endian target ๐.-mlittle-endian: generates code for a little-endian target. This is the default ๐.-mxbpf: generates code for an expanded version of BPF, which relaxes some of the restrictions imposed by the BPF architecture โจ.-<Save and restore callee-saved registers at function entry and>exit, respectively.
๐ FR30 Options ๐
These options are defined specifically for the FR30 port ๐.
-msmall-model: uses the small address space model. This can produce smaller code, but it does assume that all symbolic values and addresses fit into a 20-bit range ๐ง.-mno-lsim: assumes runtime support has already been provided, so there's no need to include the simulator library (libsim.a) on the linker command line ๐ .
๐ฆ FT32 Options ๐ฆ
These options are defined specifically for the FT32 port ๐ธ.
-msim: specifies that the program will run on the simulator. This causes an alternate runtime startup and library to be linked. Bestie, you must not use this option when generating programs for real hardware ๐ซ. You have to provide your own runtime library for whatever I/O functions you need ๐ญ.-mlra: enables Local Register Allocation. It's still experimental for FT32, so by default the compiler uses standard reload ๐งช.-mnodiv: do not usedivandmodinstructions ๐ โโ๏ธ.-mft32b: enables use of the extended instructions of the FT32B processor ๐ฅ.-mcompress: compresses all code using the Ft32B code compression scheme ๐๏ธ.-mnopm: do not generate code that reads program memory ๐.
๐ FRV Options ๐
-mgpr-32: only 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: do not try to dynamically allocate condition code registers. Only use"icc0"and"fcc0"๐.-mdword: changes the ABI to use double word instructions ๐.-mno-dword: do not use double word instructions ๐ซ.-mdouble: use floating-point double instructions ๐ฆ.-mno-double: do not use floating-point double instructions ๐ซถ.-mmedia: use media instructions ๐ถ.-mno-media: do not use media instructions ๐ โโ๏ธ.-mmuladd: use multiply and add/subtract instructions โ.-mno-muladd: do not use multiply and add/subtract instructions โ.-mfdpic: selects the FDPIC ABI, which uses function descriptors to represent pointers to functions ๐. Without any PIC/PIE-related options, it implies-fPIE. With-fpicor-fpie, it assumes GOT entries and small data are within a 12-bit range from the GOT base address. With-fPICor-fPIE, GOT offsets are computed with 32 bits. With abfin-elftarget, this option implies-msim๐ง .-minline-plt: enables inlining of PLT entries in function calls to functions that are not known to bind locally ๐. It has no effect without-mfdpic. It's enabled by default if you're optimizing for speed and compiling for shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is on the command line ๐.-mTLS: assumes a large TLS segment when generating thread-local code ๐งต.-mtls: does not assume a large TLS segment when generating thread-local code ๐งต.-mgprel-ro: enables the use of"GPREL"relocations in the FDPIC ABI for data 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. With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols, and it avoids the need for a GOT entry for the referenced symbol, so it's more likely to be a win. If it isn't,-mno-gprel-rocan be used to disable it ๐ค.-multilib-library-pic: links with the (library, not FD) pic libraries ๐. It's implied by-mlibrary-pic, as well as by-fPICand-fpicwithout-mfdpic. You should never have to use it explicitly ๐.-mlinked-fp: follows the EABI requirement of always creating a frame pointer whenever a stack frame is allocated ๐ผ๏ธ. This option is enabled by default and can be disabled with-mno-linked-fp๐ซ.-mlong-calls: uses indirect addressing to call functions outside the current compilation unit ๐. This allows the functions to be placed anywhere within the 32-bit address space ๐.-malign-labels: tries to align labels to an 8-byte boundary by inserting NOPs into the previous packet ๐. This option only has an effect when VLIW packing is enabled. It doesn't create new packets; it just adds NOPs to existing ones ๐งฉ.-mlibrary-pic: generates position-independent EABI code ๐.-macc-4: use only the first four media accumulator registers ๐ฏ.-macc-8: use all eight media accumulator registers ๐ฏ.-mpack: packs VLIW instructions ๐ฆ.-mno-pack: do not pack VLIW instructions ๐ โโ๏ธ.-mno-eflags: do not mark ABI switches ine_flags๐ณ๏ธ.-mcond-move: enables the use of conditional-move instructions (default) โ .
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-cond-move: disables the use of conditional-move instructions โ.
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mscc: enables the use of conditional set instructions (default) โ .
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-scc: disables the use of conditional set instructions โ.
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mcond-exec: enables the use of conditional execution (default) โ .
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-cond-exec: disables the use of conditional execution โ.
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mvliw-branch: runs a pass to pack branches into VLIW instructions (default) ๐.
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-vliw-branch: does not run a pass to pack branches into VLIW instructions ๐ โโ๏ธ.
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mmulti-cond-exec: enables optimization of"&&"and"||"in conditional execution (default) ๐ง .
Heads up: this switch is mainly for debugging the compiler and will likely be removed in a future version. ๐
-mno-multi-cond-execโ okay so this one switches OFF the optimization of&&and||in conditional execution ๐ It's mainly a debugging tool for the compiler and will likely be removed in a future version ๐-mnested-cond-execโ turns ON nested conditional execution optimizations, and this is the default โจ Also mostly for compiler debugging, so it'll likely be removed in a future version too ๐ธ-mno-nested-cond-execโ the opposite! It disables nested conditional execution optimizations ๐ Again, mainly debugging, and likely gone later ๐ซถ-moptimize-membarโ removes redundantmembarinstructions from the compiler-generated code. It's on by default, so you get it for free ๐-mno-optimize-membarโ disables that automatic removal of redundantmembarinstructions from 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 โจ
These -m options are defined for GNU/Linux targets ๐ง
-mglibcโ uses the GNU C library. This is the default except on*-*-linux-*uclibc*,*-*-linux-*musl*and*-*-linux-*android*targets ๐-muclibcโ uses the uClibc C library. This is the default on*-*-linux-*uclibc*targets ๐-mmuslโ uses the musl C library. This is the default on*-*-linux-*musl*targets โญ-mbionicโ uses the Bionic C library. This is the default on*-*-linux-*android*targets ๐ฆ-mandroidโ compiles code that's compatible with the Android platform. This is the default on*-*-linux-*android*targets ๐ค- When compiling, it enables
-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐ - When linking, it makes the GCC driver pass Android-specific options to the linker ๐
- It also causes the preprocessor macro
__ANDROID__to be defined โจ
- When compiling, it enables
-tno-android-ccโ disables the compilation effects of-mandroid, i.e. it does not enable-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐-tno-android-ldโ disables the linking effects of-mandroid, i.e. it passes standard Linux linking options to the linker ๐งท
โจ H8/300 Options โจ
These -m options are defined for the H8/300 implementations ๐ง
-mrelaxโ shortens some address references at link time, when possible. It uses the linker option-relax๐-mhโ generates code for the H8/300H ๐-msโ generates code for the H8S ๐-mnโ generates code for the H8S and H8/300H in the normal mode. This switch has to be used with either-mhor-ms๐-ms2600โ generates code for the H8S/2600. This switch has to be used with-ms๐ธ-mexrโ extended registers get stored on the stack before a function with the monitor attribute runs. The default is-mexr. This option is only valid for H8S targets ๐-mno-exrโ extended registers do not get stored on the stack before a function with the monitor attribute runs. The default is-mno-exr. This option is only valid for H8S targets ๐-mint32โ makesintdata 32 bits by default ๐-malign-300โ on the H8/300H and H8S, uses the same alignment rules as the H8/300. The H8/300H and H8S normally align longs and floats on 4-byte boundaries, but-malign-300moves them to 2-byte boundaries. This option has no effect on the H8/300 ๐ง
โจ HPPA Options โจ
These -m options are defined for the HPPA family of computers ๐ฅ๏ธ
-march=architecture-typeโ generates code for the specified architecture. The choices are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors ๐๏ธ- To figure out the right architecture option for your machine, check out
/usr/lib/sched.modelson an HP-UX system ๐ - Code compiled for lower numbered architectures runs on higher numbered architectures, but not the other way around โ ๏ธ
- To figure out the right architecture option for your machine, check out
-mpa-risc-1-0,-mpa-risc-1-1,-mpa-risc-2-0โ synonyms for-march=1.0,-march=1.1, and-march=2.0respectively ๐ฏ-mcaller-copiesโ the caller copies function arguments that are passed by hidden reference ๐ซฃ Use this with care, because it's not compatible with the default 32-bit runtime. Only aggregates larger than eight bytes get passed by hidden reference, though, and this option gives you better compatibility with OpenMP ๐งฉ-mjump-in-delayโ this option is ignored and only provided for compatibility purposes ๐คท-mdisable-fpregsโ stops floating-point registers from being used in any manner ๐ซ This is necessary for compiling kernels that do lazy context switching of floating-point registers. If you use this option and then try to do floating-point operations, the compiler aborts ๐-mdisable-indexingโ stops the compiler from using indexing address modes. This avoids 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 โก- Such code is suitable for level 0 PA systems and kernels ๐ง
-mfast-indirect-callsโ generates code that assumes calls never cross space boundaries. This lets GCC emit code that performs faster indirect calls ๐๏ธ- This option does not work in the presence of shared libraries or nested functions ๐ โโ๏ธ
-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use, which is super handy for kernel code ๐ A register range is written as two registers separated by a dash, and you can separate multiple ranges with a comma ๐-mlong-load-storeโ generates 3-instruction load and store sequences, which are sometimes required by the HP-UX 10 linker. 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 type cpu-type. The choices for cpu-type 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 ๐ ๏ธ
โ ๏ธ Heads up bestie: this makes symbolic debugging impossible. It also triggers a bug in the HP-UX 8 and HP-UX 9 linkers, where they give bogus error messages when linking some programs ๐ญ
-msoft-floatโ generates output containing library calls for floating point ๐งฎ
โ ๏ธ Warning: the requisite libraries are not available for all HPPA targets. Normally the facilities of the machine's usual C compiler are used, but that can't be done directly in cross-compilation. You'll have to make your own arrangements to provide suitable library functions for cross-compilation ๐ซ
-msoft-float changes the calling convention in the output file, so it's only useful if you compile all of a program with this option. In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work ๐งฉ
-msioโ generates the predefine_SIOfor server IO. The default is-mwsio, which generates the predefines__hp9000s700,__hp9000s700__and_WSIOfor workstation IO. These options are available under HP-UX and HI-UX ๐จ๏ธ-mgnu-ldโ uses options specific to GNU ld. This passes-sharedtoldwhen building a shared library. It's the default when GCC is configured (explicitly or implicitly) with the GNU linker ๐ This option doesn't affect whichldgets called. It only changes what parameters get passed to thatld. Theldthat 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-btoldwhen building a shared library, and passes+Accept TypeMismatchtoldon all links. It's the default when GCC is configured (explicitly or implicitly) with the HP linker ๐ท๏ธ Like-mgnu-ld, this option doesn't affect whichldis called. Theldthat 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 over a predefined limit set by the branch type being used. The limits for normal calls are 7,600,000 and 240,000 bytes, respectively for the PA 2.0 and PA 1.X architectures. Sibcalls are always limited at 240,000 bytes ๐- Distances are measured from the beginning of functions when using the
-ffunction-sectionsoption, or when using the-mgasand-mno-portable-runtimeoptions together under HP-UX with the SOM linker ๐งญ - It's normally not desirable to use this option, because it degrades performance ๐ It may be useful in large applications, particularly when partial linking is used to build the application ๐ฐ
- The types of long calls used depend on the capabilities of the assembler and linker, and on the type of code being generated. The impact on systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, should be relatively small. However, an indirect call is used on 32-bit ELF systems in pic code, and it is quite long ๐
- Distances are measured from the beginning of functions when using the
Okay so, the HP-UX stuff is next, bestie, and it's giving very specific vibes ๐ง๐
-munix=unix-stdโ this one picks which UNIX standard you're vibing with ๐ธ It sets up the compiler predefines and chooses a startfile for that standard. The options are93,95, and98.93works on every HP-UX version.95needs HP-UX 10.10 or later, and98needs HP-UX 11.11 or later. If you don't pick one, the default depends on your HP-UX version:93on HP-UX 10.00,95from HP-UX 10.10 through 11.00, and98on 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 startfileunix95.oโจ-munix=98โ adds predefines for"_XOPEN_UNIX","_XOPEN_SOURCE_EXTENDED","_INCLUDE__STDC_A1_SOURCE", and"_INCLUDE_XOPEN_SOURCE_500", plus the startfileunix98.o๐
๐ญ Be careful with this one, bestie! Changing the UNIX standard changes the interfaces for a bunch of library routines, and it also messes with how the C library behaves. Handle it with extreme care ๐
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. Honestly, most GNU software doesn't do this yet ๐
-nolibdldโ stops the compiler from adding link options that searchlibdld.slwhen you use-staticon HP-UX 10 and later ๐-staticโ okay, the HP-UX version ofsetlocalein libc depends onlibdld.sl, and there's no archive version of that library ๐ญ So when you use-static, you need some special link options to deal with it. On HP-UX 10 and later, the GCC driver adds those options for you to link withlibdld.sl. The catch is that this makes the binary dynamic. On the 64-bit port, the linkers make dynamic binaries by default anyway. If you don't want the driver adding those link options, use-nolibdld๐ฆ-threadsโ adds multithreading support using the DCE thread library under HP-UX. This one sets flags for both the preprocessor and the linker ๐งต
โจ IA-64 Options โจ
These are the -m options for the Intel IA-64 architecture ๐
-mbig-endianโ generates code for a big-endian target. This is the HP-UX default ๐-mlittle-endianโ generates code for a little-endian target. This is the default for AIX5 and GNU/Linux ๐ซถ-mgnu-as,-mno-gnu-asโ generates (or doesn't) code for the GNU assembler. The default is-mgnu-asโจ-mgnu-ld,-mno-gnu-ldโ generates (or doesn't) code for the GNU linker. The default is-mgnu-ld๐ฅ-mno-picโ generates code that doesn't use a global pointer register. Heads up: the result isn't position independent code, and it breaks the IA-64 ABI ๐-mvolatile-asm-stop,-mno-volatile-asm-stopโ generates (or doesn't) a stop bit right before and right after volatile asm statements ๐-mregister-names,-mno-register-namesโ generates (or doesn't)in,loc, andoutregister names for the stacked registers. This can make assembler output easier to read ๐-mno-sdata,-msdataโ disables (or enables) optimizations that use the small data section. This can be handy for working around optimizer bugs ๐-mconstant-gpโ generates code that uses one constant global pointer value. This is useful when compiling kernel code ๐ง-mauto-picโ generates code that's self-relocatable. This one implies-mconstant-gp, and it's useful when compiling firmware code ๐-minline-float-divide-min-latencyโ generates inline floating-point divides using the minimum latency algorithm ๐ธ-minline-float-divide-max-throughputโ generates inline floating-point divides using the maximum throughput algorithm ๐ธ-mno-inline-float-divideโ doesn't generate inline code for floating-point divides ๐ซ-minline-int-divide-min-latencyโ generates inline integer divides using the minimum latency algorithm ๐-minline-int-divide-max-throughputโ generates inline integer divides using the maximum throughput algorithm ๐-mno-inline-int-divideโ doesn't generate inline code for integer divides ๐ซ-minline-sqrt-min-latencyโ generates inline square roots using the minimum latency algorithm ๐ฆ-minline-sqrt-max-throughputโ generates inline square roots using the maximum throughput algorithm ๐ฆ-mno-inline-sqrtโ doesn't generate inline code for"sqrt"๐ซ-mfused-madd,-mno-fused-maddโ does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions. The default is to use them ๐ฅ-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 go earlier than right before the instruction that triggered them. This can improve instruction scheduling, but it doesn't always ๐-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers. A fixed register is one the register allocator can't use, which is useful for kernel code ๐ You specify a range as two registers separated by a dash, and you can list several ranges separated by commas ๐-mtls-size=tls-sizeโ sets the bit size of immediate TLS offsets. Valid values are14,22, and64โจ-mtune=cpu-typeโ tunes the instruction scheduling for a specific 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,long, and pointer to 32 bits. The 64-bit environment setsintto 32 bits, andlongand pointer to 64 bits. These are HP-UX specific flags ๐-mno-sched-br-data-spec,-msched-br-data-specโ (dis/en)ables data speculative scheduling before reload. This results inld.ainstructions and the matching check instructionsld.c/chk.a. It's disabled by default ๐ฆ-msched-ar-data-spec,-mno-sched-ar-data-specโ (en/dis)ables data speculative scheduling after reload. This results inld.ainstructions and the matching check instructionsld.c/chk.a. It's enabled by default ๐ธ-mno-sched-control-spec,-msched-control-specโ (dis/en)ables control speculative scheduling. This is only available during region scheduling, which means before reload. It results inld.sinstructions and the matching check instructionschk.s. It's disabled by default ๐-msched-br-in-data-spec,-mno-sched-br-in-data-specโ (en/dis)ables speculative scheduling of instructions that depend on data speculative loads before reload. This only works when-msched-br-data-specis enabled. It's enabled by default ๐ซถ-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ (en/dis)ables speculative scheduling of instructions that depend on data speculative loads after reload. This only works when-msched-ar-data-specis enabled. It's enabled by default ๐ซถ-msched-in-control-spec,-mno-sched-in-control-specโ (en/dis)ables speculative scheduling of instructions that depend on control speculative loads. This only works when-msched-control-specis enabled. It's enabled by default ๐ซถ-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ if enabled, data-speculative instructions only get scheduled when there are no other choices at the moment. This makes data speculation way more conservative. It's disabled by default ๐-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ if enabled, control-speculative instructions only get scheduled when there are no other choices at the moment. This makes control speculation way more conservative. It's disabled by default ๐-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ if enabled, speculative dependencies get counted when computing instruction priorities. This makes speculation a bit more conservative. It's disabled by default ๐-msched-spec-ldcโ uses a simple data speculation check. This one's on by default โจ-msched-control-spec-ldcโ uses a simple check for control speculation. This one's on by default โจ-msched-stop-bits-after-every-cycleโ places a stop bit after every cycle when scheduling. This one's on by default โจ-msched-fp-mem-deps-zero-costโ assumes floating-point stores and loads aren't likely to conflict when they're placed in the same instruction group. This one's disabled by default ๐-msel-sched-dont-check-control-specโ generates checks for control speculation in selective scheduling. This flag is disabled by default ๐-msched-max-memory-insns=max-insnsโ limits the number of memory insns per instruction group, and gives lower priority to later memory insns that try to schedule in the same group. This is often useful for preventing cache bank conflicts. The default value is1๐ง-msched-max-memory-insns-hard-limitโ turns the-msched-max-memory-insnslimit into a hard limit, so no more than that number of memory insns can go in an instruction group. Otherwise the limit is "soft," which means non-memory operations get preferred once the limit is hit, but memory operations can still get scheduled ๐ธ
โจ LM32 Options โจ
These -m options are defined for the LatticeMico32 architecture ๐ฆ
-mbarrel-shift-enabledโ enables barrel-shift instructions ๐ฅ-mdivide-enabledโ enables divide and modulus instructions ๐ฅ-mmultiply-enabledโ enables multiply instructions ๐ฅ-msign-extend-enabledโ enables sign extend instructions ๐ฅ-muser-enabledโ enables user-defined instructions ๐ฅ
โจ M32C Options โจ
-mcpu=nameโ okay so this one picks which CPU your code gets generated for ๐namecan ber8cfor the R8C/Tiny series,m16cfor the M16C (up to/60) series,m32cmfor the M16C/80 series, orm32cfor the M32C/80 series.-msimโ this is the simulator option โจ It links in an alternate runtime library that supports stuff like file I/O, so your program can actually do its thing while it's being tested.
โ ๏ธ bestie, do NOT use -msim when you're building for real hardware. You'll need to bring your own runtime library for whatever I/O functions you need.
-memregs=numberโ this sets how many memory-based pseudo-registers GCC uses during code generation ๐ They act like real registers, so it's a tradeoff: GCC gets better odds of fitting your code into the registers it has, but you pay a performance penalty for leaning on memory instead.
๐ every module in your program has to be compiled with the same number, and you should not use this option with GCC's default runtime libraries.
โจ M32R/D Options โจ
These -m options are defined for Renesas M32R/D architectures ๐ฆ
-m32r2โ generates code for the M32R/2.-m32rxโ generates code for the M32R/X.-m32rโ generates code for the M32R. This one's the default ๐-mmodel=smallโ assumes all objects live in the lower 16MB of memory, so their addresses can be loaded with theld24instruction, and that all subroutines are reachable with theblinstruction. This is the default ๐
You can set the addressability of one specific object with the model attribute.
-mmodel=mediumโ assumes objects can be anywhere in the 32-bit address space (the compiler usesseth/add3instructions to load their addresses), and that all subroutines are reachable with theblinstruction.-mmodel=largeโ assumes objects can be anywhere in the 32-bit address space (again withseth/add3to load their addresses), but assumes subroutines may NOT be reachable withbl. The compiler falls back to the much slowerseth/add3/jlinstruction sequence ๐ข-msdata=noneโ disables the small data area ๐ซ Variables get shoved into.data,.bss, or.rodata(unless you gave them asectionattribute). This is the default.
The small data area is made up of the .sdata and .sbss sections. You can explicitly put objects in there by using the section attribute with one of these sections.
-msdata=sdataโ puts small global and static data in the small data area, but doesn't generate any special code to reference it.-msdata=useโ puts small global and static data in the small data area AND generates special instructions to reference it ๐ฅ-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 defaultnumis 8. This option only does something if-msdatais set tosdataoruse.
Every module 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 throws an error message. Incorrect code is not generated, though---phew.
-mdebugโ makes the M32R-specific code in the compiler display some statistics that might help you debug your programs ๐-malign-loopsโ aligns all loops to a 32-byte boundary.-mno-align-loopsโ does NOT enforce a 32-byte alignment for loops. This is the default.-missue-rate=numberโ issuesnumberinstructions per cycle.numbercan only be 1 or 2.-mbranch-cost=numberโnumbercan only be 1 or 2. If it's 1, branches are preferred over conditional code. If it's 2, the opposite applies.-mflush-trap=numberโ specifies the trap number used to flush the cache. The default is 12, and valid numbers are between 0 and 15 inclusive.-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 is no OS function for flushing the cache.
โจ M680x0 Options โจ
These are the -m options defined for M680x0 and ColdFire processors ๐ The default settings depend on which architecture was selected when the compiler was configured. The defaults for the most common choices are given below.
-march=archโ generates code for a specific M680x0 or ColdFire instruction set architecture. For M680x0 architectures, the permissible values ofarchare:68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures are selected according to Freescale's ISA classification, and the permissible values are:isaa,isaaplus,isabandisac.
GCC defines a macro __mcfarch__ whenever it's generating code for a ColdFire target. The arch in this macro is one of the -march arguments listed above ๐ธ
When you use -march and -mtune together, you get code that runs on a whole family of similar processors, but is optimized for one particular microarchitecture ๐ง
-mcpu=cpuโ generates code for a specific M680x0 or ColdFire processor. The M680x0 cpus are:68000,68010,68020,68030,68040,68060,68302,68332andcpu32. The ColdFire cpus are given in the table below, which also sorts the CPUs into families ๐
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
-mcpu=cpu overrides -march=arch if arch is compatible with cpu. Other combinations of -mcpu and -march get rejected ๐
โโ๏ธ
GCC defines the macro __mcf_cpu_cpu when a ColdFire target cpu is selected. It also defines __mcf_family_family, where the value of family comes from the table above.
-mtune=tuneโ tunes the code for a particular microarchitecture, within the constraints set by-marchand-mcpu๐ฏ The M680x0 microarchitectures are:68000,68010,68020,68030,68040,68060andcpu32. The ColdFire microarchitectures are:cfv1,cfv2,cfv3,cfv4andcfv4e.
You can also use -mtune=68020-40 for code that needs to run relatively well on 68020, 68030 and 68040 targets. -mtune=68020-60 is similar, but it 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 the 680x0 architecture arch. It also defines mcarch unless either -ansi or a non-GNU -std option is used. If GCC is tuning for a range of architectures, as selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in that range.
GCC also defines the macro __muarch__ when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments listed above.
-m68000,-mc68000โ generates output for a 68000. This is the default when the compiler is configured for 68000-based systems, and it's equivalent to-march=68000.
Use this 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, and 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, and 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, and 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, and it's equivalent to-march=68040๐
This option inhibits the use of 68881/68882 instructions that have to be emulated by software on the 68040. Use 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, and it's equivalent to-march=68060.
This option inhibits the use of 68020 and 68881/68882 instructions that have to be emulated by software on the 68060. Use 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, and it's equivalent to-march=cpu32.
Use this for microcontrollers with a CPU32 or CPU32+ core, including the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360.
-m5200โ generates output for a 520X ColdFire CPU. This is the default when the compiler is configured for 520X-based systems. It's equivalent to-mcpu=5206, and it's now deprecated in favor of that option โ ๏ธ
Use this for microcontrollers with a 5200 core, including the MCF5202, MCF5203, MCF5204 and MCF5206.
-m5206eโ generates output for a 5206e ColdFire CPU. This option is now deprecated in favor of the equivalent-mcpu=5206e.-m528xโ generates output for a member of the ColdFire 528X family. This option is now deprecated in favor of the equivalent-mcpu=528x.-m5307โ generates output for a ColdFire 5307 CPU. This option is now deprecated in favor of the equivalent-mcpu=5307.-m5407โ okay bestie, this one generates output for a ColdFire 5407 CPU ๐ฆ. It's deprecated now, so just use-mcpu=5407instead ๐ซถ-mcfv4eโ this is for the ColdFire V4e family (think 547x/548x) ๐ฅ. It includes hardware floating-point instructions โจ. It's equivalent to-mcpu=547x, and it's deprecated in favor of that option ๐-m68020-40โ generate output for a 68040 without using 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 get emulated on the 68040. This is equivalent to-march=68020 -mtune=68020-40๐-m68020-60โ same energy, but for a 68060 ๐ฆ. The generated code runs pretty efficiently on a 68020/68881, a 68030, or a 68040, and it does use the 68881 instructions that get emulated on the 68060 ๐. This is equivalent to-march=68020 -mtune=68020-60๐ซถ-mhard-float,-m68881โ turns on floating-point instructions ๐ฅ. This is the default for 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 here, you get 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โ generate (or don't generate) ColdFire hardware divide and remainder instructions ๐ . If-marchis used without-mcpu, the default is "on" for ColdFire architectures and "off" for M680x0 architectures ๐. Otherwise the default comes from the target CPU, either the default CPU or whichever one you picked with-mcpu. For example, the default is "off" for-mcpu=5206and "on" for-mcpu=5206eโจ
GCC defines the macro __mcfhwdiv__ when this option is enabled ๐
-mshortโ makesint16 bits wide, just likeshort int๐. Parameters passed on the stack also get aligned to a 16-bit boundary, even on targets that normally promote to 32-bit โจ-mno-shortโintis not 16 bits wide. This is the default ๐-mnobitfield,-mno-bitfieldโ don't use the bit-field instructions ๐ . The-m68000,-mcpu32, and-m5200options all imply-mnobitfield๐-mbitfieldโ do use the bit-field instructions ๐ . The-m68020option implies-mbitfield. This is the default if you use a configuration designed for a 68020 ๐-mrtdโ a different function-calling convention ๐ฆ. Functions that take a fixed number of arguments return with thertdinstruction, which pops their arguments while returning. This saves one instruction in the caller, since there's no need to pop the arguments there ๐ง
This calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler ๐ญ
You must provide function prototypes for all functions that take variable numbers of arguments (including printf), otherwise incorrect code gets generated for calls to those functions ๐
Seriously incorrect code results if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored.)
The rtd instruction is supported by the 68010, 68020, 68030, 68040, 68060, and CPU32 processors, but not by the 68000 or 5200 ๐ธ
The default is -mno-rtd โจ
-malign-int,-mno-align-intโ controls whether GCC alignsint,long,long long,float,double, andlong doublevariables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐. Aligning on 32-bit boundaries gives code that runs 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 ๐ฌ
-mpcrelโ okay, this one tells GCC to use the pc-relative addressing mode of the 68000 directly, instead of a global offset table ๐ฆ. Right now it implies-fpic, which allows at most a 16-bit offset for pc-relative addressing ๐.-fPICisn't presently supported with-mpcrel, though it could be supported for 68020 and higher processors ๐ฅบ-mno-strict-align,-mstrict-alignโ-mno-strict-alignmeans don't assume unaligned memory references are handled by the system, and-mstrict-alignmeans do assume that ๐ซถ-msep-dataโ generates code that lets the data segment live in a different area of memory from the text segment ๐ง. This allows execute-in-place in an environment without virtual memory management โจ. This option implies-fPIC๐-mno-sep-dataโ generates code that assumes the data segment follows the text segment. This is the default ๐ธ-mid-shared-libraryโ generates code that supports shared libraries via the library ID method ๐. This allows execute-in-place and shared libraries in an environment without virtual memory management ๐ฆ. This option implies-fPIC๐-mno-id-shared-libraryโ generates code that doesn't assume ID-based shared libraries are being used. This is the default ๐-mshared-library-id=nโ specifies the identification number of the ID-based shared library being compiled ๐ข. 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โ when generating position-independent code for ColdFire, this generates code that works if the GOT has more than 8192 entries ๐. That code is larger and slower than code generated without this option. On M680x0 processors this option isn't needed, since-fPICis enough ๐
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 makes the linker report an error like this:
relocation truncated to fit: R_68K_GOT16O foobar
If that 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 ๐ญ
Some linkers, including newer versions of the GNU linker, can create multiple GOTs and sort GOT entries ๐ฅ. If you have one of those, you should only need -mxgot when compiling a single object file that accesses more than 8192 GOT entries. Very few do ๐
These options have no effect unless GCC is generating position-independent code ๐
-mlong-jump-table-offsetsโ uses 32-bit offsets inswitchtables ๐ฆ. The default is 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 asint-sized ๐-m4byte-functions,-mno-4byte-functionsโ forces all functions to be aligned to a 4-byte boundary ๐ง-mcallgraph-data,-mno-callgraph-dataโ emits callgraph information ๐-mslow-bytes,-mno-slow-bytesโ prefers word access when reading byte quantities ๐ธ-mlittle-endian,-mbig-endianโ generates code for a little-endian target ๐-m210,-m340โ generate code for the 210 processor ๐-mno-lsimโ assumes runtime support has been provided, so the simulator library (libsim.a) gets omitted 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 theabsinstruction, 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 theaveinstruction, which computes the average of two registers ๐ซถ-mbased=nโ variables of size n bytes or smaller get placed in the.basedsection by default ๐. Based variables use the$tpregister as a base register, and there's a 128-byte limit to the.basedsection ๐-mbitopsโ enables the bit operation instructions: bit test (btstm), set (bsetm), clear (bclrm), invert (bnotm), and test-and-set (tas) ๐ฅ-mc=nameโ selects which section constant data gets placed in. name may betiny,near, orfar๐ฆ-mclipโ enables theclipinstruction ๐. Heads up,-mclipisn't useful unless you also provide-mminmax๐ญ-mconfig=nameโ selects one of the built-in core configurations โจ. Each MeP chip has one or more modules, and each module has a core CPU plus a variety of coprocessors, optional instructions, and peripherals ๐งฉ. The "MeP-Integrator" tool, which is not part of GCC, provides these configurations through this option. Using this option is the same as using all the corresponding command-line options ๐. The default configuration isdefault๐ธ-mcopโ enables the coprocessor instructions ๐ฅ. By default, this is a 32-bit coprocessor ๐ . 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 ๐-mivc2โ enables IVC2 scheduling ๐ง . IVC2 is a 64-bit VLIW coprocessor ๐-mdcโ causes constant variables to be placed in the.nearsection ๐-mdivโ enables thedivanddivuinstructions โจ-mebโ generates big-endian code ๐-melโ okay bestie, this one just says generate little-endian code ๐ธ-mio-volatileโ tells the compiler that any variable with the"io"attribute is volatile no matter what ๐-mlโ makes variables land in the".far"section by default ๐ฆ-mleadzโ turns on the"leadz"(leading zero) instruction โจ-mmโ makes variables land in the".near"section by default ๐ท-mminmaxโ unlocks the"min"and"max"instructions ๐-mmultโ unlocks the multiplication and multiply-accumulate instructions ๐ฅ-mno-optsโ disables all the optional instructions that-mall-optsturned on ๐-mrepeatโ unlocks the"repeat"and"erepeat"instructions, which are for low-overhead looping ๐-msโ makes all variables default to the".tiny"section ๐ง. Heads up, this section has a 65536-byte limit, and accesses go through the%gpbase register ๐-msaturโ enables the saturation instructions. Ngl, the compiler doesn't generate these on its own yet, but the option is here so it plays nice 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 leaves out the built-in support for reset and exception vectors and tables ๐-mtfโ makes all functions default to the".far"section. Without this one, functions default to".near"๐ฆ-mtiny=nโ variables that are n bytes or smaller get put in the".tiny"section, and they use the$gpbase register. The default is 4, but remember the".tiny"section has that 65536-byte limit too โจ
โจ MicroBlaze Options โจ
-msoft-floatโ uses software emulation for floating point. This is the default ๐-mhard-floatโ uses hardware floating-point instructions ๐ฅ-mmemcpyโ doesn't optimize block moves, and usesmemcpyinstead ๐ง-mno-clearbssโ deprecated ๐. Use-fno-zero-initialized-in-bssinstead ๐ซถ-mcpu=cpu-typeโ uses the features of, and schedules code for, the CPU you give it ๐. Supported values look likevX.YY.Z, where X is the major version, YY is the minor version, and Z is compatibility code. Example values arev3.00.a,v4.00.b,v5.00.a,v5.00.b, andv6.00.a๐ธ-mxl-soft-mulโ uses software multiply emulation. This is the default ๐ท-mxl-soft-divโ uses software emulation for divides. This is 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"and".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 model app-model. The valid models are:executableโ the normal executable, and the default. It uses the startup codecrt0.o๐-mpic-data-is-text-relativeโ assumes the displacement between the text and data segments is fixed at static link time. This lets data be referenced by offset from the start of the text address instead of the GOT, since PC-relative addressing isn't supported ๐งxmdstubโ for use with the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent called xmdstub. This uses the startup filecrt1.oand sets the start address of the program to0x800๐bootstrapโ for applications loaded by a bootloader. This model uses the startup filecrt2.o, which doesn't contain a processor reset vector handler. It's suitable for handing control to the bootloader on a processor reset instead of the application ๐ฅพnovectorsโ for applications that don't need any of the MicroBlaze vectors. This can be handy for apps running inside a monitoring application. This model usescrt3.oas its startup file ๐
Option -xl-mode-app-model is a deprecated alias for -mxl-mode-app-model ๐
โจ MIPS Options โจ
-EBโ generates big-endian code ๐-ELโ generates little-endian code. This is the default formips*el-*-*configurations ๐-march=archโ generates code that runs on arch, which can be the name of a generic MIPS ISA or the name of a particular processor ๐. The ISA names aremips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5, andmips64r6. The processor names 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,xlr, andxlp. The special valuefrom-abipicks the most compatible architecture for the selected ABI, which 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 for arch. Among other things, this option controls the way instructions are scheduled and the perceived cost of arithmetic operations. The list of arch values is the same as for-march๐ฅ
When this option 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 family of processors but is optimized 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 uses the MIPS16e ASE ๐ง
MIPS16 code generation can also be controlled on a per-function basis with the "mips16" and "nomips16" attributes ๐
-mflip-mips16โ generates MIPS16 code on alternating functions. This is provided for regression testing of mixed MIPS16/non-MIPS16 code generation, and it's not intended for ordinary use when compiling user code ๐-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. -minterlink-compressed therefore disables direct jumps unless GCC knows that the jump's target 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 select a 64-bit architecture, but you can use -mgp32 to get 32-bit code instead ๐ท
For information about the O64 ABI, see http://gcc.gnu.org/projects/mipso64-abi.html ๐
GCC supports a variant of the o32 ABI in which floating-point registers are 64 rather than 32 bits wide ๐. You can select this combination with -mabi=32 -mfp64. This ABI relies on the "mthc1" and "mfhc1" instructions, so it's only supported for MIPS32R2, MIPS32R3, and MIPS32R5 processors ๐ฅน
The register assignments for arguments and return values stay exactly the same ๐ซถ, but each scalar value now gets packed into a single 64-bit register instead of a pair of 32-bit ones ๐
. Scalar floating-point values come back in $f0 only, NOT a $f0/$f1 pair โจ. The set of call-saved registers is also unchanged, so the even-numbered double-precision registers still get saved ๐ฆ.
Two extra flavours of the o32 ABI exist to help you hop from 32-bit to 64-bit registers ๐: FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg). FPXX is the strict one ๐ค. All code has to run correctly whether it's using 32-bit or 64-bit registers. FPXX code can be interlinked with FP32 or FP64, but not both ๐. FP64A is basically FP64 but it forbids the odd-numbered single-precision registers ๐. It pairs well with the "FRE" mode of FPUs in MIPS32R5 processors and lets FP32 and FP64A code interlink and run in the same process without changing FPU modes ๐ง.
-mabicalls,-mno-abicallsโ Okay so these tell GCC whether to generate code that fits SVR4-style dynamic objects ๐ธ. Yes or no, your call.-mabicallsis the default on SVR4-based systems โจ.-mshared,-mno-sharedโ-msharedmakes fully position-independent code that can be linked into shared libraries ๐.-mno-sharedis the spicy one ๐ถ๏ธ. This option only affects-mabicalls. All-mabicallscode has traditionally been position-independent, no matter what-fPICor-fpicsay ๐. BUT as an extension, the GNU toolchain lets executables use absolute accesses for locally-binding symbols, use shorter GP initialization sequences, and generate direct calls to locally-defined functions.-mno-sharedturns all that on ๐ฅ.
-mno-sharedneeds binutils 2.16 or higher, and the objects it makes can only be linked by the GNU linker ๐. Heads up, though: the option doesn't change the ABI of the final executable. It only changes the ABI of relocatable objects ๐ซถ. Using-mno-sharedusually makes executables both smaller and quicker ๐โโ๏ธ๐จ.
-mshared is the default ๐.
-mplt,-mno-pltโ Assume (or don't assume) that the static and dynamic linkers support PLTs and copy relocations ๐ฆ. This only affects-mno-shared -mabicalls. For the n64 ABI, it does nothing unless you also use-msym32๐.
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt ๐
.
-mxgot,-mno-xgotโ Lift (or don't lift) the usual size limits on the global offset table ๐.
GCC normally uses a single instruction to load values from the GOT. It's pretty efficient, but it only works if the GOT is smaller than about 64k ๐ฌ. Anything bigger and the linker will 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 less efficient, since it takes three instructions to fetch the value of a global symbol ๐ข.
Some linkers can create multiple GOTs. If yours is one of them, 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 do nothing 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 any particular width for floating-point registers ๐ฆ.-mhard-floatโ Use the floating-point coprocessor instructions ๐ช.-msoft-floatโ Don't use the floating-point coprocessor instructions. Instead, floating-point math gets done with library calls ๐.-mno-floatโ Same as-msoft-float, but it also swears the program doesn't do any floating-point operations at all ๐ค. Right now this is only supported by some bare-metal MIPS configurations, which may pick a special set of libraries that have zero floating-point support, including things like the floating-pointprintfformats ๐จ๏ธ.
If code compiled with -mno-float accidentally has floating-point operations in it, it'll most likely crash at link time or at run time ๐ญ. Don't lie to the compiler, bestie.
-msingle-floatโ Assume the floating-point coprocessor only supports single-precision operations ๐.-mdouble-floatโ Assume the floating-point coprocessor supports double-precision operations. This is the default ๐.-modd-spreg,-mno-odd-spregโ Enable (or don't enable) the use of odd-numbered single-precision floating-point registers for the o32 ABI ๐ฆ. This is the default for processors known to support these registers. When you're using the o32 FPXX ABI,-mno-odd-spregis set by default ๐ซถ.-mabs=2008,-mabs=legacyโ These control how the special not-a-number (NaN) IEEE 754 floating-point data gets handled by the"abs.fmt"and"neg.fmt"machine instructions ๐ง.
By default, or when you use -mabs=legacy, you get the legacy treatment ๐ฐ๏ธ. In this case those instructions count as arithmetic, so they get avoided wherever correct operation matters and the input might be a NaN. Instead, a longer sequence of instructions that manipulates the sign bit by hand is used, 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 operate correctly in all cases, including when the input operand is a NaN. That's why they're always used for the respective operations ๐.
-mnan=2008,-mnan=legacyโ These control the encoding of the special not-a-number (NaN) IEEE 754 floating-point data ๐.
-mnan=legacy selects the legacy encoding ๐ฐ๏ธ. Quiet NaNs (qNaNs) have the first bit of their trailing significand field set to 0, and signaling NaNs (sNaNs) have it set to 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 was configured with --with-nan=2008 ๐ซถ.
-mllsc,-mno-llscโ Use (or don't use) thell,sc, andsyncinstructions to implement the atomic memory built-in functions โ๏ธ. If you specify neither, GCC uses those instructions as long as 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 details ๐.
-mdsp,-mno-dspโ Use (or don't use) revision 1 of the MIPS DSP ASE ๐ถ. This option defines the preprocessor macro"__mips_dsp". It also defines"__mips_dsp_rev"to 1 ๐ข.-mdspr2,-mno-dspr2โ Use (or don't use) revision 2 of the MIPS DSP ASE ๐ถ. This option defines the preprocessor macros"__mips_dsp"and"__mips_dspr2". It also defines"__mips_dsp_rev"to 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 can only be used when generating 64-bit code, and it also requires hardware floating-point support to be enabled ๐ป.-mips3d,-mno-mips3dโ Use (or don't use) the MIPS-3D ASE ๐ง. The option-mips3dimplies-mpaired-singleโจ.-mmicromips,-mno-micromipsโ Generate (or don't generate) microMIPS code ๐ฃ.
You can also control microMIPS code generation on a per-function basis with 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โ Force"long"types to be 64 bits wide ๐. See-mlong32for an explanation of the default and how the pointer size gets determined ๐.-mlong32โ Force"long","int", and pointer types to be 32 bits wide ๐.
The default sizes of "int"s, "long"s, and pointers depend on the ABI ๐งพ. All the supported ABIs use 32-bit "int"s. The n64 ABI uses 64-bit "long"s, and so does the 64-bit EABI. The others use 32-bit "long"s ๐ท. Pointers are the same size as "long"s, or the same size as integer registers, whichever is smaller ๐.
-msym32,-mno-sym32โ Assume (or don't assume) that all symbols have 32-bit values, no matter which ABI you picked ๐. This is useful together with-mabi=64and-mno-abicalls, because it lets GCC generate shorter and faster references to symbolic addresses ๐๏ธ๐จ.-G numโ Okay so this one shoves definitions of externally-visible data into a little small data section ๐ง, but only if that data is no bigger thannumbytes. Bonus: GCC can then generate way more efficient accesses to the data, so check-mgpoptfor the deets ๐. The default-Gvalue depends on your configuration, so it's not one-size-fits-all โจ-mlocal-sdata,-mno-local-sdataโ Extends (or doesn't extend) 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 might also wanna build big libraries with
-mno-local-sdataso they leave more room for the main program ๐ธ.
- If the linker starts complaining that an app is using too much small data ๐ญ, try rebuilding the less performance-critical parts with
-mextern-sdata,-mno-extern-sdataโ Assumes (or doesn't assume) that externally-defined data lives in a small data section, as long as its size is within the-Glimit ๐ฆ.-mextern-sdatais the default for all configurations.- Okay this part is important ๐. If you compile a module Mod with
-mextern-sdata -G num -mgpopt, and Mod references a variable Var that's no bigger than num bytes, you must make sure Var gets placed in a small data section. - If Var is defined by another module, you either compile that module with a high-enough
-Gsetting, or attach a"section"attribute to Var's definition. - If Var is common, you need to link the application with a high-enough
-Gsetting. - The easiest way to keep everything happy is to compile and link every module with the same
-Goption ๐. But if you're building a library that supports several different small data limits, compile it with the highest supported-Gsetting and also use-mno-extern-sdata. That stops the library from making assumptions about externally-defined data ๐ซถ.
- Okay this part is important ๐. If you compile a module Mod with
-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๐. Like, if the code is part of a library that might be used in a boot monitor, programs calling 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 the small data section if possible, and otherwise to data. It gives slightly slower code than the default, but it cuts down on the RAM needed while executing, so some embedded systems might prefer it ๐.-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ Puts uninitialized"const"variables in the read-only data section. This one is only meaningful alongside-membedded-dataโจ.-mcode-readable=settingโ Specifies whether GCC may generate code that reads from executable sections. There are three possible settings, and they are giving options ๐:-mcode-readable=yesโ Instructions may freely access executable sections. This is the default setting.-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must not ๐. This is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It's also useful on processors that can be configured to have a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM.-mcode-readable=noโ Instructions must not access executable sections ๐ซ. This can be useful on targets configured with a dual instruction/data SRAM interface that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM.
-msplit-addresses,-mno-split-addressesโ Enables (or disables) use of the%hi()and%lo()assembler relocation operators. This one has been superseded by-mexplicit-relocsbut is kept around for backwards compatibility ๐ฐ๏ธ.-mexplicit-relocs,-mno-explicit-relocsโ Uses (or 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 you can override that at configure time using--with-divide=breaks. Divide-by-zero checks can be completely disabled with-mno-check-zero-division๐ โโ๏ธ.
- The default is usually
-mload-store-pairs,-mno-load-store-pairsโ Enables (or disables) an optimization that pairs consecutive load or store instructions to enable load/store bonding ๐. This is on by default, but it only takes effect when the selected architecture is known to support bonding.-mmemcpy,-mno-memcpyโ Forces (or 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โ Disables (or doesn't disable) use of the"jal"instruction. Calling functions with"jal"is more efficient, but it requires the caller and callee to be in the same 256 megabyte segment ๐บ๏ธ. This option has no effect on abicalls code. The default is-mno-long-calls.-mmad,-mno-madโ Enables (or disables) use of the"mad","madu"and"mul"instructions, as provided by the R4650 ISA ๐ฅ.-mimadd,-mno-imaddโ Enables (or 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 (or disables) use of the floating-point multiply-accumulate instructions, when they're available โจ. The default is-mfused-madd.- Heads up ๐ฌ: on the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product is calculated to infinite precision and is not subject to the FCSR Flush to Zero bit. That might be undesirable in some circumstances. On other processors the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions.
-nocppโ 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-r10000is the default when-march=r10000is used;-mno-fix-r10000is 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 ๐. Always schedule a"nop"instruction there instead. The short loop bug can, under certain conditions, make loops execute only once or twice, thanks to a hardware bug in the R5900 chip. The workaround is implemented by the assembler rather than by GCC.-mfix-rm7000,-mno-fix-rm7000โ 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, those functions are only provided by the mips64vr*-elf configurations. Other VR4120 errata require a NOP to be inserted between certain pairs of instructions. Those are handled by the assembler, not by GCC itself ๐
.
-mfix-vr4130โ Works around the VR4130"mflo"/"mfhi"errata ๐ฉน. The workarounds are implemented by the assembler rather than by GCC, although GCC avoids using"mflo"and"mfhi"if the VR4130"macc","macchi","dmacc"and"dmacchi"instructions are available instead ๐ฆ.-mfix-sb1,-mno-fix-sb1โ Works around certain SB-1 CPU core errata ๐ ๏ธ. (This flag currently works around the SB-1 revision 2"F1"and"F2"floating-point errata.)-mr10k-cache-barrier=settingโ Specifies whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors ๐ง.
Okay so, the R10K is lowkey sneaky ๐ Like many processors, it tries to guess which way a conditional branch will go and starts running instructions from the "taken" branch ahead of time. If the guess was wrong, it aborts those instructions. The tea is that on the R10K, even aborted instructions can leave side effects behind ๐
This mostly matters for kernel stores and, depending on the system, kernel loads. Picture this: a speculatively-executed store pulls the target memory into cache and marks that cache line as dirty, even though the store gets aborted later ๐ญ If a DMA operation writes to the same memory before that "dirty" line gets flushed, the cached data overwrites the DMA-ed data. Absolutely unhinged. The R10K processor manual has the full breakdown, including other potential problems, so go check it if you're curious ๐
One workaround is to insert cache barrier instructions before every memory access that might get speculatively executed and that might have side effects even if it's aborted. -mr10k-cache-barrier=setting controls how GCC handles this workaround ๐ก๏ธ It assumes that aborted accesses to any byte in the following regions have no side effects:
- the memory occupied by the current function's stack frame;
- the memory occupied by an incoming stack argument;
- the memory occupied by an object with a link-time-constant address.
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 allow j foo and jal foo to be executed speculatively. GCC honors this restriction for functions it compiles itself ๐
It expects non-GCC functions, like hand-written assembly code, to do the same thing.
The option comes in three forms:
-mr10k-cache-barrier=load-storeโ inserts a cache barrier before a load or store that might be speculatively executed and that might have side effects even if it gets aborted ๐งฑ-mr10k-cache-barrier=storeโ inserts a cache barrier before a store that might be speculatively executed and that might have side effects even if it gets aborted โจ-mr10k-cache-barrier=noneโ disables cache barrier insertion. This is the default, so no barriers unless you ask for them ๐ธ
-mflush-func=func,-mno-flush-funcโ picks the function to call for flushing the I and D caches, or tells GCC to never call one ๐งน 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 how GCC was configured, but it's commonly either_flush_funcor__cpu_flush๐ฆmbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions ๐ This cost is only a heuristic, so it's not guaranteed to give consistent results across releases, so don't build your whole personality around it ๐ A zero cost just redundantly selects the default, which is based on the-mtunesetting.-mbranch-likely,-mno-branch-likelyโ enables or disables Branch Likely instructions, no matter what the selected architecture defaults to ๐ By default, Branch Likely instructions may be generated if the selected architecture supports them. The exception is the MIPS32 and MIPS64 architectures, and processors that implement them. For those, Branch Likely instructions are not generated by default, because those architectures specifically deprecate their use ๐ฅ-mcompact-branches=never,-mcompact-branches=optimal,-mcompact-branches=alwaysโ these control which form of branch gets generated ๐ The default is-mcompact-branches=optimal.-mcompact-branches=nevermakes sure compact branch instructions are never generated.-mcompact-branches=alwaysmakes sure a compact branch instruction gets generated if one is available. If a compact branch instruction isn't available, a delay slot form of the branch gets used instead.- This option is supported from MIPS Release 6 onwards ๐ง
-mcompact-branches=optimaluses a delay slot branch if one is available in the current ISA and the delay slot is successfully filled. If the delay slot doesn't get filled, a compact branch is chosen if one is available.
-mfp-exceptions,-mno-fp-exceptionsโ specifies whether FP exceptions are enabled ๐ฅ This affects how FP instructions get scheduled 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, then we can use both FP pipes. Otherwise, we can only use one FP pipe ๐
-mvr4130-align,-mno-vr4130-alignโ the VR4130 pipeline is two-way superscalar, but it can only issue two instructions together if the first one is 8-byte aligned ๐ When this option is enabled, GCC aligns pairs of instructions that it thinks should execute in parallel.
This option only has an effect when you're optimizing for the VR4130. It normally makes code faster, but at the expense of making it bigger ๐ It's enabled by default at optimization level -O3.
-msynci,-mno-synciโ enables (or disables) generation ofsynciinstructions on architectures that support them ๐ Thesynciinstructions, if enabled, are generated when__builtin___clear_cachegets compiled.
This option defaults to -mno-synci, but you can override the default by configuring GCC with --with-synci โ๏ธ
When compiling code for single processor systems, it's generally safe to use synci. However, on many multi-core (SMP) systems, it does not invalidate the instruction caches on all cores and may lead to undefined behavior. Be careful, bestie ๐ญ
-mrelax-pic-calls,-mno-relax-pic-callsโ tries to turn PIC calls that are normally dispatched via register$25into direct calls โจ This is only possible if the linker can resolve the destination at link time, and if 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 performed by the assembler and the linker alone, without help from the compiler ๐ฆ
-mmcount-ra-address,-mno-mcount-ra-addressโ emits (or does not emit) code that lets_mcountmodify the calling function's return address ๐ฎ When enabled, this option extends the usual_mcountinterface with a new ra-address parameter. It has typeintptr_t *and gets passed in register$12._mcountcan then modify the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in
*ra-address, if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address ๐
-mframe-header-opt,-mno-frame-header-optโ enables (or disables) frame header optimization in the o32 ABI ๐งบ When you use the o32 ABI, calling functions allocate 16 bytes on the stack for the called function to write out register arguments. When this optimization is enabled, it suppresses the allocation of the frame header if it can be determined that the header is unused.
This optimization is off by default at all optimization levels ๐
-mlxc1-sxc1,-mno-lxc1-sxc1โ when applicable, enables (or disables) generation oflwxc1,swxc1,ldxc1, andsdxc1instructions. Enabled by default ๐-mmadd4,-mno-madd4โ when applicable, enables (or disables) generation of 4-operandmadd.s,madd.d, and related instructions. Enabled by default ๐
โจ MMIX Options โจ
These options are defined for the MMIX ๐
-mlibfuncs,-mno-libfuncsโ specifies that intrinsic library functions are being compiled, passing all values in registers, no matter the size ๐-mepsilon,-mno-epsilonโ generates floating-point comparison instructions that compare with respect to therEepsilon register ๐งฎ-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code that passes function parameters and return values which, in the called function, are seen as registers$0and up. The GNU ABI, by contrast, uses global registers$231and up ๐-mzero-extend,-mno-zero-extendโ when reading data from memory in sizes shorter than 64 bits, uses (or doesn't use) zero-extending load instructions by default, instead of sign-extending ones ๐ซง-mknuthdiv,-mno-knuthdivโ makes the result of a division that yields a remainder have the same sign as the divisor. With the default,-mno-knuthdiv, the sign of the remainder follows the sign of the dividend. Both methods are arithmetically valid, though the latter is almost exclusively used ๐ค-mtoplevel-symbols,-mno-toplevel-symbolsโ prepends (or doesn't prepend) a:to all global symbols, so the assembly code can be used with thePREFIXassembly directive ๐ฏ-melfโ generates an executable in the ELF format, instead of the default mmo format used by the mmix simulator ๐-mbranch-predict,-mno-branch-predictโ uses (or doesn't use) the probable-branch instructions when static branch prediction indicates a probable branch ๐-mbase-addresses,-mno-base-addressesโ generates (or doesn't generate) code that uses base addresses ๐ Using a base address automatically generates a request, handled by the assembler and the linker, for a constant to be set up in a global register. That register is used for one or more base address requests within the range0to255from the value held in the register. This generally leads to short and fast code, but the number of different data items that can be addressed is limited. So a program that uses lots of static data may require-mno-base-addresses๐ฅน-msingle-exit,-mno-single-exitโ forces (or doesn't force) generated code to have a single exit point in each function ๐ช
๐ธ MN10300 Options ๐ธ
These -m options are defined for Matsushita MN10300 architectures ๐ฏ๐ต
-mmult-bugโ generates code to avoid bugs in the multiply instructions for the MN10300 processors. This is the default ๐ ๏ธ-mno-mult-bugโ skip the workaround ๐ Don't generate code to dodge the bugs in the multiply instructions on the MN10300 processors.-mam33โ Generate code using features specific to the AM33 processor โจ-mno-am33โ No AM33-only features, thanks ๐ This is the default.-mam33-2โ Generate code using features specific to the AM33/2.0 processor ๐ฆ-mam34โ Generate code using features specific to the AM34 processor ๐ธ-mtune=cpu-typeโ Schedule instructions using the timing characteristics of the CPU type you name, but it doesn't change the targeted processor type, so it's more of a vibe-matching move than a glow-up ๐ง The CPU type must be one ofmn10300,am33,am33-2oram34.-mreturn-pointer-on-d0โ When a function returns a pointer, the pointer comes back in both"a0"and"d0"๐ Otherwise it only comes back in"a0", and calling those functions without a prototype throws errors ๐ This option is on by default. 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 only does something when you use it on the command line for the final link step.
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 also defines the preprocessor macro"__LIW__".-mno-liwโ No Long Instruction Word instructions from the compiler ๐ 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โ The compiler can't generate SETLB or Lcc instructions ๐ It defines the preprocessor macro"__NO_SETLB__".
๐ฆ Moxie Options ๐ฆ
-mebโ Generate big-endian code. This is the default formoxie-*-*configurations ๐-melโ Generate little-endian code โจ-mmul.xโ Generatemul.xandumul.xinstructions. This is the default formoxiebox-*-*configurations ๐ฅ-mno-crt0โ Don't link in the C run-time initialization object file ๐ซถ
๐ MSP430 Options ๐
These options are defined for the MSP430 ๐ง
-masm-hexโ Force assembly output to always use hex constants. Normally those constants are signed decimals, but this option is there for testsuite and/or aesthetic purposes ๐-mmcu=โ Picks the MCU you want to target ๐ฏ It's turned into a C preprocessor symbol based on the MCU name, converted to upper case and pre- and post-fixed with__. Themsp430.hheader uses that symbol to choose an MCU-specific supplementary header file.
The option also sets the ISA. If the MCU name belongs to one that only supports the 430 ISA, that's the one selected. Otherwise the 430X ISA gets picked. The generic MCU name msp430 also selects the 430 ISA, and the generic msp430x MCU name selects the 430X ISA.
An MCU-specific linker script also gets added to the linker command line. The script's name is the MCU name with .ld appended. So specifying -mmcu=xxx on the gcc command line defines the C preprocessor symbol "__XXX__" and makes the linker search for a script called xxx.ld ๐
The ISA and hardware multiply support for the different MCUs is hard-coded into GCC. However, an external devices.csv file can be used to extend device support beyond those that have been hard-coded ๐ธ
GCC searches for the devices.csv file using the following methods in the given precedence order. The first method beats the second, and the second beats the third:
- Include path specified with
"-I"and"-L"โdevices.csvgets searched for in each of the directories specified by include paths and linker library search paths. - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIRโ Define the value of the global environment variableMSP430_GCC_INCLUDE_DIRas the full path to the directory containingdevices.csv, and GCC will search that directory fordevices.csv. Ifdevices.csvis found, this directory also gets registered as an include path and linker library path. Header files and linker scripts in this directory can therefore be used without manually specifying"-I"and"-L"on the command line ๐ฆ - The
msp430-elf{,bare}/include/devicesdirectory โ Finally, GCC will checkmsp430-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. As above, this directory also gets registered as an include path and linker library path ๐
If none of the above search methods find devices.csv, the hard-coded MCU data is used.
-mwarn-mcu,-mno-warn-mcuโ Enables or disables warnings about conflicts between the MCU name given to-mmcuand the ISA set by-mcpuand/or the hardware multiply support set by-mhwmult. It also toggles warnings about unrecognized MCU names. This is on by default ๐-mcpu=โ Specifies the ISA to use. Accepted values aremsp430,msp430xandmsp430xv2. This option is deprecated, so 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 the-mmcu=option ๐งธ-mlargeโ Use large-model addressing: 20-bit pointers and a 20-bit"size_t"๐-msmallโ Use small-model addressing: 16-bit pointers and a 16-bit"size_t"๐-mrelaxโ This is 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 arenonefor no hardware multiply,16bitfor the original 16-bit-only multiply supported by early MCUs,32bitfor the 16/32-bit multiply supported by later MCUs, andf5seriesfor the 16/32-bit multiply supported by F5-series MCUs. You can also give a value ofauto, which tells GCC to deduce the hardware multiply support from the MCU name provided by the-mmcuoption. If no-mmcuoption is specified, or the MCU name isn't recognized, then no hardware multiply support is assumed."auto"is the default setting ๐
Hardware multiplies are normally performed by calling a library routine, which saves space in the generated code. When compiling at -O3 or higher, however, the hardware multiplier is invoked inline. This makes for bigger, but faster, code ๐๏ธ
The hardware multiply routines disable interrupts while they run and restore the previous interrupt state when they finish. This makes them safe to use inside interrupt handlers as well as in normal code ๐ซถ
-minrtโ Enables a minimum runtime environment with no static initializers or constructors. This is meant for memory-constrained devices ๐ง The compiler includes special symbols in some objects that tell the linker and runtime which code fragments are required.-mtiny-printfโ Enables reduced code size"printf"and"puts"library functions โจ The tiny implementations of these functions are not reentrant, so use them with caution in multi-threaded applications โ ๏ธ
Support for streams has been removed, and the string to be printed will always be sent to stdout via the "write" syscall. The string is not buffered before it's sent to write.
This option requires Newlib Nano IO, so GCC must be configured with --enable-newlib-nano-formatted-io.
-mmax-inline-shift=โ This 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, like all shifts greater than 1 on the 430 ISA.
Shifts of a 32-bit value are at least twice as costly, so the value passed for this option is divided by 2 and the resulting value is used instead.
-mcode-region=,-mdata-region=โ These tell the compiler where to place functions and data that don't have one of the"lower","upper","either"or"section"attributes ๐บ๏ธ The possible values are"lower","upper","either"or"any". The first three behave like the corresponding attribute. The fourth value,"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=โ Passes a request to the assembler to enable warning messages when a silicon errata might need to be applied ๐จ-mwarn-devices-csv,-mno-warn-devices-csvโ Warns ifdevices.csvis not found or there are problems parsing it (default: on) ๐
๐ NDS32 Options ๐
These options are defined for NDS32 implementations ๐
-mbig-endianโ Generate code in big-endian mode ๐ธ-mlittle-endianโ Generate code in little-endian mode ๐ฆ-mreduced-regsโ Use reduced-set registers for register allocation โจ-mfull-regsโ Use full-set registers for register allocation ๐-mcmovโ Generate conditional move instructions ๐ฅ-mno-cmovโ Don't generate conditional move instructions ๐-mext-perfโ Generate performance extension instructions ๐-mno-ext-perfโ Don't generate performance extension instructions ๐-mext-perf2โ Generate performance extension 2 instructions ๐ง-mno-ext-perf2โ Bestie, this one says NO to performance extension 2 instructions. They won't be generated. ๐-mext-stringโ Turns on string extension instructions. โจ-mno-ext-stringโ Keeps string extension instructions OFF. ๐-mv3pushโ Generates v3push25/pop25instructions. ๐-mno-v3pushโ Nopush25/pop25instructions for you, v3 or otherwise. ๐ธ-m16-bitโ Generates 16-bit instructions. Compact and cute. ๐ฆ-mno-16-bitโ Skips the 16-bit instructions entirely. ๐-misr-vector-size=numโ Sets the size of each interrupt vector. It has to be either4or16, no in-between vibes. ๐-mcache-block-size=numโ Sets the size of each cache block. It must 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 must fit in a 512KB addressing space. The text segment must fit in a 16MB addressing space. ๐mediumโ The data segment must fit in 512KB, but the read-only data segment can stretch across a 4GB addressing space. The text segment should still stay within 16MB. ๐ซถlargeโ All the text and data segments can live in a 4GB addressing space. Big main character energy. ๐
-mctor-dtorโ Enables the constructor/destructor feature. โญ-mrelaxโ Guides the linker to relax instructions. ๐
๐ง Nios II Options
Okay so these are the options defined for the Altera Nios II processor. Let's gooo. ๐ฅ
-G numโ Puts global and static objects that arenumbytes or smaller into the small data or BSS sections, instead of the normal data or BSS sections. The default value ofnumis8. ๐-mgpopt=option,-mgpopt,-mno-gpoptโ Generates (or doesn't generate) GP-relative accesses. These option names are recognized:noneโ No GP-relative accesses. Not it. ๐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 that were explicitly placed in a small data section with a"section"attribute. ๐ธglobalโ Same aslocal, but 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. Don't skip this, bestie. โ ๏ธdataโ Generates GP-relative accesses for all data objects in the program. If you use this, the entire data and BSS segments of your program must fit in64Kof memory, and you need an appropriate linker script to allocate them within the addressable range of the global pointer. ๐ฆallโ Generates GP-relative addresses for function pointers as well as data pointers. If you use this, the entire text, data, and BSS segments of your program must fit in64Kof memory, and you need an appropriate linker script to allocate them within the addressable range of the global pointer. ๐ง
-mgpopt is equivalent to -mgpopt=local, and -mno-gpopt is equivalent to -mgpopt=none.
The default is -mgpopt, except when -fpic or -fPIC is specified to generate position-independent code. Heads up: the Nios II ABI does not allow GP-relative accesses from shared libraries. ๐
You might need to specify -mno-gpopt explicitly when building programs that have lots of small data, including large GOT data sections. In that case, the 16-bit offset for GP-relative addressing may not be big enough to reach the entire small data section. ๐ญ
-mgprel-sec=regexpโ This option adds extra 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. ๐
It doesn't change how -G behaves. The sections you list are in addition to the standard .sdata and .sbss small-data sections that -mgpopt already recognizes.
-mr0rel-sec=regexpโ This option names sections that can be reached through a 16-bit offset fromr0, meaning the low 32K or high 32K of the 32-bit address space. It's most useful alongside"section"attributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression. โจ
Unlike GP-relative addressing for small data, zero-based addressing is never generated by default. Also, there are no conventional section names used in standard linker scripts for the low or high areas of memory. ๐
-mel,-mebโ Generates little-endian (the default) or big-endian (experimental) code, respectively. ๐ซถ-march=archโ Names the target Nios II architecture. GCC uses this name to figure out what kinds of instructions it can emit when generating assembly code. Permissible names arer1andr2. ๐
The preprocessor macro __nios2_arch__ is available to your programs. Its value is 1 or 2, which tells you the targeted ISA level. ๐ฅ
-mbypass-cache,-mno-bypass-cacheโ Forces all load and store instructions to always bypass the cache by using the I/O variants of the instructions. The default is not to bypass the cache. ๐ฆ-mno-cache-volatile,-mcache-volatileโ Volatile memory accesses bypass the cache by 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โ Don't use the 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 to not emitdivandmulx. ๐-mbmx,-mno-bmx,-mcdx,-mno-cdxโ Enables or disables generation of Nios II R2 BMX (bit manipulation) and CDX (code density) instructions. Turning these on also requires-march=r2. Since these instructions are optional extensions to the R2 architecture, the default is not to emit them. ๐-mcustom-insn=N,-mno-custom-insnโ Each-mcustom-insn=Noption enables use of a custom instruction with encodingNwhen generating code that usesinsn. For example,-mcustom-fadds=253generates custom instruction253for single-precision floating-point add operations, instead of the default behavior of using a library call. โจ
These are the supported values of insn. Unless noted otherwise, floating-point operations are expected to use normal IEEE 754 semantics and correspond directly to the C operators or the equivalent GCC built-in functions. ๐ค
๐ธ Single-precision floating point
fadds,fsubs,fdivs,fmulsโ Binary arithmetic operations.fnegsโ Unary negation.fabssโ Unary absolute value.fcmpeqs,fcmpges,fcmpgts,fcmples,fcmplts,fcmpnesโ Comparison operations.fmins,fmaxsโ Floating-point minimum and maximum. These instructions are only generated if-ffinite-math-onlyis specified. ๐ฆfsqrtsโ Unary square root operation.fcoss,fsins,ftans,fatans,fexps,flogsโ Floating-point trigonometric and exponential functions. These instructions are only generated if-funsafe-math-optimizationsis also specified. ๐ง
๐ Double-precision floating point
faddd,fsubd,fdivd,fmuldโ Binary arithmetic operations.fnegdโ Unary negation.fabsdโ Unary absolute value.fcmpeqd,fcmpged,fcmpgtd,fcmpled,fcmpltd,fcmpnedโ Comparison operations.fmind,fmaxdโ Double-precision minimum and maximum. These instructions are only generated if-ffinite-math-onlyis specified. ๐fsqrtdโ Unary square root operation.fcosd,fsind,ftand,fatand,fexpd,flogdโ Double-precision trigonometric and exponential functions. These instructions are only generated if-funsafe-math-optimizationsis also specified. ๐
๐ฅ Conversions
fextsdโ Converts single precision to double precision.ftruncdsโ Converts 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_lroundf"function when-fno-math-errnois used. ๐floatis,floatus,floatid,floatudโ Converts signed or unsigned integer types to floating-point types. ๐ซถ
In addition, all of the following transfer instructions for the internal registers X and Y must be provided to use any of the double-precision floating-point instructions. ๐ง
Custom instructions that take two double-precision source operands expect the first operand in the 64-bit register X. The other operand (or the only operand of a unary operation) is given to the custom arithmetic instruction with the least significant half in source register src1 and the most significant half in src2. A custom instruction that returns a double-precision result returns the most significant 32 bits in the destination register, and the other half in 32-bit register Y. GCC automatically generates the necessary code sequences to write register X and/or read register Y when double-precision floating-point instructions are used. You don't have to do any of that yourself. โจ
fwrxโ Writessrc1into the least significant half ofX, andsrc2into the most significant half ofX.fwryโ Writessrc1intoY.frdxhi,frdxloโ Reads the most or least significant half (respectively) ofXand stores it indest.frdyโ Reads the value ofYand stores it intodest.
Note that you can get more local control over the generation of Nios II custom instructions by using the target("custom-insn=N") and target("no-custom-insn") function attributes or pragmas. ๐
-mcustom-fpu-cfg=name Okay so this option is bestie's go-to for picking a whole pre-made bundle of custom instruction encodings, named and everything ๐
(it builds on the -mcustom-insn stuff from above โจ). Right now these sets exist:
-mcustom-fpu-cfg=60-1 is the same as: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -fsingle-precision-constant
-mcustom-fpu-cfg=60-2 is the same as: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant
-mcustom-fpu-cfg=72-3 is the same as: -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 the same as: -mcustom-fabss=224 -mcustom-fnegs=225 -mcustom-fcmpnes=226 -mcustom-fcmpeqs=227 -mcustom-fcmpges=228 -mcustom-fcmpgts=229 -mcustom-fcmples=230 -mcustom-fcmplts=231 -mcustom-fmaxs=232 -mcustom-fmins=233 -mcustom-round=248 -mcustom-fixsi=249 -mcustom-floatis=250 -mcustom-fsqrts=251 -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255
Heads up, bestie: any custom instruction you set with an individual-mcustom-insn=option wins over what-mcustom-fpu-cfg=gives you, no matter what order you typed them in on the command line ๐ซถ
Want even more local control? You can pick an FPU configuration just for one spot in your code with the target("custom-fpu-cfg=name") function attribute or pragma ๐ฆ
The name fph2 is short for Nios II Floating Point Hardware 2 Component ๐ธ
Quick warnings, because I love you ๐ญ:
- The custom instructions for
-mcustom-fmins=233and-mcustom-fmaxs=234only get generated if you also use-ffinite-math-only๐ - The custom instruction for
-mcustom-round=248only gets generated if you use-fno-math-errno๐ - Unlike all the other configs,
-fsingle-precision-constantis NOT set forfph2๐
โจ These extra -m options are for the Altera Nios II ELF (bare-metal) target โจ
These are the extra -m options that work with the Altera Nios II ELF (bare-metal) target ๐ง
-mhalโ Links with the HAL BSP ๐ This skips the GCC-provided C runtime startup and termination code, and it's usually paired with-msys-crt0=so you can point to the alternate startup code the HAL BSP brings along.-msmallcโ Links with a limited version of the C library,-lsmallc, instead of Newlib ๐-msys-crt0=startfileโstartfileis the name of the startfile (crt0) you want when linking ๐ This only does anything when you're also using-mhal.-msys-lib=systemlibโsystemlibis the name of the library that gives you the low-level system calls the C library needs, like"read"and"write"๐ฆ You'll usually use this to link against a library from a HAL BSP.
๐ Nvidia PTX Options ๐
These options are defined for Nvidia PTX ๐ฅ
-m64โ Ignored, but kept around for backward compatibility ๐ซถ Only the 64-bit ABI is supported.-misa=ISA-stringโ Generates code for the PTX ISA you pick (likesm_35) โจ ISA strings have to be lower-case. Valid ones includesm_30andsm_35, and the default issm_35.-mmainkernelโ Links in code for a__mainkernel ๐ This is for stand-alone execution instead of offloading.-moptimizeโ Applies partitioned execution optimizations ๐ This is the default whenever any level of optimization is turned on.-msoft-stackโ Generates code that doesn't use.localmemory directly for stack storage ๐ธ Instead, a per-warp stack pointer is maintained explicitly. This lets you do variable-length stack allocation (with variable-length arrays or"alloca"), and when global memory is the underlying storage, you can access automatic variables from other threads or with atomic instructions ๐ญ This code generation variant is used for OpenMP offloading, but the option is exposed on its own so the compiler can be tested. If you want code that links into programs using OpenMP offloading, use-mgompinstead.-muniform-simtโ Switches to a code generation variant that lets all threads in each warp execute while memory state and side effects still behave as if only one thread per warp was active outside OpenMP SIMD regions ๐ง All atomic operations and calls to the runtime (malloc,free,vprintf) only run conditionally (if the current lane index equals the master lane index), and the register being assigned is copied from the master lane with a shuffle instruction. Outside SIMD regions, lane 0 is the master; inside them, each thread sees itself as the master ๐ A shared memory arrayint __nvptx_uni[]stores all-zeros or all-ones bitmasks for each warp to show the current mode (0 outside SIMD regions). Each thread can bitwise-and the bitmask at position"tid.y"with the current lane index to compute the master lane index ๐ค-mgompโ Generates code for OpenMP offloading ๐ It turns on-msoft-stackand-muniform-simtand picks the matching multilib variant.
๐ OpenRISC Options ๐
These options are defined for OpenRISC ๐ฆ
-mboard=nameโ Configures a board-specific runtime ๐ธ This gets passed to the linker for newlib board library linking. The default is"or1ksim".-mnewlibโ Ignored, it's only here for compatibility ๐ It used to pick linker and preprocessor options for newlib.-msoft-div,-mhard-divโ Picks software or hardware divide ("l.div","l.divu") instructions โจ The default is hardware divide.-msoft-mul,-mhard-mulโ Picks software or hardware multiply ("l.mul","l.muli") instructions ๐ The default is hardware multiply.-msoft-float,-mhard-floatโ Picks software or hardware for floating point operations ๐ซถ The default is software.-mdouble-floatโ When-mhard-floatis selected, this turns on generation of double-precision floating point instructions ๐ฅ By default, functions from libgcc handle double-precision floating point operations.-munordered-floatโ When-mhard-floatis selected, this turns on generation of unordered floating point compare and set flag ("lf.sfun*") instructions ๐ง By default, functions from libgcc handle unordered floating point compare and set flag operations.-mcmovโ Turns on generation of conditional move ("l.cmov") instructions ๐ By default, the equivalent is generated using set and branch.-mrorโ Turns on generation of rotate right ("l.ror") instructions ๐ By default, functions from libgcc handle rotate right operations.-mroriโ Turns on generation of rotate right with immediate ("l.rori") instructions โญ By default, functions from libgcc handle rotate right with immediate operations.-msextโ Turns on generation of sign extension ("l.ext*") instructions ๐ By default, memory loads handle sign extension.-msfimmโ Turns on generation of compare and set flag with immediate ("l.sf*i") instructions โจ By default, extra instructions are generated to store the immediate in a register first.-mshftimmโ Turns on generation of shift with immediate ("l.srai","l.srli","l.slli") instructions ๐ By default, extra instructions are generated to store the immediate in a register first.
๐ฆ 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 isn't supported, bestie ๐ญ) Implies-m45.-msoft-floatโ Doesn't use hardware floating point ๐ซถ-mac0โ Returns floating-point results inac0(fr0in Unix assembler syntax) ๐ธ-mno-ac0โ Returns floating-point results in memory ๐ This is the default.-m40โ Generates code for a PDP-11/40 โจ Implies-msoft-float -mno-split.-m45โ Generates code for a PDP-11/45 ๐ This is the default.-m10โ Generates code for a PDP-11/10 ๐ Implies-msoft-float -mno-split.-mint16,-mno-int32โ Uses 16-bit"int"๐ This is the default.-mint32,-mno-int16โ Uses 32-bit"int"๐ฅ-msplitโ The target has split instruction and data space ๐ Implies-m45.-munix-asmโ Uses Unix assembler syntax ๐ง-mdec-asmโ Uses DEC assembler syntax ๐-mgnu-asmโ Uses GNU assembler syntax ๐ธ This is the default.-mlraโ Uses the new LRA register allocator ๐ฆ By default, the old"reload"allocator is used.
๐ picoChip Options ๐
These -m options are defined for picoChip implementations ๐
-mae=ae_typeโ Sets the instruction set, register set, and instruction scheduling parameters for array element typeae_typeโจ Supported values forae_typeareANY,MUL, andMAC.-mae=ANYpicks a completely generic AE type ๐ซถ Code generated with this option runs on any of the other AE types. It's not as efficient as code compiled for a specific AE type, and some operations (e.g., multiplication) don't work properly on all AE types ๐ญ-mae=MULpicks a MUL AE type ๐ฅ This is the most useful AE type for compiled code, and it's the default.-mae=MACpicks a DSP-style MAC AE ๐ Code compiled with this option may have poor performance for byte (char) manipulation, since the DSP AE doesn't have 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, without 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 on ๐-mno-inefficient-warningsโ Disables warnings about generating inefficient code ๐ง These warnings can show up when you compile code that does byte-level memory operations on the MAC AE type. The MAC AE has no hardware support for byte-level memory operations, so every byte load/store has to be synthesized from word load/store operations. That's inefficient, so GCC warns you to rewrite the code to avoid byte operations or to target an AE type with the right hardware support. This option turns those warnings off ๐
PowerPC Options
These are listed under
โจ PRU Options โจ
okay so these command-line options are specifically for the PRU target, so only use them if you're building for PRU ๐
-minrtโ Links you with a minimum runtime ๐ง There's no support for static initializers and constructors, and using it can seriously shrink your final ELF binary. Heads up though, the compiler could still generate code with static initializers and constructors, so it's on you to make sure your source doesn't use those features ๐ซถ-mmcu=mcuโ Picks the PRU MCU variant you want. For the full list of supported MCUs, check Newlib ๐-mno-relaxโ Tells GCC to pass--no-relaxto the linker instead of--relax๐ฆ-mloopโ Lets GCC use the LOOP instruction, or doesn't let it, depending on how you set it ๐ธ-mabi=variantโ Picks the ABI variant your code gets output for.-mabi=tigives you the unmodified TI ABI, and-mabi=gnugives you a GNU variant that plays nicer with certain GCC assumptions. Here's the tea on what's different โ
Function Pointer Size
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 bigger than 64 bits get passed through a hidden pointer as the first argument of the function. TI ABI, though, 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. As a result, the standard C library can't be built, so it gets omitted when you link with-mabi=ti. Not ideal, bestie ๐
Relaxation is a GNU feature, so for safety reasons it's disabled when you use -mabi=ti. The TI toolchain doesn't emit relocations for QBBx instructions, which means the GNU linker can't adjust them when it shortens adjacent LDI32 pseudo instructions ๐
โจ 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 you're generating PIC code, this decides whether PLTs are allowed or not. It's ignored for non-PIC. The default is-mplt๐-mabi=ABI-stringโ Picks the integer and floating-point calling convention โจ An ABI string has two parts: the size of integer types, and the registers used for floating-point types. For example,-march=rv64ifd -mabi=lp64dmeanslongand pointers are 64-bit (which implicitly makesint32-bit), and floating-point values up to 64 bits wide get passed in F registers ๐ Compare that with-march=rv64ifd -mabi=lp64f, which still lets the compiler generate code using the F and D extensions, but only lets floating-point values up to 32 bits long get passed in registers. Or there's-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers at all ๐ซถ
The default for this one is system dependent, so if you want a specific calling convention, pick one explicitly ๐ The valid calling conventions are: ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d. Some combos are impossible on some ISAs. For example, -march=rv32if -mabi=ilp32d is invalid, because the ABI needs 64-bit values passed in F registers, but F registers are only 32 bits wide ๐ There's also the ilp32e ABI, which can only be used with the rv32e architecture. It's not well specified right now and is subject to change, so tread carefully ๐ง
-mfdiv,-mno-fdivโ Do or don't use hardware floating-point divide and square root instructions. This needs the F or D extensions for floating-point registers. The default is to use them if the architecture you specified has these instructions ๐ฆ-mdiv,-mno-divโ Do or don't use hardware instructions for integer division. This needs the M extension. The default is to use them if the architecture you specified has these instructions ๐ธ-march=ISA-stringโ Generates code for the given RISC-V ISA, likerv64im. ISA strings must be lower-case! Examples includerv64i,rv32g,rv32e, andrv32imaf๐
When -march= isn't specified, GCC uses the setting from -mcpu. If both -march and -mcpu= are left out, the default is system dependent, so if you want specific architecture extensions, pick them explicitly ๐ฅ
-mcpu=processor-stringโ Uses the architecture of, and optimizes the output for, the given processor, specified by a particular CPU name. The permissible values are:sifive-e20,sifive-e21,sifive-e24,sifive-e31,sifive-e34,sifive-e76,sifive-s21,sifive-s51,sifive-s54,sifive-s76,sifive-u54, andsifive-u74โจ-mtune=processor-stringโ Optimizes the output for the given processor, specified by microarchitecture or a 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, GCC uses the setting from -mcpu. If both are missing, the default is rocket ๐ The size choice isn't meant for end-users. It's used when -Os is specified, and it overrides the instruction cost info provided by -mtune=, but it does not override the pipeline info. This helps reduce code size while still giving good performance ๐ซถ
-mpreferred-stack-boundary=numโ Tries to keep the stack boundary aligned to a 2 raised tonumbyte boundary. If you don't specify-mpreferred-stack-boundary, the default is4(16 bytes, or 128 bits) ๐
โ ๏ธ 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. No skipping, bestie ๐ญ
-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, by replacing a load/store of'base register + large offset'with a new load/store of'new base + small offset'. If the new base gets stored in a compressed register, then the new load/store can be compressed. Currently this only targets 32-bit integer load/stores ๐ฆ-mstrict-align,-mno-strict-alignโ Do not generate unaligned memory accesses, or do. 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 GiBand+2 GiB. Programs can be statically or dynamically linked. This is the default code model ๐-mcmodel=medanyโ Generates code for the medium-any code model. The program and its statically defined symbols must be within any single 2 GiB address range. Programs can be statically or dynamically linked ๐-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โ Takes advantage of linker relaxations to reduce the number of instructions needed to materialize symbol addresses. The default is to take advantage of linker relaxations โจ-memit-attribute,-mno-emit-attributeโ Emits (or doesn't emit) a RISC-V attribute to record extra information into ELF objects. This feature requires at least binutils 2.32 ๐-malign-data=typeโ Controls how GCC aligns variables and constants of array, structure, or union types. The supported values fortypearexlen, which uses the x register width as the alignment value, andnatural, which uses natural alignment.xlenis the default ๐-mbig-endianโ Generates big-endian code. This is the default when GCC is configured for ariscv64be-*-*orriscv32be-*-*target ๐ฆ-mlittle-endianโ Generates little-endian code. This is the default when GCC is configured for ariscv64-*-*orriscv32-*-*target, but not ariscv64be-*-*orriscv32be-*-*target ๐-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block ๐ก๏ธ
With the tls choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also tell GCC which register to use as the base register for reading the canary, and what offset from that base register to use. There's no default register or offset, because this is entirely for use within the Linux kernel ๐ง
โจ RL78 Options โจ
last but not least, the RL78 options ๐ธ
-msimโ Links in additional target libraries so things can run inside a simulator ๐ง-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ Specifies the type of hardware multiplication and division support to use. The simplest is"none", which uses software for both multiplication and division. This is the default ๐ The"g13"value is for the hardware multiply/divide peripheral found on the RL78/G13 (S2 core) targets. The"g14"value selects the multiplication and division instructions supported by the RL78/G14 (S3 core) parts. The value"rl78"is an alias for"g14", and the value"mg10"is an alias for"none"๐
There's also a C preprocessor macro defined based on this setting. The possible values are: "__RL78_MUL_NONE__", "__RL78_MUL_G13__", or "__RL78_MUL_G14__" โจ
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ Specifies the RL78 core to target. The default is the G14 core, also known as an S3 core or just RL78 ๐ The G13 or S2 core doesn't have multiply or divide instructions. Instead, it uses a hardware peripheral for those operations. The G10 or S1 core doesn't have register banks, so it uses a different calling convention ๐ฆ
okay so the hardware multiply part is a whole thing ๐งฎ โ -mcpu also picks which hardware multiply support you get, unless you override it with -mmul=none on the command line ๐
โโ๏ธ. So -mcpu=g13 switches on the G13 hardware multiply peripheral โจ, and -mcpu=g10 turns hardware multiplication off completely ๐.
ngl, the RL78/G14 core is the default target, BUT -mcpu=g14 or -mcpu=rl78 on the command line does change how the toolchain behaves, because it also turns on G14 hardware multiply support ๐ฅ. If you leave those out of the command line, the compiler uses software multiplication routines even though the code targets the RL78 core ๐. That's only there for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ซถ.
Also, a C preprocessor macro gets defined based on this setting ๐ง. The possible values are __RL78_G10__, __RL78_G13__, or __RL78_G14__ ๐.
-mg10,-mg13,-mg14,-mrl78โ these are just aliases for the matching-mcpu=option ๐ฆ. They're only around so older setups keep working.-mallregsโ lets the compiler use every available register ๐. By defaultr24..r31are reserved for interrupt handlers, but with this on they can be used in ordinary functions too.-m64bit-doubles,-m32bit-doublesโ makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) ๐. The default is-m32bit-doubles.-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ tells interrupt handler functions to preserve the MDUC registers ๐ก๏ธ. This only matters if normal code might touch the MDUC registers, like when it does multiplication and division. The default ignores the MDUC registers because that makes the interrupt handlers faster โก. The target option-mg13needs to be passed for this to work, since this feature is only available on the G13 target (S2 core). The MDUC registers only get saved if the interrupt handler does a multiplication or division or calls another function.
๐ธ IBM RS/6000 and PowerPC Options ๐ธ
These -m options are defined for the IBM RS/6000 and PowerPC ๐. You use them to pick which instructions are available on the processor you're using. The default value of these is decided when you configure GCC. Specifying -mcpu=cpu_type overrides these, and honestly we recommend using -mcpu=cpu_type instead of the options below ๐
.
-mpowerpc-gpopt,-mno-powerpc-gpoptโ-mpowerpc-gpoptlets GCC use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root โจ.-mpowerpc-gfxopt,-mno-powerpc-gfxoptโ-mpowerpc-gfxoptlets GCC use the optional PowerPC architecture instructions in the Graphics group, including floating-point select ๐จ.-mpowerpc64,-mno-powerpc64โ-mpowerpc64lets GCC generate the extra 64-bit instructions found in the full PowerPC64 architecture, and treat GPRs as 64-bit doubleword quantities ๐. GCC defaults to-mno-powerpc64.-mmfcrf,-mno-mfcrfโ lets GCC generate the move from condition register field instruction ๐งญ. That one's on the POWER4 and other processors that support the PowerPC V2.01 architecture.-mpopcntb,-mno-popcntbโ lets GCC generate the popcount and double-precision FP reciprocal estimate instruction ๐ข. That's on the POWER5 and other processors that support the PowerPC V2.02 architecture.-mpopcntd,-mno-popcntdโ lets GCC generate the popcount instruction ๐ข. That's on the POWER7 and other processors that support the PowerPC V2.06 architecture.-mfprnd,-mno-fprndโ lets GCC generate the FP round to integer instructions ๐ฏ. Those are on the POWER5+ and other processors that support the PowerPC V2.03 architecture.-mcmpb,-mno-cmpbโ lets GCC generate the compare bytes instruction ๐งฉ. That's on the POWER6 and other processors that support the PowerPC V2.05 architecture.-mhard-dfp,-mno-hard-dfpโ lets GCC generate the decimal floating-point instructions that show up on some POWER processors ๐.
-mcpu=cpu_type
This one is a big deal ๐. It sets the architecture type, register usage, and instruction scheduling parameters for the machine type cpu_type. The supported values for cpu_type are 401, 403, 405, 405fp, 440, 440fp, 464, 464fp, 476, 476fp, 505, 601, 602, 603, 603e, 604, 604e, 620, 630, 740, 7400, 7450, 750, 801, 821, 823, 860, 970, 8540, a2, e300c2, e300c3, e500mc, e500mc64, e5500, e6500, ec603e, G3, G4, G5, titan, power3, power4, power5, power5+, power6, power6x, power7, power8, power9, power10, powerpc, powerpc64, powerpc64le, rs64, and native.
-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 ๐ง. They come with an appropriate, generic processor model 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 ๐ฅ๏ธ. -mcpu=native has no effect if GCC doesn't recognize the processor.
The other options specify a specific processor. Code generated under those runs best on that processor, and may not run at all on others ๐ญ.
The -mcpu options automatically enable or disable the following options:
-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple -mpopcntb
-mpopcntd -mpowerpc64 -mpowerpc-gpopt -mpowerpc-gfxopt -mmulhw
-mdlmzb -mmfpgpr -mvsx -mcrypto -mhtm -mpower8-fusion
-mpower8-vector -mquad-memory -mquad-memory-atomic -mfloat128
-mfloat128-hardware -mprefixed -mpcrel -mmma -mrop-protect
The exact options set for any CPU change between compiler versions, depending on what setting seems to make the best code for that CPU ๐. It doesn't necessarily reflect the real hardware's capabilities. If you want to set an individual option to a particular value, you can put it after the -mcpu option, like -mcpu=970 -mno-altivec ๐.
On AIX, the -maltivec and -mpowerpc64 options are not enabled or disabled by the -mcpu option right now, 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 does not set the architecture type or register usage the way -mcpu=cpu_type does ๐ฏ. The same values for cpu_type work for -mtune as for -mcpu. If you specify both, the code uses the architecture and registers set by -mcpu, but the scheduling parameters set by -mtune ๐ซถ.
-mcmodel=smallโ generates PowerPC64 code for the small model, where the TOC is limited to 64k ๐ฃ.-mcmodel=mediumโ generates PowerPC64 code for the medium model, where the TOC and other static data 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
These generate code that uses (or doesn't use) AltiVec instructions, and also enable built-in functions that give you more direct access to the AltiVec instruction set ๐
. You may also need to set -mabi=altivec to adjust the current ABI with AltiVec ABI enhancements.
When -maltivec is used, the element order for AltiVec intrinsics such as vec_splat, vec_extract, and vec_insert matches the array element order for the endianness of the target ๐. So element zero is the leftmost element in a vector register when you're targeting a big-endian platform, and the rightmost element in a vector register when you're targeting a little-endian platform.
-mvrsave,-mno-vrsaveโ generates VRSAVE instructions when generating AltiVec code ๐ท.-msecure-pltโ generates code that allowsldandld.soto build executables and shared libraries with non-executable.pltand.gotsections ๐. This is a PowerPC 32-bit SYSV ABI option.-mbss-pltโ generates code that uses a BSS.pltsection thatld.sofills in ๐งฑ. It requires.pltand.gotsections that are both writable and executable. This is a PowerPC 32-bit SYSV ABI option.-misel,-mno-iselโ this switch enables or disables the generation of ISEL instructions ๐.-mvsx,-mno-vsxโ generates code that uses (or doesn't use) vector/scalar (VSX) instructions ๐, and also enables built-in functions for more direct access to the VSX instruction set.-mcrypto,-mno-cryptoโ enables (or disables) the built-in functions that give direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐.-mhtm,-mno-htmโ enables (or disables) the built-in functions for direct access to the Hardware Transactional Memory (HTM) instructions added in version 2.07 of the PowerPC ISA ๐ง .-mpower8-fusion,-mno-power8-fusionโ the-mpower8-fusionversion generates code that keeps some integer operations next to each other so they can be fused together on power8 and later processors ๐งต. The-mno-power8-fusionversion doesn't keep them adjacent.-mpower8-vector,-mno-power8-vectorโ generates code that uses (or doesn't use) the vector and scalar instructions added in version 2.07 of the PowerPC ISA ๐. It also enables built-in functions for more direct access to the vector instructions.-mquad-memory,-mno-quad-memoryโ generates code that uses (or doesn't use) the non-atomic quad word memory instructions ๐. The-mquad-memoryoption requires use of 64-bit mode.
-mquad-memory-atomic -mno-quad-memory-atomic
Okay so these two are a whole vibe ๐
-mquad-memory-atomic turns ON the atomic quad word memory instructions, and -mno-quad-memory-atomic turns them OFF. Heads up bestie: the -mquad-memory-atomic one needs 64-bit mode to work ๐ญ๐ซถ
-mfloat128 -mno-float128
Ngl this is giving main character energy ๐ These toggle the __float128 keyword for IEEE 128-bit floating point ๐ฆ You can get the math done either with software emulation or with actual hardware instructions, your choice!
The VSX instruction set (-mvsx) has to be enabled before you can use IEEE 128-bit floating point support ๐ And the IEEE 128-bit floating point stuff is only supported on Linux, so no cap, keep that in mind ๐ธ
By default -mfloat128 is enabled on PowerPC Linux systems using the VSX instruction set, and disabled on other systems โจ
If you use the ISA 3.0 instruction set (-mpower9-vector or -mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support will also turn on the generation of ISA 3.0 IEEE 128-bit floating point instructions ๐ฅ But if you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets handled by software emulation instead ๐ง
-mfloat128-hardware -mno-float128-hardware
Okay this pair is iconic ๐ -mfloat128-hardware lets you use ISA 3.0 hardware instructions to support the __float128 data type, and -mno-float128-hardware turns that off ๐
By default -mfloat128-hardware is enabled on PowerPC Linux systems using the ISA 3.0 instruction set, and disabled on other systems ๐
-m32 -m64
Slay ๐
These pick the environment you generate code for: -m32 or -m64, on Darwin and SVR4 targets (including GNU/Linux) ๐ธ The 32-bit one sets int, long and pointer to 32 bits and makes code that runs on any PowerPC variant โจ The 64-bit one sets int to 32 bits, but long and pointer go to 64 bits, and it generates code for PowerPC64, same as -mpowerpc64 ๐ฆ
-mfull-toc -mno-fp-in-toc -mno-sum-in-toc -mminimal-toc
Okay the TOC (Table Of Contents) is a whole thing ๐ง Every executable file gets one, and this group changes how it's made. -mfull-toc is the default: GCC gives at least one TOC entry to each unique non-automatic variable reference in your program, and it also puts floating-point constants in the TOC ๐ Just know only 16,384 entries are available in the TOC, so be mindful ๐
If you get a linker error saying you've overflowed the available TOC space, you can shrink TOC usage with -mno-fp-in-toc and -mno-sum-in-toc ๐ซถ -mno-fp-in-toc stops GCC from putting floating-point constants in the TOC, and -mno-sum-in-toc makes GCC calculate the sum of an address and a constant at run time, instead of stuffing that sum into the TOC โจ You can use one or both. Each one makes the code very slightly slower and larger, but it saves TOC space, so it's a trade-off bestie ๐
Still out of room even with both? Then go with -mminimal-toc ๐ญ It makes only one TOC entry for every file. The code ends up slower and larger, but it uses extremely little TOC space. You might want to use this only on files with less frequently-executed code ๐ธ
-maix64 -maix32
Lowkey a big deal ๐ -maix64 turns on the 64-bit AIX ABI and calling convention, with 64-bit pointers, a 64-bit "long" type, and the infrastructure needed to support them ๐ฅ It also implies -mpowerpc64. -maix32 disables the 64-bit ABI and implies -mno-powerpc64 ๐ง GCC defaults to -maix32 ๐ฆ
-mxl-compat -mno-xl-compat
It's giving IBM XL compiler vibes ๐ -mxl-compat makes code that matches IBM XL compiler semantics more closely when you're using the AIX-compatible ABI ๐ It does a few things: floating-point arguments go to prototyped functions beyond the register save area (RSA) on the stack, as well as in argument FPRs โจ It also doesn't assume the most significant double in a 128-bit long double value is properly rounded when comparing values and converting to double ๐ And it uses XL symbol names for long double support routines ๐
-mno-xl-compat turns all that off ๐
Okay this part is lowkey obscure ๐ค The AIX calling convention was extended, but not documented at first, to handle an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than declared. IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine is compiled without optimization ๐ซถ Storing floating-point arguments on the stack all the time is inefficient and rarely needed, so this option isn't on by default. You only need it when calling subroutines compiled by IBM XL compilers without optimization ๐ญ
-mpe
Ngl this one is very specific ๐ธ -mpe supports the IBM RS/6000 SP Parallel Environment (PE) ๐ฐ๏ธ It links an application that uses message passing with special startup code, so the app can actually run ๐ฅ The system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you have to override the specs file with -specs= to point at the right directory location ๐ง Big heads up: the Parallel Environment doesn't support threads, so -mpe and -pthread are incompatible ๐ซ๐
-malign-natural -malign-power
Okay alignment is a whole mood ๐ On AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux, -malign-natural overrides the ABI-defined alignment of larger types, like floating-point doubles, so they sit on their natural size-based boundary ๐ฆ -malign-power tells GCC to follow the ABI-specified alignment rules instead โจ GCC defaults to the standard alignment defined in the ABI ๐ธ
On 64-bit Darwin, natural alignment is the default, and -malign-power is not supported ๐
-msoft-float -mhard-float
Okay this pair is about the floating-point register set ๐ -msoft-float makes code that does not use the floating-point registers, and -mhard-float makes code that does use them ๐ 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
Literally so specific ๐ญ -mmultiple generates code that uses the load multiple word and store multiple word instructions, and -mno-multiple generates code that doesn't ๐
These are generated by default on POWER systems, but not on PowerPC systems ๐ฅ Do not use -mmultiple on little-endian PowerPC systems, bestie, because those instructions don't work when the processor is in little-endian mode ๐ซ The exceptions are PPC740 and PPC750, which permit these instructions in little-endian mode โจ
-mupdate -mno-update
Okay so -mupdate generates code that uses the load or store instructions that update the base register to the address of the calculated memory location, and -mno-update generates code that doesn't ๐ These instructions are generated by default ๐ฆ Here's the tea though: if you use -mno-update, there's a small window between the time the stack pointer is updated and the time the address of the previous frame is stored. That means code that walks the stack frame across interrupts or signals may get corrupted data ๐ญ๐
-mavoid-indexed-addresses -mno-avoid-indexed-addresses
This one is so detailed ๐ค -mavoid-indexed-addresses generates code that tries to avoid indexed load or store instructions, and -mno-avoid-indexed-addresses means it doesn't try to avoid them ๐ธ Indexed instructions can cause a performance penalty on Power6 processors in certain situations, like when stepping through large arrays that cross a 16M boundary ๐ This option is enabled by default when targeting Power6, and disabled otherwise ๐ง
-mfused-madd -mno-fused-madd
Okay the multiply-and-accumulate vibes are real ๐ฅ -mfused-madd generates code that uses the floating-point multiply and accumulate instructions, and -mno-fused-madd generates code that doesn't โจ These are generated by default if hardware floating point is used ๐ Also, the machine-dependent -mfused-madd option is now mapped to the machine-independent -ffp-contract=fast option, and -mno-fused-madd is mapped to -ffp-contract=off ๐ซถ
-mmulhw -mno-mulhw
Ngl these are for a specific crowd ๐ฆ -mmulhw generates code that uses the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors, and -mno-mulhw generates code that doesn't ๐ These instructions are generated by default when you target those processors ๐
-mdlmzb -mno-dlmzb
Lowkey a fun one ๐ง -mdlmzb generates code that uses the string-search dlmzb instruction on the IBM 405, 440, 464 and 476 processors, and -mno-dlmzb generates code that doesn't ๐
This instruction is generated by default when targeting those processors โจ
-mno-bit-align -mbit-align
Okay bit-fields, bestie ๐ On System V.4 and embedded PowerPC systems, -mno-bit-align does not force structures and unions that contain bit-fields to be aligned to the base type of the bit-field, and -mbit-align does ๐ธ
For example, by default a structure with nothing but 8 unsigned bit-fields of length 1 is aligned to a 4-byte boundary and has a size of 4 bytes ๐ With -mno-bit-align, that same structure is aligned to a 1-byte boundary and is 1 byte in size ๐ฅ
-mno-strict-align -mstrict-align
Okay alignment again ๐ญ On System V.4 and embedded PowerPC systems, -mno-strict-align does not assume that unaligned memory references are handled by the system, and -mstrict-align does ๐
-mrelocatable -mno-relocatable
Okay this one is giving linker drama ๐ฆ -mrelocatable generates code that allows a static executable to be relocated to a different address at run time, and -mno-relocatable generates code that doesn't allow it ๐ A simple embedded PowerPC system loader should relocate the entire contents of .got2 and 4-byte locations listed in the .fixup section, which is a table of 32-bit addresses generated by this option ๐ง For this to work, all objects linked together must be compiled with -mrelocatable or -mrelocatable-lib ๐ซถ Also, -mrelocatable code aligns the stack to an 8-byte boundary โจ
-mrelocatable-lib -mno-relocatable-lib
Like, this is the cousin of -mrelocatable ๐ -mrelocatable-lib also generates a .fixup section so static executables can be relocated at run time ๐ The difference is that it doesn't use the smaller stack alignment of -mrelocatable ๐ฅ Objects compiled with -mrelocatable-lib can be linked with objects compiled with any combination of the -mrelocatable options ๐ซถ -mno-relocatable-lib turns this off ๐
-mno-toc -mtoc
Okay the TOC is back, bestie ๐ง On System V.4 and embedded PowerPC systems, -mno-toc does not assume that register 2 contains a pointer to a global area pointing to the addresses used in the program, and -mtoc does ๐ธ
-mlittle -mlittle-endian
Ngl these are the same thing ๐
On System V.4 and embedded PowerPC systems, both of these compile code for the processor in little-endian mode ๐ซถ -mlittle-endian is the same as -mlittle โจ
-mbig -mbig-endian
And the big-endian sibling ๐ฆ On System V.4 and embedded PowerPC systems, both of these compile code for the processor in big-endian mode ๐ -mbig-endian is the same as -mbig ๐
-mdynamic-no-pic
It's giving Darwin ๐ On Darwin and Mac OS X systems, -mdynamic-no-pic compiles code so that it is not relocatable, but its external references are relocatable ๐ The resulting code is suitable for applications, but not shared libraries ๐ซ๐
Okay bestie, this batch is all about PowerPC ๐ฆ and how GCC lays out your code. Let's go ๐
-msingle-pic-baseโ this one's lowkey iconic ๐. It treats the register used for PIC addressing as read-only, so GCC stops loading it in the prologue of every single function. Instead, the runtime system has to set that register to an appropriate value before execution even begins ๐ซถ-mprioritize-restricted-insns=priorityโ this controls the priority given to dispatch-slot restricted instructions during the second scheduling pass โจ. The priority argument takes0,1, or2:0gives no priority,1gives the highest, and2gives the second-highest.-msched-costly-dep=dependence_typeโ this decides which dependences the target considers costly during instruction scheduling ๐ง . The dependence_type argument takes one of these:noโ no dependence is costly ๐allโ every dependence is costly ๐true_store_to_loadโ a true dependence from store to load is costlystore_to_loadโ any dependence from store to load is costlynumberโ any dependence whose latency is greater than or equal to number is costly
-minsert-sched-nops=schemeโ this picks which NOP insertion scheme runs during the second scheduling pass ๐ธ. The scheme argument takes one of these:noโ don't insert NOPspadโ pad any dispatch group that has vacant issue slots with NOPs, according to the scheduler's groupingregroup_exactโ insert NOPs to force costly dependent insns into separate groups. It inserts exactly as many NOPs as needed to push an insn into a new group, according to the estimated processor groupingnumberโ insert NOPs to force costly dependent insns into separate groups. It inserts number NOPs to force an insn into a new group
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code with calling conventions that follow the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement ๐. This is the default unless you configured GCC usingpowerpc-*-eabiaix.-mcall-sysv-eabi,-mcall-eabiโ this is the same as specifying both-mcall-sysvand-meabi๐-mcall-sysv-noeabiโ this is the same as specifying both-mcall-sysvand-mno-eabi๐-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐ง-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐ฆ-mtraceback=traceback_typeโ pick the type of traceback table โจ. Valid values for traceback_type arefull,part, andno.-maix-struct-returnโ returns all structures in memory, as the AIX ABI specifies ๐งฑ-msvr4-struct-returnโ returns structures smaller than 8 bytes in registers, as the SVR4 ABI specifies ๐งบ-mabi=abi-typeโ extends the current ABI with a particular extension, or removes that extension ๐ง. Valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1,elfv2, and for AIX:vec-extabi,vec-default.-mabi=ibmlongdoubleโ switches the current ABI to IBM extended-precision long double ๐ซ
This is not likely to work if your system defaults to IEEE extended-precision long double ๐ญ. If you change the long double type from IEEE extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption. This requires-mlong-double-128to be enabled.
-mabi=ieeelongdoubleโ switches the current ABI to IEEE extended-precision long double ๐ซ
This is not likely to work if your system defaults to IBM extended-precision long double ๐ญ. If you change the long double type from IBM extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption. This requires-mlong-double-128to be enabled.
-mabi=elfv1โ switches the current ABI to the ELFv1 ABI. This is the default ABI for big-endian PowerPC 64-bit Linux ๐ข
Overriding the default ABI requires special system support and is likely to fail in spectacular ways ๐
-mabi=elfv2โ switches the current ABI to the ELFv2 ABI. This is the default ABI for little-endian PowerPC 64-bit Linux ๐ธ
Overriding the default ABI requires special system support and is likely to fail in spectacular ways ๐
-mgnu-attribute,-mno-gnu-attributeโ emits.gnu_attributeassembly directives to set tag/value pairs in a.gnu.attributessection. These specify ABI variations in function parameters or return values ๐ท๏ธ-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems,-mprototypeassumes that all calls to variable argument functions are properly prototyped ๐. Otherwise, the compiler has to insert an instruction before every non-prototyped call to set or clear bit 6 of the condition code register ("CR"). That bit tells the function 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 issim-crt0.oand the standard C libraries arelibsim.aandlibc.a๐ฅ๏ธ. This is the default forpowerpc-*-eabisimconfigurations.-mmvmeโ on embedded PowerPC systems, this assumes the startup module iscrt0.oand the standard C libraries arelibmvme.aandlibc.a๐-madsโ on embedded PowerPC systems, this assumes the startup module iscrt0.oand the standard C libraries arelibads.aandlibc.a๐-myellowknifeโ on embedded PowerPC systems, this assumes the startup module iscrt0.oand the standard C libraries arelibyk.aandlibc.a๐-mvxworksโ on System V.4 and embedded PowerPC systems, this specifies that you're compiling for a VxWorks system ๐ฐ๏ธ-membโ on embedded PowerPC systems, this sets the"PPC_EMB"bit in the ELF flags header. That tells everyone that eabi extended relocations are used ๐ช-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems,-meabiadheres to the Embedded Applications Binary Interface (EABI), which is a set of modifications to the System V.4 specifications.-mno-eabidoes not ๐ โโ๏ธ- With
-meabi, the stack is aligned to an 8-byte boundary. A function__eabiis called frommainto set up the EABI environment, and the-msdataoption can use bothr2andr13to point to two separate small data areas. - With
-mno-eabi, the stack is aligned to a 16-byte boundary and no EABI initialization function is called frommain. The-msdataoption only usesr13to point to a single small data area. - The
-meabioption is on by default if you configured GCC using one of thepowerpc*-*-eabi*options ๐
- With
-msdata=eabiโ on System V.4 and embedded PowerPC systems, small initializedconstglobal and static data goes in the.sdata2section, whichr2points to ๐ฆ. Small initialized non-constglobal and static data goes in the.sdatasection, whichr13points to. Small uninitialized global and static data goes in the.sbsssection, which sits right next to.sdata. The-msdata=eabioption is incompatible with the-mrelocatableoption, and it also sets the-memboption ๐-msdata=sysvโ on System V.4 and embedded PowerPC systems, small global and static data goes in the.sdatasection, whichr13points to. Small uninitialized global and static data goes in the.sbsssection, which is adjacent to.sdata. The-msdata=sysvoption is incompatible with the-mrelocatableoption ๐งธ-msdata=default,-msdataโ on System V.4 and embedded PowerPC systems, if-meabiis used, this compiles code the same as-msdata=eabi. Otherwise, it compiles code the same as-msdata=sysv๐ฏ-msdata=dataโ on System V.4 and embedded PowerPC systems, small global data goes in the.sdatasection, and small uninitialized global data goes in the.sbsssection. It does not user13to address small data, though. This is the default behavior unless other-msdataoptions are used ๐-msdata=none,-mno-sdataโ on embedded PowerPC systems, all initialized global and static data goes in the.datasection, and all uninitialized data goes in the.bsssection ๐ซง-mreadonly-in-sdataโ puts read-only objects in the.sdatasection as well. This is the default ๐-mblock-move-inline-limit=numโ inlines all block moves (like calls to"memcpy"or structure copies) that are less than or equal to num bytes ๐. The minimum value for num is 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default value is target-specific.-mblock-compare-inline-limit=numโ generates non-looping inline code for all block compares (like calls to"memcmp"or structure compares) that are less than or equal to num bytes ๐. If num is0, all inline expansion of block compares, both non-loop and loop, is disabled. The default value is target-specific.-mblock-compare-inline-loop-limit=numโ generates an inline expansion using loop code for all block compares that are less than or equal to num bytes, but greater than the limit for non-loop inline block compare expansion ๐. If the block length isn't constant, at most num bytes get compared before"memcmp"is called to compare the rest of the block. The default value is target-specific.-mstring-compare-inline-limit=numโ compares at most num string bytes with inline code ๐งต. If the difference or end of string isn't found at the end of the inline compare, a call to"strcmp"or"strncmp"takes care of the rest of the comparison. The default is 64 bytes.-G numโ on embedded PowerPC systems, this puts global and static items that are less than or equal to num bytes into the small data or BSS sections, instead of the normal data or BSS section ๐ช. By default, num is 8. The-G numswitch is also passed to the linker. All modules should be compiled with the same-G numvalue โญ-mregnames,-mno-regnamesโ okay so on System V.4 and embedded PowerPC systems,-mregnamestells GCC to print register names in the assembly output using symbolic forms ๐ .-mno-regnamessays nah, don't do that. ๐ธ-mlongcall,-mno-longcallโ bestie, by default GCC assumes every call is far away ๐ง, so it uses a longer, more expensive calling sequence. That's needed for calls farther than 32 megabytes (33,554,432 bytes) from the current location. A short call only gets generated if the compiler knows the call can't be that far. You can override this with the "shortcall" function attribute, or with#pragma longcall(0).- Some linkers can spot out-of-range calls and generate glue code on the fly ๐ฅ. On those systems long calls are unnecessary, and they just make slower code. As of this writing, the AIX linker can do this, and so can the GNU linker for PowerPC/64. It's planned to add this feature to the GNU linker for 32-bit PowerPC systems too.
- On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see
-mpltseq). PowerPC with-mbss-pltand PowerPC64 ELFv1 (big-endian) do not support inline PLT calls ๐. - On Darwin/PPC systems,
#pragma longcallgeneratesjbsr 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 abl calleeif the PPCblinstruction reaches the callee directly. Otherwise, the linker generatesbl L42to call the branch island. The branch island gets tacked onto the end of the calling function's body, and it computes the full 32-bit address of the callee and jumps to it. ๐ฆ - On Mach-O (Darwin) systems, this option directs the compiler to emit the glue for every direct call, and 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โ ngl this one's a vibe ๐ฆ. It makes GCC implement (or not implement)-fno-pltand long calls using an inline PLT call sequence that supports lazy linking and long calls to functions in dlopen'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, for 32-bit PowerPC, if GCC is configured with--enable-secureplt.
Heads up:-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together. ๐
-mtls-markers,-mno-tls-markersโ this one marks (or doesn't mark) calls to__tls_get_addrwith a relocation specifying the function argument โจ. That relocation lets the linker reliably associate the function call with the argument setup instructions for TLS optimization, which in turn lets GCC schedule the sequence better.-mrecip,-mno-recipโ this option turns on 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 then a divide) for floating-point arguments ๐งฎ. You should use-ffast-mathwhen using-mrecip(or at least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math). Note that while the throughput of the sequence is generally higher than the throughput of the non-reciprocal instruction, the precision of the sequence can be decreased by up to 2 ulp (i.e. the inverse of1.0equals0.99999994) for reciprocal square roots.-mrecip=optโ this controls which reciprocal estimate instructions may be used ๐.optis a comma-separated list of options, and any of them can be preceded by a!to invert it:allโ enable all estimate instructions.defaultโ enable the default instructions, equivalent to-mrecip.noneโ disable all estimate instructions, equivalent to-mno-recip.divโ enable the reciprocal approximation instructions for both single and double precision.divfโ enable the single-precision reciprocal approximation instructions.divdโ enable the double-precision reciprocal approximation instructions.rsqrtโ enable the reciprocal square root approximation instructions for both single and double precision.rsqrtfโ enable the single-precision reciprocal square root approximation instructions.rsqrtdโ enable the double-precision reciprocal square root approximation instructions.- So, for example,
-mrecip=all,!rsqrtdenables all of the reciprocal estimate instructions, except for the "FRSQRTE", "XSRSQRTEDP", and "XVRSQRTEDP" instructions, which handle the double-precision reciprocal square root calculations. ๐ซถ
-mrecip-precision,-mno-recip-precisionโ assume (or don't assume) that the reciprocal estimate instructions give higher-precision estimates than the PowerPC ABI mandates ๐. Selecting-mcpu=power6,-mcpu=power7or-mcpu=power8automatically selects-mrecip-precision. The double-precision square root estimate instructions aren't generated by default on low-precision machines, since they don't provide an estimate that converges after three steps.-mveclibabi=typeโ specifies the ABI type to use for vectorizing intrinsics using an external library ๐. The only type supported at present ismass, which tells GCC to use IBM's Mathematical Acceleration Subsystem (MASS) libraries for vectorizing intrinsics using external libraries. GCC currently emits calls toacosd2,acosf4,acoshd2,acoshf4,asind2,asinf4,asinhd2,asinhf4,atan2d2,atan2f4,atand2,atanf4,atanhd2,atanhf4,cbrtd2,cbrtf4,cosd2,cosf4,coshd2,coshf4,erfcd2,erfcf4,erfd2,erff4,exp2d2,exp2f4,expd2,expf4,expm1d2,expm1f4,hypotd2,hypotf4,lgammad2,lgammaf4,log10d2,log10f4,log1pd2,log1pf4,log2d2,log2f4,logd2,logf4,powd2,powf4,sind2,sinf4,sinhd2,sinhf4,sqrtd2,sqrtf4,tand2,tanf4,tanhd2, andtanhf4when generating code for power7. Both-ftree-vectorizeand-funsafe-math-optimizationsmust also be enabled. The MASS libraries must be specified at link time.-mfriz,-mno-frizโ generate (or don't generate) thefrizinstruction when-funsafe-math-optimizationsis used to optimize rounding of floating-point values to 64-bit integer and back to floating point ๐ธ. Heads up, though: thefrizinstruction does not return the same value if the floating-point number is too large to fit in an integer. ๐-mpointers-to-nested-functions,-mno-pointers-to-nested-functionsโ generate (or don't generate) code to load up the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems, where a function pointer points to a 3-word descriptor giving the function address, the TOC value to be loaded in registerr2, and the static chain value to be loaded in registerr11.-mpointers-to-nested-functionsis on by default. If you use-mno-pointers-to-nested-functions, you can't call through pointers to nested functions, or through pointers to functions compiled in other languages that use the static chain. ๐ง-msave-toc-indirect,-mno-save-toc-indirectโ generate (or don't generate) code to save the TOC value in the reserved stack location in the function prologue, if the function calls through a pointer on AIX and 64-bit Linux systems. If the TOC value isn't saved in the prologue, it's saved just before the call through the pointer.-mno-save-toc-indirectis the default ๐ .-mcompat-align-parm,-mno-compat-align-parmโ generate (or don't generate) code to pass structure parameters with a maximum alignment of 64 bits, for compatibility with older versions of GCC ๐.- Older versions of GCC (prior to 4.9.0) incorrectly did not align a structure parameter on a 128-bit boundary when that structure contained a member requiring 128-bit alignment. This is corrected in more recent versions of GCC. This option may be used to generate code that's compatible with functions compiled with older versions of GCC. ๐ญ
-mno-compat-align-parmis the default.
-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset,-mstack-protector-guard-symbol=symbolโ generate stack protection code using a canary at guard ๐ก๏ธ. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default with GNU libc version 2.4 or later).- With the
tlschoice,-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsetalso let you pick which register to use as the base register for reading the canary, and what offset from that base register. The defaults for those are whatever the relevant ABI specifies. -mstack-protector-guard-symbol=symboloverrides the offset with a symbol reference to a canary in the TLS block.
- With the
-mpcrel,-mno-pcrelโ generate (or don't generate) pc-relative addressing ๐ฆ. The-mpcreloption requires that the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) options are enabled.-mprefixed,-mno-prefixedโ generate (or don't generate) addressing modes using prefixed load and store instructions โจ. The-mprefixedoption requires that the option-mcpu=power10(or later) is enabled.-mmma,-mno-mmaโ generate (or don't generate) the MMA instructions ๐ฅ. The-mmaoption requires that the option-mcpu=power10(or later) is enabled.-mrop-protect,-mno-rop-protectโ generate (or don't generate) ROP protection instructions when the target processor supports them. Currently, this option disables the shrink-wrap optimization (-fshrink-wrap) ๐.-mprivileged,-mno-privilegedโ generate (or don't generate) code that will run in privileged state ๐.-mblock-ops-unaligned-vsx,-mno-block-ops-unaligned-vsxโ generate (or don't generate) unaligned vsx loads and stores for inline expansion ofmemcpyandmemmove๐.
โจ RX Options โจ
These command-line options are defined for RX targets:
-m64bit-doubles,-m32bit-doubles: okay so these decide how big thedoubletype is ๐.-m64bit-doublesmakes it 64 bits and-m32bit-doublesmakes it 32 bits. The default is-m32bit-doubles, and that makes sense because the RX floating-point hardware only works on 32-bit values ๐ฅ.-fpu,-nofpu: this turns the RX floating-point hardware on (-fpu) or off (-nofpu) โจ. It's on by default for the RX600 series and off for the RX200 series.
Floating-point instructions only get generated for 32-bit floats though, so the FPU isn't used for doubles if you go with -m64bit-doubles ๐ฆ.
๐จ Note: if-fpuis enabled,-funsafe-math-optimizationsgets switched on automatically too. That's because the RX FPU instructions are themselves unsafe, so be careful, bestie ๐.
-mcpu=name: picks which RX CPU you're targeting ๐. There are three types: the generic RX600 series, the RX200 series, and the specific RX610 CPU. The default is RX600.
The only difference between RX600 and RX610 is that the RX610 doesn't support the "MVTIPL" instruction ๐. The RX200 series has no hardware floating-point unit, so -nofpu is turned on by default when you pick that one ๐.
-mbig-endian-data,-mlittle-endian-data: stores data (but not code) in big-endian format ๐. The default is-mlittle-endian-data, so your data gets stored little-endian unless you say otherwise.-msmall-data-limit=N: this sets the max size in bytes for global and static variables that can get tucked into the small data area ๐ง. The small data area can make code smaller and faster, but it's limited in size and it's on you, the programmer, to make sure it doesn't overflow ๐ญ.
When the small data area is in use, one of the RX's registers (usually "r13") gets reserved to point at that area, so the compiler can't use it anymore. That can mean slower and/or bigger code if variables get pushed onto the stack instead of living in that register ๐
.
Heads up: common variables (ones that haven't been initialized) and constants don't go 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. It's also not turned on by default at higher optimization levels (-O2 etc), because reserving a register can have potentially detrimental effects. It's up to you to experiment and see if it helps your program โจ. Check out the -mpid option to see how the register that holds the small data area pointer gets chosen.
-msim,-mno-sim: uses the simulator runtime ๐. The default is the libgloss board-specific runtime.-mas100-syntax,-mno-as100-syntax: when generating assembler output, this uses a syntax that's compatible with Renesas's AS100 assembler ๐ฆ. The GAS assembler can handle this syntax too, but it has some restrictions, so it isn't generated by default.-mmax-constant-size=N: sets the max size in bytes of a constant that can be used as an operand in an RX instruction ๐ธ. The RX instruction set can take constants up to 4 bytes long, but a longer value means a longer instruction. So sometimes it's actually beneficial to limit the size of constants used in instructions. Constants that are too big get put into a constant pool instead and referenced via register indirection.
The value N can be between 0 and 4. A value of 0 (the default) or 4 means constants of any size are allowed ๐.
-mrelax: enables linker relaxation ๐ง . That's where the linker tries to shrink your program by finding shorter versions of various instructions. It's disabled by default.-mint-register=N: reserves a number of registers for fast interrupt handler functions ๐.Ncan be between 0 and 4:1:"r13"is reserved for the exclusive use of fast interrupt handlers.2:"r13"and"r12"are reserved.3:"r13","r12"and"r11"are reserved.4:"r13"through"r10"are reserved.0(the default) doesn't reserve any registers ๐.
-msave-acc-in-interrupts: tells interrupt handler functions to preserve the accumulator register โจ. You only need this if normal code might use the accumulator, for example because it does 64-bit multiplications. By default the accumulator gets ignored, because that makes interrupt handlers faster ๐โโ๏ธ.-mpid,-mno-pid: turns on the generation of position independent data ๐ง. When it's on, any access to constant data happens via an offset from a base address held in a register. This lets the location of constant data get figured out at run time without the executable needing to be relocated, which is a big win for embedded apps with tight memory constraints ๐ซถ. Data that can be modified isn't affected by this option.
โ ๏ธ Heads up: using this feature reserves a register, usually "r13", for the constant data base address. That can mean slower and/or larger code, especially in complicated functions ๐ฌ.
Which register holds that base address depends on whether -msmall-data-limit and/or -mint-register are enabled. Starting at "r13" and working downwards, registers get allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. So it's totally possible for the small data area register to end up as "r8" if you specify both -mint-register=4 and -mpid on the command line ๐.
By default this feature is not enabled. You can restore the default with the -mno-pid command-line option.
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interrupts: stops GCC from throwing a warning if it finds more than one fast interrupt handler while compiling a file ๐ฅ. By default it warns for each extra fast interrupt handler it finds, because the RX only supports one of those.-mallow-string-insns,-mno-allow-string-insns: enables or disables the string manipulation instructions"SMOVF","SCMPU","SMOVB","SMOVU","SUNTIL""SWHILE", plus the"RMPA"instruction ๐ . These might prefetch data, which is not safe if you're accessing an I/O register ๐. (See section 12.2.7 of the RX62N Group User's Manual for more info.)
The default is to allow these instructions. GCC can't reliably detect every situation where a string instruction might be used to touch an I/O register, so it can't turn them off automatically. Instead, it's on the programmer to use -mno-allow-string-insns if the program accesses I/O space ๐ซถ.
When the instructions are enabled, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. Otherwise it defines __RX_DISALLOW_STRING_INSNS__ โจ.
-mjsr,-mno-jsr: uses only (or not only)"JSR"instructions to access functions ๐ฆ. This can come in handy when your code size goes past the range of"BSR"instructions. Note that-mno-jsrdoesn't mean "don't use JSR". It just means any type of branch may be used.
Note: the generic GCC command-line option -ffixed-reg has special significance to the RX port when it's used with the "interrupt" function attribute ๐ง. That attribute marks a function meant to process fast interrupts. GCC makes sure it only uses the registers "r10", "r11", "r12" and/or "r13", and only as long as the normal use of those registers has been restricted via the -ffixed-reg or -mint-register command-line options ๐.
โจ S/390 and zSeries Options โจ
These are the -m options defined for the S/390 and zSeries architecture ๐.
-mhard-float,-msoft-float: uses (or doesn't use) the hardware floating-point instructions and registers for floating-point operations ๐ฅ. With-msoft-float, functions inlibgcc.aget used to do the floating-point operations. With-mhard-float, the compiler generates IEEE floating-point instructions. This is the default.-mhard-dfp,-mno-hard-dfp: uses (or doesn't use) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐. With-mno-hard-dfp, functions inlibgcc.ado the decimal-floating-point work. With-mhard-dfp, the compiler generates decimal-floating-point hardware instructions. This is the default for-march=z9-ecor higher.-mlong-double-64,-mlong-double-128: these switches control the size of thelong doubletype ๐. A size of 64 bits makeslong doubleequivalent todouble. This is the default.-mbackchain,-mno-backchain: stores (or doesn't store) the address of the caller's frame as a backchain pointer in the callee's stack frame ๐ง . A backchain might be needed to allow debugging with tools that don't understand DWARF call frame information.
When -mno-packed-stack is in effect, the backchain pointer is stored at the bottom of the stack frame. When -mpacked-stack is in effect, the backchain gets placed into the topmost word of the 96/160 byte register save area ๐ธ.
In general, code compiled with -mbackchain is call-compatible with code compiled with -mno-backchain. However, using the backchain for debugging purposes usually requires the whole binary to be built with -mbackchain ๐. Note that the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported. In order to build a Linux kernel, use -msoft-float ๐ซถ.
The default is to not maintain the backchain.
-mpacked-stack, -mno-packed-stack
Okay so this one is all about how the stack gets laid out ๐ฅ -mno-packed-stack tells the compiler to use every field of the 96/160 byte register save area only for its default purpose, which means unused fields still eat up stack space ๐ญ -mpacked-stack packs the register save slots densely at the top of that area, and unused space gets reused for other stuff, so your stack space goes way further โจ BUT if -mbackchain is also on, the topmost word of the save area is always used for the backchain, and the return address register is always saved two words below the backchain ๐
As long as the stack frame backchain isn't used, code made with -mpacked-stack is call-compatible with code made with -mno-packed-stack ๐ซถ Lowkey tricky part: 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-stackand-mhard-floatis not supported ๐ซ If you're building a linux kernel, use-msoft-floatinstead ๐ง
The default is to not use the packed stack layout ๐
-msmall-exec,-mno-small-execโ generate (or skip generating) code that uses thebrasinstruction for subroutine calls ๐ This only works reliably if the total executable size doesn't go over 64k, so it's not for chonky programs ๐ โโ๏ธ The default is thebasrinstruction instead, which doesn't have that limit ๐-m64,-m31โ-m31makes code compliant with the GNU/Linux for S/390 ABI, and-m64makes it compliant with the GNU/Linux for zSeries ABI ๐ This lets GCC generate 64-bit instructions, which is giving main character energy ๐ For the s390 targets the default is-m31, and the s390x targets default to-m64โจ-mzarch,-mesaโ-mzarchgenerates code using the instructions available on z/Architecture, and-mesauses the instructions available on ESA/390 ๐ฆ Heads up:-mesais NOT possible with-m64โ ๏ธ When you're making GNU/Linux for S/390 ABI code, the default is-mesa. For GNU/Linux for zSeries ABI code, the default is-mzarch๐-mhtm,-mno-htmโ the-mhtmoption turns on a set of builtins that use instructions from the transactional execution facility, which came in with the IBM zEnterprise EC12 machine generation, plus S/390 System z Built-in Functions ๐ง-mhtmis enabled by default when you use-march=zEC12๐-mvx,-mno-vxโ-mvxgenerates code using the instructions from the vector extension facility, introduced with the IBM z13 machine generation ๐ธ This 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 binary with the ABI it used ๐-mvxis enabled by default when you use-march=z13๐ฅ-mzvector,-mno-zvectorโ-mzvectorturns on vector language extensions and builtins, using the same vector extension facility from the IBM z13 machine generation ๐ It lets you usevectoras a keyword to define vector type variables and arguments ๐ซง Just know thatvectoronly works when GNU extensions are enabled. It won't expand if you ask for strict standard compliance, like with-std=c99๐ โโ๏ธ On top of the GCC low-level builtins,-mzvectoralso adds a set of builtins for compatibility with AltiVec-style implementations like Power and Cell ๐ To use those, 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 info while compiling ๐ The default is to not print debug info ๐-march=cpu-typeโ generate code that runs on cpu-type, which is the name of a system for a certain processor type ๐ฅ๏ธ The 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,z16/arch14, andnative๐ The default is-march=z900๐ซถ
Picking native as the cpu type selects the best architecture option for the host processor ๐ง But -march=native does nothing if GCC doesn't recognize the processor ๐คทโโ๏ธ
-mtune=cpu-typeโ tunes everything applicable about the generated code to cpu-type, except for the ABI and the set of available instructions โจ The list of cpu-type values is the same as for-march๐ The default is whatever value 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 is off by default, even when you're 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-trace, so they point to specialized trace routines ๐ฏ This lets you selectively skip function trace entries for the TPF OS ๐ฆ It's off by default too, even when you're 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 get generated by default if hardware floating point is used ๐ช-mwarn-framesize=framesizeโ emits a warning if the current function goes over 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 spot functions that most probably cause a stack overflow ๐ It's super useful in environments with a limited stack size, like the linux kernel ๐ง-mwarn-dynamicstackโ emits a warning if the function callsallocaor uses dynamically-sized arrays ๐จ This is generally a bad idea with a limited stack size ๐ฌ-mstack-guard=stack-guard,-mstack-size=stack-sizeโ if you give these options, the S/390 back end adds extra instructions to the function prologue that trigger a trap if the stack size is stack-guard bytes above the stack-size ๐ชค (Remember, the stack on S/390 grows downward, so keep that in mind ๐) If you leave outstack-guard, the smallest power of 2 larger than the frame size of the compiled function gets picked ๐งฎ These are meant to help you debug stack overflow problems ๐ The extra code only adds a little overhead, so it can even be used in production-like systems without a big performance hit ๐
The values have to be exact powers of 2, and stack-size has to be greater than stack-guard without going over 64k ๐ To be efficient, the extra code assumes the stack starts at an address aligned to the value given by stack-size ๐งฉ Also, -mstack-guard can only be used together with -mstack-size ๐ซถ
-mhotpatch=pre-halfwords,post-halfwordsโ if the hotpatch option is enabled, a "hot-patching" function prologue is generated for all functions in the compilation unit ๐ฅ The function label gets prepended with the given number of two-byte NOP instructions (pre-halfwords, maximum1000000) ๐ After the label,2 * post-halfwordsbytes get appended, using the largest NOP-like instructions the architecture allows (maximum1000000) ๐งฑ
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 code for big-endian mode ๐ This is the default ๐-melโ compile code for little-endian mode ๐-mnhwloopโ disables generation ofbcnzinstructions ๐ซ-mulsโ enables generation of unaligned load and store instructions ๐งถ-mmacโ enables the use of multiply-accumulate instructions ๐งฎ Disabled by default ๐ค-mscore5โ specifies SCORE5 as the target architecture ๐ฏ-mscore5uโ specifies SCORE5U as the target architecture ๐ฏ-mscore7โ specifies SCORE7 as the target architecture ๐ This is the default ๐-mscore7dโ specifies SCORE7D as the target architecture ๐ฏ
โจ SH Options โจ
These -m options are defined for the SH implementations ๐ฆ
-m1โ generate code for the SH1 ๐ฑ-m2โ generate code for the SH2 ๐ฟ-m2eโ generate code for the SH2e ๐-m2a-nofpuโ generate code for the SH2a without FPU, or for a SH2a-FPU in such a way that the floating-point unit isn't used ๐-m2a-single-onlyโ generate code for the SH2a-FPU so that no double-precision floating-point operations are used ๐-m2a-singleโ generate code for the SH2a-FPU, assuming the floating-point unit is in single-precision mode by default ๐น-m2aโ generate code for the SH2a-FPU, assuming the floating-point unit is in double-precision mode by default ๐ท-m3โ generate code for the SH3 ๐ผ-m3eโ generate code for the SH3e ๐ป-m4-nofpuโ generate code for the SH4 without a floating-point unit ๐ โโ๏ธ-m4-single-onlyโ generate code for the SH4 with a floating-point unit that only supports single-precision arithmetic ๐ซง-m4-singleโ generate code for the SH4, assuming the floating-point unit is in single-precision mode by default ๐ท-m4โ generate code for the SH4 ๐บ-m4-100โ generate code for SH4-100 ๐ฏ-m4-100-nofpuโ generate code for SH4-100 in such a way that the floating-point unit isn't used ๐-m4-100-singleโ generate code for SH4-100, assuming the floating-point unit is in single-precision mode by default โจ-m4-100-single-onlyโ generate code for SH4-100 so that no double-precision floating-point operations are used ๐-m4-200โ generate code for SH4-200 ๐-m4-200-nofpu: okay so this one makes code for the SH4-200 without touching the floating-point unit at all ๐-m4-200-single: code for SH4-200, assuming the FPU boots up in single-precision mode by default โจ-m4-200-single-only: code for SH4-200 that never uses double-precision floating-point operations ๐ฆ-m4-300: code for SH4-300 ๐ธ-m4-300-nofpu: code for SH4-300 that keeps the floating-point unit out of it ๐ซถ-m4-300-single: code for SH4-300 that never uses double-precision floating-point operations ๐-m4-300-single-only: same vibe as the one above, the page says the exact same thing for this one too ๐-m4-340: code for SH4-340, which has no MMU and no FPU ๐-m4-500: code for SH4-500, no FPU. It also passes-isa=sh4-nofputo the assembler ๐ฅ-m4a-nofpu: code for the SH4al-dsp, or for a SH4a where the floating-point unit is not used ๐-m4a-single-only: code for the SH4a that skips all double-precision floating-point operations ๐-m4a-single: code for the SH4a, assuming the FPU is in single-precision mode by default โญ-m4a: code for the SH4a, full stop ๐ง-m4al: same as-m4a-nofpu, except it implicitly passes-dspto the assembler. GCC doesn't generate any DSP instructions rn ๐-mb: compile for the processor in big-endian mode ๐-ml: compile for the processor in little-endian mode ๐-mdalign: align doubles at 64-bit boundaries. Heads up bestie: this changes the calling conventions, so some functions from the standard C library won't work unless you recompile it first with-mdalign๐ญ-mrelax: shorten some address references at link time, when possible. It uses the linker option-relaxโจ-mbigtable: use 32-bit offsets in"switch"tables. The default is 16-bit offsets ๐ฆ-mbitops: enable bit manipulation instructions on SH2A ๐-mfmovd: enable thefmovdinstruction. Check-mdalignfor the alignment constraints ๐ซถ-mrenesas: comply with the calling conventions defined by Renesas ๐-mno-renesas: comply with the calling conventions GCC used before the Renesas ones existed. 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: these control the IEEE compliance of floating-point comparisons, which affects how cases where the comparison result is unordered get handled. By default-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled,-mno-ieeegets 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๐-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"icbi"instruction. If the selected option doesn't allow"icbi"and-musermodeis not in effect, the inlined code pokes the instruction cache address array directly with an associative write. That not only needs privileged mode at run time, it also fails if the cache line got mapped via the TLB and has since become unmapped ๐-misize: dump instruction size and location in the assembly code ๐ง-mpadstruct: this one is deprecated ๐. It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI-matomic-model=model: sets the model of atomic operations, plus any extra parameters, as a comma-separated list. For the full scoop on atomic built-in functions, check__atomic Builtins. These are the models and parameters you can pick from โจnone: disables compiler-generated atomic sequences and emits library calls for atomic operations. This is the default if the target is not"sh*-*-linux*"soft-gusa: generates GNU/Linux compatible gUSA software atomic sequences for the atomic built-in functions. These 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 on by default when the target is"sh*-*-linux*"and SH3* or SH4*. On SH4A it also partly uses the hardware atomic instructionsmovli.landmovco.lto make the code more efficient, unlessstrictis specified ๐ฆsoft-tcb: generates software atomic sequences that use a variable in the thread control block. It's a variation of the gUSA sequences that also works on SH1* and SH2* targets. These sequences need extra interrupt/exception handling support and are only suitable for single-core systems. When you use this model, thegbr-offset=parameter has to be specified as well ๐soft-imask: generates software atomic sequences that temporarily disable interrupts by setting"SR.IMASK = 1111". This model only works when the program runs in privileged mode and is only suitable for single-core systems. No extra interrupt/exception handling support is needed. It's on by default when the target is"sh*-*-linux*"and SH1* or SH2* ๐ฅhard-llcs: generates hardware atomic sequences using only themovli.landmovco.linstructions. This is only available on SH4A and is suitable for multi-core systems. Since the hardware instructions only support 32-bit atomic variable access, 8-bit and 16-bit variables get emulated with 32-bit accesses. Code compiled with this option is also compatible with other software atomic model interrupt/exception handling systems if it runs on an SH4A system. No extra interrupt/exception support is required for this model ๐gbr-offset=: the offset in bytes of the variable inside the thread control block structure that the generated atomic sequences should use when thesoft-tcbmodel is selected. For other models this parameter is ignored. The value must be an integer multiple of four and in the range0-1020โญstrict: stops you from mixing multiple atomic models, even compatible ones, and makes the compiler generate atomic sequences of the specified model only ๐
-mtas: generates thetas.bopcode for__atomic_test_and_set. Notice that depending on your particular hardware and software setup, this can degrade overall performance because of the operand cache line flushes that thetas.binstruction implies ๐ซถ
Careful, bestie! On multi-core SH4A processors, the tas.b instruction has to be used with caution, since it can cause data corruption for certain cache configurations ๐ญ
-mprefergot: when generating position-independent code, emit function calls through the Global Offset Table instead of the Procedure Linkage Table ๐ง-musermode,-mno-usermode: "Don't allow (allow) the compiler generating privileged mode code," according to the page ๐. Specifying-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode.-musermodeis the default when the target is"sh*-*-linux*". If the target is SH1* or SH2*,-musermodehas no effect, since there's no user mode there ๐-multcost=number: sets the cost to assume for a multiply insn ๐ธ-mdiv=strategy: sets the division strategy used for integer division operations.strategycan be one of these ๐ฅcall-div1: calls a library function that uses the single-step division instructiondiv1to do the job. Division 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. Division by zero causes a floating-point exception. This is the default for SHcompact with FPU. Specifying this for targets without a double-precision FPU defaults tocall-div1๐call-table: calls a library function that uses a lookup table for small divisors and thediv1instruction with case distinction for bigger divisors. Division by zero gives an unspecified result and doesn't trap. This is the default for SH4. Specifying this for targets without dynamic shift instructions defaults tocall-div1โจ- When no division strategy is specified, the default is picked based on the current target. For SH2A the default is to use the
divsanddivuinstructions 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 change around conditional code ๐ซถ-mdivsi3_libfunc=name: sets the name of the library function used for 32-bit signed division toname. This only changes the name used in the call division strategies. The compiler still expects the same sets of input, output 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. This is super useful when compiling kernel code ๐. A register range is written as two registers separated by a dash, and you can list multiple ranges separated by a comma ๐-mbranch-cost=numโ โจ okay sonumis basically the cost you're assigning to a branch instruction ๐ฆ. Crank it higher and the compiler will try harder to write branch-free code when it can ๐ . If you don't set it, GCC picks a value based on which processor you're compiling for ๐ง.-mzdcbranch,-mno-zdcbranchโ ๐ These tell the compiler whether zero displacement conditional branches,"bt"and"bf", are fast. With-mzdcbranchit'll prefer those zero displacement branch sequences ๐ธ. It's already on by default when you're targeting SH4 and SH4A ๐, and you can turn it off explicitly with-mno-zdcbranch๐.-mcbranch-force-delay-slotโ ๐ญ This forces conditional branches to use delay slots. If nothing suitable can fill the slot, it gets stuffed with anopinstead ๐. It's off by default, but you can flip it on to work around hardware bugs found in the original SH7055 ๐ฅ.-mfused-madd,-mno-fused-maddโ ๐ Lowkey this controls whether the floating-point multiply and accumulate instructions get used. They're generated by default when hardware floating point is in play โจ. Heads up: the machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fast, and-mno-fused-maddis mapped to-ffp-contract=off๐ซถ.-mfsca,-mno-fscaโ ๐ง These allow or disallow the compiler from emitting the"fsca"instruction for sine and cosine approximations. You have to pair-mfscawith-funsafe-math-optimizations๐ฅ. It's on by default for SH4A. And-mno-fscashuts off those sine and cosine approximations even when-funsafe-math-optimizationsis in effect ๐ โโ๏ธ.-mfsrra,-mno-fsrraโ ๐ฆ Same vibe, but for the"fsrra"instruction, which handles reciprocal square root approximations.-mfsrraneeds to be used with both-funsafe-math-optimizationsand-ffinite-math-only๐. It's enabled by default for SH4A.-mno-fsrraturns off reciprocal square root approximations even if-funsafe-math-optimizationsand-ffinite-math-onlyare both active ๐.-mpretend-cmoveโ ๐ This prefers zero-displacement conditional branches for conditional move instruction patterns. It can give you faster code on the SH4 processor โญ.-mfdpicโ ๐ธ Generates code using the FDPIC ABI ๐ .
โจ Solaris 2 Options โจ
These -m options are supported on Solaris 2 ๐:
-mclear-hwcapโ ๐ซถ This tells the compiler to remove the hardware capabilities that the Solaris assembler generated. You only really need it when object files use ISA extensions that the current machine doesn't support, but the code checks at runtime whether or not to use them ๐.-mimpure-textโ ๐ฅ Used alongside-shared, this tells the compiler not to pass-z textto the linker when it's linking a shared object. With it, you can link position-dependent code into a shared object ๐ง.
โ ๏ธ Bestie, be careful here.-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 is not 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 that uses global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐. Just like global register 1, each of global registers 2 through 4 is then treated as an allocable register that gets clobbered by function calls. This is the default ๐.
If you want to be fully SVR4 ABI-compliant (at the cost of some performance loss), go with -mno-app-regs ๐ซถ. You should compile libraries and system software with this option ๐ฅ.
-mflat,-mno-flatโ ๐ง With-mflat, the compiler doesn't generate save/restore instructions and uses a "flat" or single register window model ๐ฆ. This model is compatible with the regular register window model. The local registers and the input registers (0--5) are still treated as "call-saved" registers and get saved on the stack as needed โจ.
With -mno-flat (the default), the compiler generates save/restore instructions, except for leaf functions ๐. This is the normal operating mode ๐.
-mfpu,-mhard-floatโ โญ Generates output containing floating-point instructions. This is the default ๐.-mno-fpu,-msoft-floatโ ๐ญ Generates output containing library calls for floating point instead.
โ ๏ธ Warning, bestie: the requisite libraries are not available for all SPARC targets ๐. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation ๐. You must 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 in order for this to work ๐ซถ.
-mhard-quad-floatโ ๐ Generates output containing quad-word (long double) floating-point instructions ๐ธ.-msoft-quad-floatโ ๐ฆ Generates output containing library calls for quad-word (long double) floating-point instructions. The functions called are the ones specified in the SPARC ABI. This is the default ๐.
As of this writing, there are no SPARC implementations with hardware support for the quad-word floating-point instructions ๐ญ. They all invoke a trap handler for one of these instructions, and then the trap handler emulates the effect of the instruction ๐. Because of that trap handler overhead, this is much slower than calling the ABI library routines ๐. So -msoft-quad-float is the default โจ.
-mno-unaligned-doubles,-munaligned-doublesโ ๐ Assumes that doubles have 8-byte alignment. This is the default ๐.
With -munaligned-doubles, GCC assumes doubles have 8-byte alignment only if they're contained in another type, or if they have an absolute address ๐. Otherwise, it assumes they have 4-byte alignment โญ. Using this option avoids some rare compatibility problems with code generated by other compilers ๐ซถ. It's not the default, though, because it results in a performance loss, especially for floating-point code ๐ญ.
-muser-mode,-mno-user-modeโ ๐ Does not generate code that can only run in supervisor mode. This is only relevant for the"casa"instruction emitted for the LEON3 processor ๐ง. This is the default ๐ .-mfaster-structs,-mno-faster-structsโ ๐ฅ With-mfaster-structs, the compiler assumes structures should have 8-byte alignment ๐ฆ. That lets it use pairs of"ldd"and"std"instructions for copies in structure assignment, in place of twice as many"ld"and"st"pairs โจ.
โ ๏ธ Bestie, this one is spicy. The use of this changed alignment directly violates the SPARC ABI ๐. So it's intended only for targets where the developer acknowledges that their resulting code is not directly in line with the rules of the ABI ๐ญ.
-mstd-struct-return,-mno-std-struct-returnโ ๐ธ With-mstd-struct-return, the compiler generates checking code in functions returning structures or unions. That code detects size mismatches between the two sides of function calls, as per the 32-bit ABI ๐.
The default is -mno-std-struct-return ๐. This option has no effect in 64-bit mode ๐.
-mlra,-mno-lraโ ๐ Enables Local Register Allocation. This has been the default for SPARC since GCC 7, so you need to pass-mno-lraif you want the old Reload ๐.-mcpu=cpu_typeโ ๐ Sets the instruction set, register set, and instruction scheduling parameters for machine typecpu_typeโจ. Supported values forcpu_typearev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,leon5,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8๐.
Native Solaris and GNU/Linux toolchains also support the value native, which selects the best architecture option for the host processor ๐ซถ. -mcpu=native has no effect if GCC doesn't recognize the processor ๐.
Default instruction scheduling parameters are used for values that select an architecture and not an implementation ๐ง. Those are v7, v8, sparclite, sparclet, and v9 ๐
.
Here's the lineup of each supported architecture and its supported implementations ๐ฆ:
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3,leon5sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of the SPARC architecture ๐ธ. With -mcpu=cypress, the compiler additionally optimizes it for the Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series โจ. This is also appropriate for the older SPARCStation 1, 2, IPX etc. ๐.
With -mcpu=v8, GCC generates code for the V8 variant of the SPARC architecture ๐. The only difference from V7 code is that the compiler emits the integer multiply and integer divide instructions, which exist in SPARC-V8 but not in SPARC-V7 ๐. With -mcpu=supersparc, the compiler additionally optimizes it for the SuperSPARC chip, as used in the SPARCStation 10, 1000 and 2000 series โญ.
With -mcpu=sparclite, GCC generates code for the SPARClite variant of the SPARC architecture ๐ฅ. This adds the integer multiply, integer divide step and scan ("ffs") instructions, which exist in SPARClite but not in SPARC-V7 ๐ญ. With -mcpu=f930, the compiler additionally optimizes it for the Fujitsu MB86930 chip, which is the original SPARClite, with no FPU ๐ง. With -mcpu=f934, the compiler additionally optimizes it for the Fujitsu MB86934 chip, which is the more recent SPARClite with FPU ๐.
With -mcpu=sparclet, GCC generates code for the SPARClet variant of the SPARC architecture ๐ฆ This adds the integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions, which exist in SPARClet but not in SPARC-V7. With -mcpu=tsc701, the compiler also optimizes it for the TEMIC SPARClet chip ๐
With -mcpu=v9, GCC generates code for the V9 variant of the SPARC architecture โจ This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers, and conditional move instructions. With -mcpu=ultrasparc, the compiler also optimizes it for the Sun UltraSPARC I/II/IIi chips ๐ฅ With -mcpu=ultrasparc3, it's optimized for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips ๐ With -mcpu=niagara, the compiler also optimizes it for Sun UltraSPARC T1 chips ๐ธ With -mcpu=niagara2, it's optimized for Sun UltraSPARC T2 chips ๐ซถ With -mcpu=niagara3, it's optimized for Sun UltraSPARC T3 chips ๐ With -mcpu=niagara4, it's optimized for Sun UltraSPARC T4 chips ๐ With -mcpu=niagara7, the compiler also optimizes it for Oracle SPARC M7 chips โญ And With -mcpu=m8, it's optimized for Oracle M8 chips. Iconic ๐ญ
-mtune=cpu_typeโ Sets the instruction scheduling parameters for machine type cpu_type, but does not set the instruction set or register set the way-mcpu=cpu_typedoes ๐
The same values for -mcpu=cpu_type work here too, but honestly the only useful ones are the ones that select a particular CPU implementation. Those are cypress, supersparc, hypersparc, leon, leon3, leon3v7, leon5, f930, f934, sparclite86x, tsc701, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7 and m8. With native Solaris and GNU/Linux toolchains, native can also be used ๐ง
-mv8plus,-mno-v8plusโ With-mv8plus, GCC generates code for the SPARC-V8+ ABI ๐ The difference from the V8 ABI is that the global and out registers are considered 64 bits wide. This is enabled by default on Solaris in 32-bit mode for all SPARC-V9 processors.-mvis,-mno-visโ With-mvis, GCC generates code that takes advantage of the UltraSPARC Visual Instruction Set extensions ๐ฆ The default is-mno-vis.-mvis2,-mno-vis2โ With-mvis2, GCC generates code that takes advantage of version 2.0 of the UltraSPARC Visual Instruction Set extensions. The default is-mvis2when targeting a cpu that supports such instructions, such as UltraSPARC-III and later. Setting-mvis2also sets-mvis๐ฅ-mvis3,-mno-vis3โ With-mvis3, GCC generates code that takes advantage of version 3.0 of the UltraSPARC Visual Instruction Set extensions. The default is-mvis3when targeting a cpu that supports such instructions, such as niagara-3 and later. Setting-mvis3also sets-mvis2and-mvisโจ-mvis4,-mno-vis4โ With-mvis4, GCC generates code that takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions. The default is-mvis4when targeting a cpu that supports such instructions, such as niagara-7 and later. Setting-mvis4also sets-mvis3,-mvis2and-mvis๐-mvis4b,-mno-vis4bโ With-mvis4b, GCC generates code that takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions, plus the additional VIS instructions introduced in the Oracle SPARC Architecture 2017 ๐ The default is-mvis4bwhen targeting a cpu that supports such instructions, such as m8 and later. Setting-mvis4balso sets-mvis4,-mvis3,-mvis2and-mvis๐-mcbcond,-mno-cbcondโ With-mcbcond, GCC generates code that takes advantage of the UltraSPARC Compare-and-Branch-on-Condition instructions. The default is-mcbcondwhen targeting a CPU that supports such instructions, such as Niagara-4 and later ๐-mfmaf,-mno-fmafโ With-mfmaf, GCC generates code that takes advantage of the UltraSPARC Fused Multiply-Add Floating-point instructions. The default is-mfmafwhen targeting a CPU that supports such instructions, such as Niagara-3 and later ๐-mfsmuld,-mno-fsmuldโ With-mfsmuld, GCC generates code that takes advantage of the Floating-point Multiply Single to Double (FsMULd) instruction. The default is-mfsmuldwhen targeting a CPU supporting the architecture versions V8 or V9 with FPU, except-mcpu=leon๐ง-mpopc,-mno-popcโ With-mpopc, GCC generates code that takes advantage of the UltraSPARC Population Count instruction. The default is-mpopcwhen targeting a CPU that supports such an instruction, such as Niagara-2 and later ๐ธ-msubxc,-mno-subxcโ With-msubxc, GCC generates code that takes advantage of the UltraSPARC Subtract-Extended-with-Carry instruction. The default is-msubxcwhen targeting a CPU that supports such an instruction, such as Niagara-7 and later ๐ฆ-mfix-at697fโ Enables the documented workaround for the single erratum of the Atmel AT697F processor (which corresponds to erratum #13 of the AT697E processor) ๐ ๏ธ-mfix-ut699โ Enables the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor ๐ซถ-mfix-ut700โ Enables the documented workaround for the back-to-back store errata of the UT699E/UT700 processor ๐-mfix-gr712rcโ Enables the documented workaround for the back-to-back store errata of the GR712RC processor โจ
These -m options are supported in addition to the above on SPARC-V9 processors in 64-bit environments ๐
-m32,-m64โ Generates code for a 32-bit or 64-bit environment. The 32-bit 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 the following:medlowโ The Medium/Low code model: 64-bit addresses, 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, programs must be linked in the low 44 bits of memory, the text and data segments must be less than 2GB in size and the data segment must be located within 2GB of the text segment ๐medanyโ The Medium/Anywhere code model: 64-bit addresses, programs may be linked anywhere in memory, the text and data segments must be less than 2GB in size and the data segment must be located within 2GB of the text segment ๐embmedanyโ The Medium/Anywhere code model for embedded systems: 64-bit addresses, the text and data segments must be less than 2GB in size, both starting anywhere in memory (determined at link time). The global register%g4points to the base of the data segment. Programs are statically linked and PIC is not supported ๐ง
-mmemory-model=mem-modelโ Sets the memory model in force on the processor to one of the following:defaultโ The default memory model for the processor and operating system ๐ธrmoโ Relaxed Memory Order ๐psoโ Partial Store Order ๐ฆtsoโ Total Store Order โจscโ Sequential Consistency ๐
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, as set in the processor's "PSTATE.MM" field ๐ค
-mstack-bias,-mno-stack-biasโ With-mstack-bias, GCC assumes that the stack pointer, and frame pointer if present, are offset by -2047, which must be added back when making stack frame references. This is the default in 64-bit mode. Otherwise, it assumes no such offset is present ๐ซถ
โจ Options for System V โจ
These additional options are available on System V Release 4 for compatibility with other compilers on those systems ๐
-Gโ Creates a shared object. It is recommended that-symbolicor-sharedbe used instead ๐ฅ-Qyโ Identifies the versions of each tool used by the compiler, in a.identassembler directive in the output ๐-Qnโ Refrains from adding.identdirectives to the output file (this is the default) ๐-YP,dirsโ Searches the 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. Absolute addresses support the full address range ๐ธ-mcmodel=largeโ Generates code for the large model. There is no limitation on call distance, pc-relative addresses, or absolute addresses ๐-mcpu=nameโ Selects the type of CPU to be targeted. Currently the only supported type istilegxโจ-m32,-m64โ Generate 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โ Generate 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 be targeted. Currently 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 essentially 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 indirect through the pointer ๐-mno-ep,-mepโ Does not optimize (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 ๐
โจ Machine-dependent goodies, continued โจ
-mno-prolog-function,-mprolog-functionโ bestie, these decide whether the function prologue and epilogue use external helper functions to save and restore registers ๐ซถ-mprolog-functionis the default if you optimize. The helpers are slower, but if several functions save the same number of registers, they take up less code space ๐-mspaceโ the "make it tiny" button ๐ง It just switches on-mepand-mprolog-function.-mtda=nโ puts static or global variables that arenbytes or smaller into the tiny data area that registereppoints to ๐ธ That area holds up to 256 bytes total, and 128 of those are for byte references.-msda=nโ same vibe, but for the small data area that registergppoints to ๐ Variables ofnbytes or less go in there, and it can hold up to 64 kilobytes.-mzda=nโ variables ofnbytes or less get put into the first 32 kilobytes of memory ๐ฆ-mv850โ tells GCC your target processor is the V850 ๐-mv850e3v5โ your target is the V850E3V5, and the preprocessor constant__v850e3v5__gets defined when you use this โจ-mv850e2v4โ heads up, this one is giving confusing energy ๐ The page says it targets the V850E3V5, and it's just an alias for-mv850e3v5.-mv850e2v3โ your target is the V850E2V3, and__v850e2v3__gets defined ๐-mv850e2โ your target is the V850E2, and__v850e2__gets defined ๐-mv850e1โ your target is the V850E1, and both__v850e1__and__v850e__get defined ๐-mv850esโ the V850ES, which is just an alias for-mv850e1๐ฅ-mv850eโ your target is the V850E, and__v850e__gets defined ๐
If none of -mv850, -mv850e, -mv850e1, -mv850e2, -mv850e2v3, or -mv850e3v5 is set, GCC picks a default target processor for you and defines the matching __v850*__ preprocessor constant. No cap, that's a lot of constants ๐ญ
The preprocessor constants __v850 and __v851__ are always defined, no matter which processor variant you're targeting โจ
-mdisable-callt,-mno-disable-calltโ this one stops GCC from generating theCALLTinstruction for the v850e, v850e1, v850e2, v850e2v3, and v850e3v5 flavors of the v850 architecture ๐ It's on by default when the RH850 ABI is in use (see-mrh850-abi), and off by default when the GCC ABI is in use. WhenCALLTinstructions are being generated, the C preprocessor symbol__V850_CALLT__is defined ๐ฆ-mrelax,-mno-relaxโ passes (or doesn't pass) the-mrelaxcommand-line option along to the assembler ๐ซถ-mlong-jumps,-mno-long-jumpsโ turns off (or turns back on) the generation of PC-relative jump instructions ๐ธ-msoft-float,-mhard-floatโ turns off (or back on) the generation of hardware floating point instructions ๐ This only matters when the target architecture is V850E2V3 or higher. If hardware floating point instructions are being generated, the symbol__FPU_OK__is defined; otherwise__NO_FPU__is defined.-mloopโ enables the use of the e3v5LOOPinstruction ๐ง It's not enabled by default when the e3v5 architecture is selected, because its use is still experimental, so proceed with a little caution ๐-mrh850-abi,-mghsโ enables support for the RH850 version of the V850 ABI, and this is the default โจ With this version, these rules apply:- Integer sized structures and unions are returned via a memory pointer instead of 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, these rules apply:- Integer sized structures and unions are returned in register
r10. - Large structures and unions (more than 8 bytes in size) are passed by reference.
- Functions are aligned to 32-bit boundaries, unless you're optimizing for size.
- The
-m8byte-aligncommand-line option is not supported. - The
-mdisable-calltcommand-line option is supported but not enabled by default.
- Integer sized structures and unions are returned in register
When this version of the ABI is enabled, the C preprocessor symbol __V850_GCC_ABI__ is defined ๐
-m8byte-align,-mno-8byte-alignโ letsdoubleandlong longtypes get aligned on 8-byte boundaries ๐ The default is to keep the alignment of all objects to at most 4 bytes. When-m8byte-alignis in effect, the C preprocessor symbol__V850_8BYTE_ALIGN__is defined โจ-mbig-switchโ generates code that's suitable for big switch tables ๐ Only use this if the assembler or linker complains about out of range branches inside a switch table, because it's a specific fix and not a everyday flex.-mapp-regsโ makes the generated code user2andr5๐ This is the default.-mno-app-regsโ treatsr2andr5as fixed registers so they're left alone ๐ฆ
๐ VAX Options ๐
These -m options are defined for the VAX ๐
-munixโ doesn't output certain jump instructions, likeaobleqand so on, because the Unix assembler for the VAX can't handle them across long ranges ๐ซถ-mgnuโ does output those jump instructions, on the assumption that you're using the GNU assembler ๐ฅ-mgโ outputs code for G-format floating-point numbers instead of D-format ๐
๐ธ Visium Options ๐ธ
-mdebugโ if your program does file I/O and is headed for an MCM target, link it with this option โจ It causes the librarieslibc.aandlibdebug.ato get linked. You should run the program on the target under the control of the GDB remote debugging stub.-msimโ if your program does file I/O and is headed for the simulator, link it with this option ๐ง It causes the librarieslibc.aandlibsim.ato get linked.-mfpu,-mhard-floatโ generates code containing floating-point instructions ๐ธ This is the default.-mno-fpu,-msoft-floatโ generates code containing library calls for floating-point instead ๐
โ ๏ธ-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile all of a program with this option. 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 typecpu_type๐ The supported values forcpu_typearemcm,gr5, andgr6.
mcm is a synonym of gr5 that's kept around for backward compatibility ๐
By default (unless it's been 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 the machine typecpu_type, but doesn't touch the instruction set or register set the way-mcpu=cpu_typewould ๐-msv-modeโ generates code for supervisor mode, where there are no restrictions on access to general registers ๐ This is the default.-muser-modeโ generates code for user mode, where access to some general registers is forbidden ๐ On the GR5, registersr24tor31can't be accessed in this mode. On the GR6, only registersr29tor31are affected.
๐ท VMS Options ๐ท
These -m options are defined for the VMS implementations ๐ฆ
-mvms-return-codesโ returns VMS condition codes frommain. By default, you get POSIX-style condition (like error) codes instead โจ-mdebug-main=prefixโ flags the first routine whose name starts withprefixas the main routine for the debugger ๐ง-mmalloc64โ defaults to 64-bit memory allocation routines ๐-mpointer-size=sizeโ sets the default size of pointers. The possible values forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers. Thenooption disablespragma pointer_size๐
๐ VxWorks Options ๐
The options in this section are defined for all VxWorks targets ๐ซถ Options specific to the target hardware are listed with the other options for that target.
-mrtpโ GCC can generate code for both VxWorks kernels and real time processes (RTPs). This option switches from the former to the latter ๐ It also defines the preprocessor macro__RTP__.-non-staticโ links an RTP executable against shared libraries instead of static libraries ๐ The options-staticand-sharedcan also be used for RTPs, and-staticis the default โจ-Bstatic,-Bdynamicโ these options get passed down to the linker ๐ They're defined for compatibility with Diab.-Xbind-lazyโ enables lazy binding of function calls ๐ฅ This is equivalent to-Wl,-z,nowand is defined for compatibility with Diab.-Xbind-nowโ disables lazy binding of function calls ๐ This is the default, and it's defined for compatibility with Diab.
๐ฅ๏ธ x86 Options ๐ฅ๏ธ
These -m options are defined for the x86 family of computers ๐
-march=cpu-typeโ generates instructions for the machine typecpu-type๐ฆ Here's the big difference:-mtune=cpu-typejust tunes the generated code for the specifiedcpu-type, but-march=cpu-typelets GCC generate code that may not run at all on processors other than the one you indicated ๐ญ Specifying-march=cpu-typeimplies-mtune=cpu-type, except where noted otherwise.
The choices for cpu-type are:
native๐ โ okay so this one picks the CPU by checking the machine that's doing the compiling, like it literally looks at itself in the mirror ๐ช. With-march=nativeit turns on every instruction subset the local machine supports, so the result might not run on other machines โ ๏ธ. With-mtune=nativeyou get code tuned for the local machine, but still within whatever instruction set you chose.x86-64๐ธ โ a generic CPU with 64-bit extensions, the iconic baseline of the bunch.x86-64-v2,x86-64-v3,x86-64-v4โจ โ these pick the matching micro-architecture level from the x86-64 psABI. On ABIs other than the x86-64 psABI, they still select the same CPU features the x86-64 psABI documents for that particular level.- Since these cpu-type values don't have a matching
-mtunesetting, using-marchwith them enables generic tuning. For specific tuning, use-mtune=other-cpu-type with an appropriate other-cpu-type value ๐.
- Since these cpu-type values don't have a matching
i386๐ โ the original Intel i386 CPU, the OG ๐ฆ.i486๐ โ Intel i486 CPU. (No scheduling is implemented for this chip, so it's giving unbothered ๐.)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 instruction set support.pentium3,pentium3m๐ธ โ Intel Pentium III CPU, based on the Pentium Pro core with MMX and SSE instruction set support.pentium-m๐ โ Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE and SSE2 instruction set support. Used by Centrino notebooks ๐ป.pentium4,pentium4mโจ โ Intel Pentium 4 CPU with MMX, SSE and SSE2 instruction set support.prescott๐ โ an improved Intel Pentium 4 CPU with MMX, SSE, SSE2 and SSE3 instruction set support.nocona๐ซถ โ an improved Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2 and SSE3 instruction set support. Main character glow-up energy ๐.core2โ โ Intel Core 2 CPU with 64-bit extensions,MMX,SSE,SSE2,SSE3andSSSE3instruction set support.nehalem๐ โ Intel Nehalem CPU with 64-bit extensions,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2andPOPCNTinstruction set support.westmere๐ โ Intel Westmere CPU with 64-bit extensions,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AESandPCLMULinstruction set support.sandybridge๐ธ โ Intel Sandy Bridge CPU with 64-bit extensions,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AESandPCLMULinstruction set support.ivybridge๐ง โ Intel Ivy Bridge CPU with 64-bit extensions,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AES,PCLMUL,FSGSBASE,RDRNDandF16Cinstruction set support.haswell๐ฅ โ Intel Haswell CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2andF16Cinstruction set support.broadwell๐ฆ โ Intel Broadwell CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCXandPREFETCHWinstruction set support.skylake๐ โ Intel Skylake CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVECandXSAVESinstruction set support.bonnell๐ โ Intel Bonnell CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3andSSSE3instruction set support.silvermont๐ โ Intel Silvermont CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AES,PREFETCHW,PCLMULandRDRNDinstruction set support.goldmontโจ โ Intel Goldmont CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPTandFSGSBASEinstruction set support.goldmont-plus๐ โ Intel Goldmont Plus CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPT,FSGSBASE,PTWRITE,RDPID,SGXandUMIPinstruction set support.tremont๐ซถ โ Intel Tremont CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPT,FSGSBASE,PTWRITE,RDPID,SGX,UMIP,GFNI-SSE,CLWB,MOVDIRI,MOVDIR64B,CLDEMOTEandWAITPKGinstruction set support.knl๐ธ โ Intel Knight's Landing CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,PREFETCHWT1,AVX512F,AVX512PF,AVX512ERandAVX512CDinstruction set support.knm๐ฅ โ Intel Knights Mill CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,PREFETCHWT1,AVX512F,AVX512PF,AVX512ER,AVX512CD,AVX5124VNNIW,AVX5124FMAPSandAVX512VPOPCNTDQinstruction set support.skylake-avx512๐ โ Intel Skylake Server CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQandAVX512CDinstruction set support.cannonlake๐ฆ โ Intel Cannonlake Server CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VBMI,AVX512IFMA,SHAandUMIPinstruction set support.icelake-client๐ โ Intel Icelake Client CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VBMI,AVX512IFMA,SHA,CLWB,UMIP,RDPID,GFNI,AVX512VBMI2,AVX512VPOPCNTDQ,AVX512BITALG,AVX512VNNI,VPCLMULQDQandVAESinstruction set support.icelake-server๐ โ Intel Icelake Server CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VBMI,AVX512IFMA,SHA,CLWB,UMIP,RDPID,GFNI,AVX512VBMI2,AVX512VPOPCNTDQ,AVX512BITALG,AVX512VNNI,VPCLMULQDQ,VAES,PCONFIGandWBNOINVDinstruction set support.cascadelakeโญ โ Intel Cascadelake CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CDandAVX512VNNIinstruction set support.cooperlake๐ โ Intel cooperlake CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VNNIandAVX512BF16instruction set support.tigerlake๐ง โ Intel Tigerlake CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,AVX512VBMI,AVX512IFMA,SHA,CLWB,UMIP,RDPID,GFNI,AVX512VBMI2,AVX512VPOPCNTDQ,AVX512BITALG,AVX512VNNI,VPCLMULQDQ,VAES,PCONFIG,WBNOINVD,MOVDIRI,MOVDIR64B,AVX512VP2INTERSECTandKEYLOCKERinstruction set support.sapphirerapids๐ โ Intel sapphirerapids CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,CX16,SAHF,FXSR,AVX,XSAVE,PCLMUL,FSGSBASE,RDRND,F16C,AVX2,BMI,BMI2,LZCNT,FMA,MOVBE,HLE,RDSEED,ADCX,PREFETCHW,AES,CLFLUSHOPT,XSAVEC,XSAVES,SGX,AVX512F,AVX512VL,AVX512BW,AVX512DQ,AVX512CD,PKU,AVX512VBMI,AVX512IFMA,SHA,AVX512VNNI,GFNI,VAES,AVX512VBMI2,VPCLMULQDQ,AVX512BITALG,RDPID,AVX512VPOPCNTDQ,PCONFIG,WBNOINVD,CLWB,MOVDIRI,MOVDIR64B,AVX512VP2INTERSECT,ENQCMD,CLDEMOTE,PTWRITE,WAITPKG,SERIALIZE,TSXLDTRK,UINTR,AMX-BF16,AMX-TILE,AMX-INT8,AVX-VNNIandAVX512BF16instruction set support.alderlake๐ฆ โ Intel Alderlake CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPT,FSGSBASE,PTWRITE,RDPID,SGX,UMIP,GFNI-SSE,CLWB,MOVDIRI,MOVDIR64B,CLDEMOTE,WAITPKG,ADCX,AVX,AVX2,BMI,BMI2,F16C,FMA,LZCNT,PCONFIG,PKU,VAES,VPCLMULQDQ,SERIALIZE,HRESET,KL,WIDEKLandAVX-VNNIinstruction set support. ๐
โจ OPTIONS โจ
rocketlakeโ ๐ Intel Rocketlake CPU, and bestie, it is PACKED. You get 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, and VAES instruction set support. ๐ฅ๐k6โ ๐ AMD K6 CPU with MMX instruction set support.k6-2,k6-3โ ๐ฆ Upgraded AMD K6 CPUs with MMX and 3DNow! instruction set support.athlon,athlon-tbirdโ AMD Athlon CPU with MMX, 3dNOW!, enhanced 3DNow! and SSE prefetch instructions support. ๐ธathlon-4,athlon-xp,athlon-mpโ An improved AMD Athlon CPU with MMX, 3DNow!, enhanced 3DNow! and full SSE instruction set support. โญk8,opteron,athlon64,athlon-fxโ Processors built on the AMD K8 core with x86-64 instruction set support, including the AMD Opteron, Athlon 64, and Athlon 64 FX processors. It's giving main character. ๐ (This supersets MMX, SSE, SSE2, 3DNow!, enhanced 3DNow! and 64-bit instruction set extensions.)k8-sse3,opteron-sse3,athlon64-sse3โ Glow-up versions of the AMD K8 cores with SSE3 instruction set support. โจamdfam10,barcelonaโ CPUs based on AMD Family 10h cores with x86-64 instruction set support. ๐ (This supersets MMX, SSE, SSE2, SSE3, SSE4A, 3DNow!, enhanced 3DNow!, ABM and 64-bit instruction set extensions.)bdver1โ CPUs based on AMD Family 15h cores with x86-64 instruction set support. ๐ง (This supersets FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver2โ AMD Family 15h core based CPUs with x86-64 instruction set support. ๐ (This supersets BMI, TBM, F16C, FMA, FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver3โ AMD Family 15h core based CPUs with x86-64 instruction set support. ๐ฆ (This supersets BMI, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver4โ AMD Family 15h core based CPUs with x86-64 instruction set support. It's the upgraded one, obviously. ๐ฅ (This supersets BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP, LWP, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)znver1โ AMD Family 17h core based CPUs with x86-64 instruction set support. ๐ (This supersets BMI, BMI2, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, and 64-bit instruction set extensions.)znver2โ AMD Family 17h core based CPUs with x86-64 instruction set support. ๐ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, and 64-bit instruction set extensions.)znver3โ AMD Family 19h core based CPUs with x86-64 instruction set support. ๐ซถ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, and 64-bit instruction set extensions.)znver4โ AMD Family 19h core based CPUs with x86-64 instruction set support. This one is absolutely unhinged in the best way. ๐ญ (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, AVX512F, AVX512DQ, AVX512IFMA, AVX512CD, AVX512BW, AVX512VL, AVX512BF16, AVX512VBMI, AVX512VBMI2, AVX512VNNI, AVX512BITALG, AVX512VPOPCNTDQ, GFNI and 64-bit instruction set extensions.)btver1โ CPUs based on AMD Family 14h cores with x86-64 instruction set support. ๐ (This supersets MMX, SSE, SSE2, SSE3, SSSE3, SSE4A, CX16, ABM and 64-bit instruction set extensions.)btver2โ CPUs based on AMD Family 16h cores with x86-64 instruction set support. This one includes MOVBE, F16C, BMI, AVX, PCLMUL, AES, SSE4.2, SSE4.1, CX16, ABM, SSE4A, SSSE3, SSE3, SSE2, SSE, MMX and 64-bit instruction set extensions. ๐ฆwinchip-c6โ IDT WinChip C6 CPU, handled the same way as i486, with extra MMX instruction set support. ๐ธwinchip2โ IDT WinChip 2 CPU, handled the same way as i486, with extra MMX and 3DNow! instruction set support. ๐ธc3โ VIA C3 CPU with MMX and 3DNow! instruction set support. No scheduling is implemented for this chip, so keep that in mind. ๐c3-2โ VIA C3-2 (Nehemiah/C5XL) CPU with MMX and SSE instruction set support. No scheduling is implemented for this chip. ๐c7โ VIA C7 (Esther) CPU with MMX, SSE, SSE2 and SSE3 instruction set support. No scheduling is implemented for this chip. ๐samuel-2โ VIA Eden Samuel 2 CPU with MMX and 3DNow! instruction set support. No scheduling is implemented for this chip. ๐nehemiahโ VIA Eden Nehemiah CPU with MMX and SSE instruction set support. No scheduling is implemented for this chip. ๐estherโ VIA Eden Esther CPU with MMX, SSE, SSE2 and SSE3 instruction set support. No scheduling is implemented for this chip. ๐eden-x2โ VIA Eden X2 CPU with x86-64, MMX, SSE, SSE2 and SSE3 instruction set support. No scheduling is implemented for this chip. ๐eden-x4โ VIA Eden X4 CPU with x86-64, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 instruction set support. No scheduling is implemented for this chip. ๐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, this one's about tuning. It tunes everything applicable about the generated code tocpu-type, except for the ABI and the set of available instructions. Picking a specificcpu-typeschedules things appropriately for that particular chip, but the compiler won't generate any code that can't run on the default machine type unless you use a-march=cpu-typeoption. For example, if GCC is configured fori686-pc-linux-gnu, then-mtune=pentium4generates code that's tuned for Pentium 4 but still runs on i686 machines. ๐ซถ
The choices for cpu-type are the same as for -march. On top of that, -mtune supports 2 extra choices for cpu-type:
generic
Produces code optimized for the most common IA32/AMD64/EM64T processors. ๐ If you know the CPU your code will run on, use the matching -mtune or -march option instead of -mtune=generic. But if you don't know exactly what CPU your users will have, this is the one to use.
As new processors hit the market, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generation controlled by this option will change to reflect the processors that are most common when that version of GCC is released. โจ
There is no -march=generic option, because -march indicates the instruction set the compiler can use, and there's no generic instruction set that applies to all processors. In contrast, -mtune 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 -mtune or -march option instead of -mtune=intel. But if you want your application performs better on both Haswell and Silvermont, this is the one.
As new Intel processors hit the market, 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 change to reflect the most current Intel processors when that version of GCC is released. ๐ท
There is no -march=intel option, because -march indicates the instruction set the compiler can use, and there's no common instruction set that applies to all processors. In contrast, -mtune indicates the processor (or, in this case, collection of processors) the code is optimized for. ๐ง
-mcpu=cpu-typeโ ๐ an old nickname that's just a deprecated synonym for-mtune. It still works, but switch to-mtune๐ซถ-mfpmath=unitโ ๐ this one picks which unit does your floating-point math. The choices for unit are:387โ the standard 387 floating-point coprocessor, found on most chips and emulated on the rest ๐ง code built this way runs almost everywhere. Temporary results get computed in 80-bit precision instead of the precision the type asks for, so your answers can come out slightly different from most other chips. See-ffloat-storefor the full tea.- This is the default choice for non-Darwin x86-32 targets. โจ
sseโ uses the scalar floating-point instructions from the SSE instruction set ๐ Pentium III and newer chips have it, and on the AMD side it's Athlon-4, Athlon XP and Athlon MP. The early version of SSE only does single-precision math, so double and extended-precision stuff still goes through 387. A later version, only in Pentium 4 and AMD x86-64 chips, handles double-precision too.- For the x86-32 compiler, you need
-march=cpu-type,-msseor-msse2to turn on SSE extensions and make this option work. For the x86-64 compiler, those extensions are on by default. - The result should be way faster in most cases and dodge the numerical instability problems of 387 code. But it may break existing code that expects temporaries to be 80 bits ๐
- This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and the default choice for x86-32 targets with the SSE2 instruction set when
-ffast-mathis enabled. ๐ฅ
- For the x86-32 compiler, you need
sse,387,sse+387,bothโ attempts to use both instruction sets at once ๐ฆ that effectively doubles the available registers and, on chips with separate execution units for 387 and SSE, the execution resources too. Use 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โ picks the assembly dialect for the output, and also decides which dialect basicasmand extendedasmuse ๐ธ supported choices (in dialect order) areattorintel. The default isatt. Darwin doesn't supportintel.-mieee-fp,-mno-ieee-fpโ controls whether the compiler uses IEEE floating-point comparisons, which correctly handle the case where a comparison result 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 instead.
Warning: the requisite libraries are not part of GCC ๐ฑ Normally the facilities of the machine's usual C compiler get used, but that can't be done directly in cross-compilation. You 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 still be emitted even if -msoft-float is used.
-mno-fp-ret-in-387โ don't use the FPU registers for function return values ๐ง the usual calling convention has functions returnfloatanddoublevalues in an FPU register, even if there's no FPU at all, on the idea that the operating system should emulate one. This option makes those values come back in ordinary CPU registers instead.-mno-fancy-math-387โ some 387 emulators don't support thesin,cosandsqrtinstructions for the 387 ๐ use this to avoid generating those instructions. It gets overridden when-marchsays the target CPU always has an FPU, since that instruction doesn't need emulating then. These instructions aren't generated unless you also use the-funsafe-math-optimizationsswitch.-malign-double,-mno-align-doubleโ controls whether GCC alignsdouble,long double, andlong longvariables on a two-word boundary or a one-word boundary ๐ aligningdoubleon a two-word boundary makes code run somewhat faster on a Pentium, at the expense of more memory.- On x86-64,
-malign-doubleis enabled by default.
- On x86-64,
Warning: if you use -malign-double, structures containing the above types are aligned differently than the published application binary interface specs for x86-32, and they aren't binary compatible with structures in code compiled without that switch.
-m96bit-long-double,-m128bit-long-doubleโ these control the size oflong double๐ the x86-32 ABI specifies 96 bits, so-m96bit-long-doubleis the default in 32-bit mode.
Modern chips (Pentium and newer) prefer long double aligned to an 8- or 16-byte boundary, but that's not possible in arrays or structures that follow the ABI. So -m128bit-long-double aligns long double to a 16-byte boundary by padding it with an additional 32-bit zero.
In the x86-64 compiler, -m128bit-long-double is the default choice, since its ABI says 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.
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, and also modifies the function calling convention for functions takinglong double. So they aren't binary-compatible with code compiled without that switch.
-mlong-double-64,-mlong-double-80,-mlong-double-128โ these switches control the size of thelong doubletype ๐ a size of 64 bits makeslong doubleequivalent todouble, and that's the default for the 32-bit Bionic C library. A size of 128 bits makeslong doubleequivalent to__float128, which is the default for the 64-bit Bionic C library.
Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, and also modifies the function calling convention for functions takinglong double. So they aren't binary-compatible with code compiled without that switch.
-malign-data=typeโ controls how GCC aligns variables โจ supported values for type are:compatโ uses an increased alignment value compatible with GCC 4.8 and earlier.abiโ uses the alignment value specified by the psABI.cachelineโ uses an increased alignment value to match the cache line size.
compat is the default.
-mlarge-data-threshold=thresholdโ when-mcmodel=mediumis specified, data objects larger than threshold get placed in the large data section ๐ง this value must be the same across all objects linked into the binary, and it defaults to65535.-mrtdโ switches to a different function-calling convention ๐ฆ functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments as it returns. That saves one instruction in the caller, since it doesn't need to pop the arguments there.
You can make an individual function use this calling sequence with the function attribute stdcall. You can also override the -mrtd option with the function attribute cdecl.
Warning: this calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler.
You must also provide function prototypes for all functions that take variable numbers of arguments (including printf), otherwise incorrect code gets generated for calls to those functions.
In addition, seriously incorrect code results if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored.) ๐
-mregparm=numโ controls how many registers are used to pass integer arguments ๐ธ by default, no registers are used to pass arguments, and at most 3 registers can be used. You can control this for a specific function with the function attributeregparm.
Warning: if you use this switch and num is nonzero, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules.
-msseregparmโ uses SSE register passing conventions forfloatanddoublearguments and return values ๐ you can control this for a specific function with the function attributesseregparm.
Warning: if you use this switch, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules.
-mvect8-ret-in-memโ returns 8-byte vectors in memory instead of MMX registers ๐ซถ this is the default on VxWorks, to match the ABI of the Sun Studio compilers until version 12. Only use this option if you need to stay compatible with existing code produced by those older compiler versions or older versions of GCC.-mpc32,-mpc64,-mpc80โ set 80387 floating-point precision to 32, 64 or 80 bits ๐ with-mpc32, the significands of floating-point operation results are rounded to 24 bits (single precision).-mpc64rounds them to 53 bits (double precision), and-mpc80rounds them to 64 bits (extended double precision), which is the default. When this option is used, floating-point operations in higher precisions aren't available to the programmer unless you set the FPU control word explicitly.
Okay so dropping the rounding precision below the default 80 bits can speed some programs up by 2% or more ๐ but bestie, be careful ๐ญ some math libraries assume extended-precision (80-bit) floating-point ops are on by default. If you set the precision lower than extended, routines in those libraries can lose a lot of accuracy, usually through so-called "catastrophic cancellation" ๐
-mdaz-ftzโ okay this one is about the FTZ (flush-to-zero) and DAZ (denormals-are-zero) flags in the MXCSR register, which control floating-point math โจ SSE and AVX instructions, scalar and vector, can get a glow-up when you turn on FTZ and DAZ with-mdaz-ftz. And if you use-mno-daz-ftz, GCC won't set those flags at all ๐ซถ-mstackrealignโ realign the stack at entry ๐ง On x86, this gives you an alternate prologue and epilogue that realigns the runtime stack when it needs to. It lets old code that keeps 4-byte stack alignment mix with modern code that keeps 16-byte alignment for SSE compatibility ๐ See also the attributeforce_align_arg_pointer, which works on individual functions.-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐ If you don't specify it, the default is4, which means 16 bytes (128 bits).
Warning: this one is giving danger ๐จ When you generate code for the x86-64 architecture with SSE extensions disabled,-mpreferred-stack-boundary=3can keep the stack boundary aligned to 8 bytes. But the x86-64 ABI requires 16-byte stack alignment, so this is ABI incompatible ๐ It's only meant for controlled environments where stack space is a serious limitation. It leads to wrong code when functions compiled with 16-byte stack alignment (like functions from a standard library) get called with a misaligned stack, and then SSE instructions can cause misaligned memory access traps ๐ญ Variable arguments also get handled incorrectly for 16-byte aligned objects (including x87long doubleand__int128), which gives wrong results. You must build all modules with-mpreferred-stack-boundary=3, including any libraries, and that includes the system libraries and startup modules ๐
-mincoming-stack-boundary=numโ assumes the incoming stack is aligned to a 2 raised to num byte boundary ๐ฆ If you don't specify it, GCC uses whatever-mpreferred-stack-boundarysays.
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double) or you'll take big run-time performance hits ๐ฉ On Pentium III, the SSE data type __m128 may not work properly if it isn't 16-byte aligned ๐
To keep those values properly aligned on the stack, the stack boundary has to be at least as aligned as whatever the stack's most-aligned value needs. Every function also has to be generated so it keeps the stack aligned. So if a function compiled with a higher preferred stack boundary gets called from a function compiled with a lower one, the stack will most likely be misaligned ๐ฅบ Libraries that use callbacks should always stick with the default setting, periodt โจ
This extra alignment eats up extra stack space and usually makes the code bigger ๐ฆ Code that's sensitive to stack space, like embedded systems and operating system kernels, might want to drop the preferred alignment to -mpreferred-stack-boundary=2 ๐ธ
-mmmx,-msse,-msse2,-msse3,-mssse3,-msse4,-msse4a,-msse4.1,-msse4.2,-mavx,-mavx2,-mavx512f,-mavx512pf,-mavx512er,-mavx512cd,-mavx512vl,-mavx512bw,-mavx512dq,-mavx512ifma,-mavx512vbmi,-msha,-maes,-mpclmul,-mclflushopt,-mclwb,-mfsgsbase,-mptwrite,-mrdrnd,-mf16c,-mfma,-mpconfig,-mwbnoinvd,-mfma4,-mprfchw,-mrdpid,-mprefetchwt1,-mrdseed,-msgx,-mxop,-mlwp,-m3dnow,-m3dnowa,-mpopcnt,-mabm,-madx,-mbmi,-mbmi2,-mlzcnt,-mfxsr,-mxsave,-mxsaveopt,-mxsavec,-mxsaves,-mrtm,-mhle,-mtbm,-mmwaitx,-mclzero,-mpku,-mavx512vbmi2,-mavx512bf16,-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 switches turn on the instruction sets in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA, AES, PCLMUL, CLFLUSHOPT, CLWB, FSGSBASE, PTWRITE, RDRND, F16C, FMA, PCONFIG, WBNOINVD, FMA4, PREFETCHW, RDPID, PREFETCHWT1, RDSEED, SGX, XOP, LWP, 3DNow!, enhanced 3DNow!, POPCNT, ABM, ADX, BMI, BMI2, LZCNT, FXSR, XSAVE, XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2, GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16, ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE, UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI or CLDEMOTE extended instruction sets ๐ Each one has a matching-mno-option that turns its use off ๐ โโ๏ธ
These extensions are also available as built-in functions. Check out x86 Built-in Functions for the functions these switches enable and disable ๐ง
If you want SSE/SSE2 instructions generated automatically from floating-point code (instead of 387 instructions), look at -mfpmath=sse ๐
GCC depresses SSEx instructions when -mavx is used. Instead, it generates new AVX instructions, or AVX equivalents for all SSEx instructions, when needed ๐ฆ
These options let GCC use those extended instructions in the generated code, even without -mfpmath=sse. Applications that do run-time CPU detection have to compile separate files for each supported architecture, using the right flags ๐ซถ The file with the CPU detection code specifically should be compiled without these options โญ
-mdump-tune-featuresโ tells GCC to dump the names of the x86 performance tuning features and their default settings ๐ You can use those names in-mtune-ctrl=feature-list.-mtune-ctrl=feature-listโ fine-grained control over x86 code generation features ๐๏ธ feature-list is a comma-separated list of feature names. See also-mdump-tune-features. If a feature isn't preceded by^, it gets turned on. If it is preceded by^, it gets turned off.
Warning: -mtune-ctrl=feature-list is meant for GCC developers ๐ง Using it may lead to code paths that aren't covered by testing, and it can potentially cause compiler ICEs or runtime errors ๐
-mno-defaultโ turns off all tunable features ๐ See also-mtune-ctrl=feature-listand-mdump-tune-features.-mcldโ tells GCC to emit acldinstruction in the prologue of functions that use string instructions ๐งน String instructions depend on the DF flag to pick between autoincrement and autodecrement mode. The ABI says DF should be cleared on function entry, but some operating systems don't clear it in their exception dispatchers ๐ฌ So the exception handler can get invoked with DF set, which means the wrong direction mode when string instructions are used. This option can be enabled by default on 32-bit x86 targets by configuring GCC with the--enable-cldconfigure option. In that case, you can suppress generation ofcldinstructions with the-mno-cldcompiler option.-mvzeroupperโ emits avzeroupperinstruction before control flow leaves the function โจ This minimizes the AVX to SSE transition penalty, and it also removes unnecessaryzeroupperintrinsics ๐-mprefer-avx128โ uses 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer ๐ธ-mprefer-vector-width=optโ tells GCC to use opt-bit vector width in instructions, instead of the default for the selected platform ๐noneโ no extra limits applied to 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 to do compare-and-exchange operations on 16-byte aligned 128-bit objects ๐ This is super useful for atomic updates of data structures bigger than one machine word. The compiler uses this instruction to implement__syncBuiltins. For__atomicBuiltins operating on 128-bit integers, though, it always uses a library call, so don't expect the instruction there ๐-msahfโ enables generation ofSAHFinstructions in 64-bit code ๐งช Early Intel Pentium 4 CPUs with Intel 64 support, before the Pentium 4 G1 step arrived in December 2005, didn't have theLAHFandSAHFinstructions that AMD64 supports. These are load and store instructions, respectively, for certain status flags ๐๏ธ In 64-bit mode, theSAHFinstruction gets used to optimize thefmod,drem, andremainderbuilt-in functions. See Other Builtins for details.-mmovbeโ enables use of themovbeinstruction to implement__builtin_bswap32and__builtin_bswap64๐-mshstkโ enables shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ก๏ธ-mcrc32โ enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32siand__builtin_ia32_crc32diso they generate thecrc32machine instruction ๐งฎ-mmwaitโ okay so this one turns on the built-in functions__builtin_ia32_monitorand__builtin_ia32_mwaitso they can generate themonitorandmwaitmachine instructions ๐งโจ-mrecipโ this one swaps in theRCPSSandRSQRTSSinstructions (plus their vectorized buddiesRCPPSandRSQRTPS) with an extra Newton-Raphson step for precision, instead ofDIVSSandSQRTSS(and their vectorized versions) for single-precision floats ๐ฅ It only kicks in when-funsafe-math-optimizationsis on together with-ffinite-math-onlyand-fno-trapping-math. ngl the sequence has higher throughput than the non-reciprocal version, but the precision can drop by up to 2 ulp (like, the inverse of 1.0 comes out as0.99999994) ๐
Also, GCC already turns 1.0f/sqrtf(x) into RSQRTSS (or RSQRTPS) with -ffast-math (or that same option combo), so you don't need -mrecip for that ๐
And GCC already emits that Newton-Raphson sequence for vectorized single-float division and vectorized sqrtf(x) with -ffast-math (or the same combo), so again, no -mrecip needed ๐ซถ
-mrecip=optโ this controls which reciprocal estimate instructions are allowed to be used ๐optis a comma-separated list, and any item can get a!in front to flip it:allโ enables all estimate instructions ๐defaultโ enables the default instructions, same as-mrecip๐noneโ disables all estimate instructions, same as-mno-recip๐divโ enables the approximation for scalar division โจvec-divโ enables the approximation for vectorized division ๐ฆsqrtโ enables the approximation for scalar square root ๐ธvec-sqrtโ enables the approximation for vectorized square root ๐
So, for example, -mrecip=all,!sqrt turns on every reciprocal approximation except square root. Iconic. ๐ฅ
-mveclibabi=typeโ this picks the ABI type for vectorizing intrinsics through an external library ๐ง The supported values fortypearesvml(the Intel short vector math library) andacml(the AMD math core library). To use it, you need both-ftree-vectorizeand-funsafe-math-optimizationsturned on, plus an SVML or ACML ABI-compatible library linked in at link time, or it's not gonna work bestie ๐ญ
GCC currently emits calls to vmldExp2, vmldLn2, vmldLog102, vmldPow2, vmldTanh2, vmldTan2, vmldAtan2, vmldAtanh2, vmldCbrt2, vmldSinh2, vmldSin2, vmldAsinh2, vmldAsin2, vmldCosh2, vmldCos2, vmldAcosh2, vmldAcos2, vmlsExp4, vmlsLn4, vmlsLog104, vmlsPow4, vmlsTanh4, vmlsTan4, vmlsAtan4, vmlsAtanh4, vmlsCbrt4, vmlsSinh4, vmlsSin4, vmlsAsinh4, vmlsAsin4, vmlsCosh4, vmlsCos4, vmlsAcosh4 and vmlsAcos4 for the corresponding function type when -mveclibabi=svml is used. With -mveclibabi=acml, it uses __vrd2_sin, __vrd2_cos, __vrd2_exp, __vrd2_log, __vrd2_log2, __vrd2_log10, __vrs4_sinf, __vrs4_cosf, __vrs4_expf, __vrs4_logf, __vrs4_log2f, __vrs4_log10f and __vrs4_powf for the matching function type ๐
-mabi=nameโ generates code for the calling convention you pick ๐ฆ The allowed values aresysv(the ABI used on GNU/Linux and other systems) andms(the Microsoft ABI). By default you get the Microsoft ABI when targeting Microsoft Windows and the SysV ABI everywhere else. If you want to override that for specific functions, use the function attributesms_abiandsysv_abi๐-mforce-indirect-callโ forces every function call to be indirect โจ This is handy with Intel Processor Trace, since it gives more precise timing info for function calls ๐ฐ๏ธ-mmanual-endbrโ only inserts theENDBRinstruction at function entry when you ask for it with thecf_checkfunction attribute ๐ซถ This is useful alongside-fcf-protection=branch, which lets you controlENDBRinsertion at the function entry.-mcall-ms2sysv-xloguesโ okay so because of differences in 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function has to treatRSI,RDIandXMM6-15as clobbered ๐ญ By default the code for saving and restoring those registers is emitted inline, which makes the prologues and epilogues super lengthy. With-mcall-ms2sysv-xlogues, the prologues and epilogues use stubs in the static portion oflibgccinstead, so your functions get smaller, at the cost of a few extra instructions ๐-mtls-dialect=typeโ generates code to access thread-local storage using thegnuorgnu2conventions ๐งgnuis the conservative default, andgnu2is more efficient, but it may add compile- and run-time requirements that can't be satisfied on all systems, so be careful with that one ๐-mpush-args,-mno-push-argsโ usesPUSHoperations to store outgoing parameters ๐ธ This method is shorter and usually just as fast as theSUB/MOVmethod, and it's enabled by default. In some cases turning it off may improve performance because of better scheduling and fewer dependencies ๐-maccumulate-outgoing-argsโ if enabled, the maximum amount of space needed for outgoing arguments gets computed in the function prologue ๐ This is faster on most modern CPUs because of fewer dependencies, better scheduling and less stack usage when the preferred stack boundary isn't equal to 2. The catch 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 of their code with-mthreads. When compiling, it defines-D_MT, and when linking, it pulls in the special thread helper library-lmingwthrd, which cleans up per-thread exception-handling data ๐ซถ-mms-bitfields,-mno-ms-bitfieldsโ enables or disables bit-field layout that's compatible with the native Microsoft Windows compiler ๐
If packed is used on a structure, or if bit-fields are used, the Microsoft ABI may lay out the structure differently than GCC normally does. Especially when you're moving packed data between functions compiled with GCC and the native Microsoft compiler (through a function call or as data in a file), you may need to access either format ๐
This option is on by default for Microsoft Windows targets. You can also control this locally with variable or type attributes. For more info, see x86 Variable Attributes and x86 Type Attributes โจ
The Microsoft structure layout algorithm is pretty simple, except for bit-field packing ๐ง The padding and alignment of structure members, and whether a bit-field can straddle a storage-unit boundary, are determined by these rules:
- Structure members are stored sequentially in the order they're declared: the first member has the lowest memory address and the last member has the highest ๐ฆ
- Every data object has an alignment requirement. For all data except structures, unions, and arrays, the alignment requirement is either the size of the object or the current packing size (set with either the
alignedattribute or thepackpragma), whichever is less. For structures, unions, and arrays, the alignment requirement is the largest alignment requirement of its members. Every object gets an offset so that:
offset % alignment_requirement == 0
- Adjacent bit-fields get packed into the same 1-, 2-, or 4-byte allocation unit if the integral types are the same size, and if the next bit-field fits into the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit-fields ๐ธ
MSVC interprets zero-length bit-fields in these ways ๐
- If a zero-length bit-field is inserted between two bit-fields that would normally be coalesced, the bit-fields are not coalesced. For example:
struct
{
unsigned long bf_1 : 12;
unsigned long : 0;
unsigned long bf_2 : 12;
} t1;
The size of t1 is 8 bytes with the zero-length bit-field. If the zero-length bit-field were removed, t1's size would be 4 bytes ๐ญ
- If a zero-length bit-field is inserted after a bit-field,
foo, and the alignment of the zero-length bit-field is greater than that of the member that follows it,bar, thenbaris aligned as the type of the zero-length bit-field. For example:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For t2, bar is placed at offset 2, rather than offset 1. Accordingly, the size of t2 is 4. For t3, the zero-length bit-field doesn't affect the alignment of bar or, as a result, the size of the structure ๐ง
Taking this into account, it's important to note the following:
- If a zero-length bit-field follows a normal bit-field, the type of the zero-length bit-field may affect the alignment of the structure as a whole. For example,
t2has a size of 4 bytes, since the zero-length bit-field follows a normal bit-field and is of typeshort๐ - Even if a zero-length bit-field is not followed by a normal bit-field, it may still affect the alignment of the structure:
struct
{
char foo : 6;
long : 0;
} t4;
Here, t4 takes up 4 bytes. main character energy ๐๐
- Zero-length bit-fields that come after non-bit-field members just get ignored, bestie ๐๐ง
struct
{
char foo;
long : 0;
char bar;
} t5;
So t5 only takes up 2 bytes. Tiny struct, big energy ๐
-mno-align-stringopsโ Don't align the destination of inlined string operations ๐ซถ This one shrinks your code and can make things faster when the destination is already aligned, even though GCC doesn't know that yet ๐-minline-all-stringopsโ By default GCC only inlines string operations when it knows the destination is aligned to at least a 4-byte boundary ๐ This turns on more inlining, which makes your code bigger but can speed up code that relies on fastmemcpyandmemsetfor short lengths โก It also enables inline expansion ofstrlenfor all pointer alignments ๐-minline-stringops-dynamicallyโ For string operations with an unknown size, you get run-time checks with inline code for small blocks and a library call for big ones ๐ฆ-mstringop-strategy=algโ Overrides GCC's internal decision heuristic and lets you pick the algorithm used for inlining string operations ๐ The allowed values foralgare:rep_byte,rep_4byte,rep_8byteโ expand using the i386repprefix at the matching size ๐ธbyte_loop,loop,unrolled_loopโ expand into an inline loop ๐libcallโ always use a library call ๐
-mmemcpy-strategy=strategyโ Another override for the heuristic, this time deciding whether__builtin_memcpygets inlined and which inline algorithm to use when the expected copy size is known ๐ง Thestrategyis a comma-separated list ofalg:max_size:dest_aligntriplets ๐algis one of the values from-mstringop-strategy.max_sizeis the max byte size the inline algorithmalgis allowed to handle.- The last triplet's
max_sizemust be-1. - The
max_sizevalues in the list have to go in increasing order. - The minimal byte size for
algis0for the first triplet, andmax_size + 1of the preceding range for every triplet after that.
-mmemset-strategy=strategyโ Basically the same vibe as-mmemcpy-strategy=, except this one controls__builtin_memsetexpansion ๐-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions โจ This skips the instructions that save, set up, and restore frame pointers, and frees up an extra register in leaf functions ๐ The option-fomit-leaf-frame-pointerremoves the frame pointer for leaf functions too, but heads up, that might make debugging harder ๐ฅฒ-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ Controls whether TLS variables can be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer has to be added ๐งต Whether that's valid depends on your operating system, and on whether it maps the segment to cover the entire TLS area ๐ค
For systems that use the GNU C Library, the default is on ๐
-msse2avx,-mno-sse2avxโ Tells the assembler to encode SSE instructions with a VEX prefix ๐ฆ The option-mavxturns this on by default โจ-mfentry,-mno-fentryโ If profiling is active (-pg), this puts 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), this generates a__mcount_locsection full of pointers to each profiling call ๐ It's super useful for automatically patching and out calls ๐ ๏ธ-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), the calls to the profiling functions get generated as NOPs ๐ด This is handy when they should be patched in later, dynamically ๐ช It's likely only useful together with-mrecord-mcount๐-minstrument-return=typeโ Instruments function exit in-pg -mfentryinstrumented functions by calling the specified function ๐ช It only instruments true returns ending withret, not sibling calls ending with a jump ๐ โโ๏ธ Valid types are:noneโ don't instrument ๐callโ generate a call to__return__๐nop5โ generate a 5 byte nop ๐
-mrecord-return,-mno-record-returnโ Generates a__return_locsection pointing to all the return instrumentation code ๐บ๏ธ-mfentry-name=nameโ Sets the name of the__fentry__symbol that gets called at function entry for-pg -mfentryfunctions ๐ท๏ธ-mfentry-section=nameโ Sets the name of the section where-mrecord-mcountcalls get recorded (default__mcount_loc) ๐-mskip-rax-setup,-mno-skip-rax-setupโ When generating x86-64 code with SSE extensions disabled,-mskip-rax-setuplets you skip setting up the RAX register when no variable arguments are passed in vector registers ๐ง
Warning: this one is DRAMATIC ๐ RAX is used to avoid unnecessarily saving vector registers on the stack when passing variable arguments, so the impact is that callees may waste some stack space, misbehave, or jump to a random location ๐ฑ GCC 4.4 or newer don't have those issues, regardless of the RAX register value ๐ซ
-m8bit-idiv,-mno-8bit-idivโ On some processors, like Intel Atom, 8-bit unsigned integer divide is way faster than 32-bit/64-bit integer divide ๐๏ธ This option generates a run-time check. If both the dividend and divisor are within the range of 0 to 255, 8-bit unsigned integer divide gets used instead of 32-bit/64-bit integer divide ๐งฎ-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Splits 32-byte AVX unaligned loads and stores into smaller pieces โ๏ธ-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generates stack protection code using a canary atguard๐ค The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default) ๐งต This only has an effect when-fstack-protectoror-fstack-protector-allis specified ๐ก๏ธ
With the latter choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also tell GCC which segment register (%fs or %gs) to use as the base register for reading the canary, and from what offset from that base register ๐ฏ The defaults for those are whatever the relevant ABI specifies ๐
-mgeneral-regs-onlyโ Generates code that only uses the general-purpose registers ๐ This keeps the compiler away from floating-point, vector, mask, and bound registers ๐ โโ๏ธ-mindirect-branch=choiceโ Converts indirect calls and jumps according tochoice๐ฆ The default iskeep, which leaves indirect calls and jumps unmodified. Here's the rest of the menu:thunkโ converts indirect calls and jumps to a call and return thunk ๐งฉthunk-inlineโ converts them to an inlined call and return thunk ๐งฉthunk-externโ converts them to an external call and return thunk that lives in a separate object file ๐ฆ
You can control this for a specific function with the function attribute indirect_branch ๐๏ธ
Note:-mcmodel=largeis incompatible with-mindirect-branch=thunkand-mindirect-branch=thunk-extern, since the thunk function may not be reachable in the large code model ๐
Note that -mindirect-branch=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐
-mfunction-return=choiceโ Converts function returns according tochoice๐ The default iskeep, which leaves function returns unmodified. The other choices are:thunkโ converts function returns to a call and return thunk ๐งฉthunk-inlineโ converts them to an inlined call and return thunk ๐งฉthunk-externโ converts them to an external call and return thunk provided in a separate object file ๐ฆ
You can control this for a specific function with the function attribute function_return ๐๏ธ
Note that -mindirect-return=thunk-extern is compatible with -fcf-protection=branch, since the external thunk can be made to enable control-flow check ๐
Note:-mcmodel=largeis incompatible with-mfunction-return=thunkand-mfunction-return=thunk-extern, since the thunk function may not be reachable in the large code model ๐
-mindirect-branch-registerโ Forces indirect calls and jumps to go via a register ๐ฏ-mharden-sls=choiceโ Generates code to mitigate straight line speculation (SLS) according tochoice๐ก๏ธ The default isnone, which disables all SLS hardening ๐ The other options are:returnโ enables SLS hardening for function returns ๐indirect-jmpโ enables SLS hardening for indirect jumps ๐ฆallโ enables all SLS hardening ๐ช
-mindirect-branch-cs-prefixโ Adds a CS prefix to call and jmp to an indirect thunk with the branch target in the r8-r15 registers ๐ง This makes the call and jmp instructions 6 bytes long, so they can be replaced at run-time withlfence; call *%r8-r15orlfence; jmp *%r8-r15๐ช
These -m switches are supported in addition to the above on x86-64 processors in 64-bit environments ๐
-m32,-m64,-mx32,-m16,-miamcuโ Generates code for a 16-bit, 32-bit, or 64-bit environment ๐ธ-m32setsint,long, and pointer types to 32 bits, and generates code that runs in 32-bit mode ๐-m64setsintto 32 bits andlongand pointer types to 64 bits, and generates code for the x86-64 architecture ๐ For Darwin only, the-m64option also turns off the-fno-picand-mdynamic-no-picoptions ๐-mx32setsint,long, and pointer types to 32 bits, and generates code for the x86-64 architecture ๐ฆ-m16is the same as-m32, except it outputs the.code16gccassembly directive at the beginning of the assembly output so the binary can run in 16-bit mode ๐ฐ๏ธ-miamcugenerates code that conforms to the Intel MCU psABI ๐งธ It requires-m32to be turned on ๐ซถ
-mno-red-zoneโ Don't use a so-called "red zone" for x86-64 code ๐ โโ๏ธ The red zone is mandated by the x86-64 ABI: it's a 128-byte area beyond the stack pointer that signal or interrupt handlers don't modify, so it can be used for temporary data without adjusting the stack pointer ๐ง The flag-mno-red-zonedisables this red zone ๐
Okay so the code models are next, and they're lowkey the most serious bit of this whole section ๐
-mcmodel=smallโ this is the default code model ๐ the program and its symbols must be linked in the lower 2 GB of the address space. Pointers are 64 bits, and programs can be statically or dynamically linked. No notes.-mcmodel=kernelโ the kernel runs in the negative 2 GB of the address space, so this model is the one you have to use for Linux kernel code ๐-mcmodel=mediumโ the program is linked in the lower 2 GB of the address space, and small symbols get placed there too. Symbols with sizes bigger than-mlarge-data-thresholdget shoved into large data or BSS sections and can live above 2GB ๐ programs can be statically or dynamically linked.-mcmodel=largeโ the big boss model ๐ it makes no assumptions at all about addresses and sizes of sections.-maddress-mode=longโ generates code for long address mode. It's 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. It's only supported for 32-bit and x32 environments, and it's the default for 32-bit and x32 environments ๐ฆ-mneeded,-mno-neededโ emits theGNU_PROPERTY_X86_ISA_1_NEEDEDGNU property for the Linux target, which tells you the micro-architecture ISA level needed to run the binary ๐ง
x86 Windows Options
These extra options are available for Microsoft Windows targets ๐ช๐
-mconsoleโ makes 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 is turned on by default on those targets ๐ธ-mdllโ available for Cygwin and MinGW targets. It makes a DLL---a dynamic link library---and lets you pick the required runtime startup object and entry point ๐-mnop-fun-dllimportโ available for Cygwin and MinGW targets. It tells GCC to ignore the"dllimport"attribute ๐-mthreadโ available for MinGW targets. It uses MinGW-specific thread support ๐งต-municodeโ available for MinGW-w64 targets. It predefines the"UNICODE"preprocessor macro and picks Unicode-capable runtime startup code ๐-mwin32โ available for Cygwin and MinGW targets. It sets the typical Microsoft Windows predefined macros in the preprocessor, but it doesn't change which runtime library or startup code gets chosen ๐-mwindowsโ available for Cygwin and MinGW targets. It makes a GUI application by telling the linker to set the PE header subsystem type to match โจ-fno-set-stack-executableโ available for MinGW targets. The executable flag for the stack used by nested functions doesn't get set. This is necessary for binaries running in kernel mode of Microsoft Windows, since the User32 API (the one used to set executable privileges) isn't available there ๐ญ-fwritable-relocated-rdataโ available for MinGW and Cygwin targets. Relocated data in a read-only section gets put into the".data"section. This is necessary for older runtimes that don't support modifying".rdata"sections for pseudo-relocation ๐ฅ-mpe-aligned-commonsโ available for Cygwin and MinGW targets. 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, bestie ๐ฆ
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 of"CONST16"instructions for loading constant values."CONST16"isn't a standard Tensilica option right now. When it's enabled,"CONST16"instructions are always used in place of the standard"L32R"instructions. It's only enabled by default if the"L32R"instruction isn't available ๐-mfused-madd,-mno-fused-maddโ enables or disables fused multiply/add and multiply/subtract instructions in the floating-point option. This does nothing if the floating-point option isn't also enabled. Turning fused instructions off forces the compiler to use separate instructions for the multiply and the add/subtract. This can be a vibe when strict IEEE 754-compliant results are required, because fused multiply add/subtract instructions don't round the intermediate result, so you get more bits of precision than the IEEE standard specifies. Disabling them also makes sure the program output doesn't depend on the compiler's ability to combine multiply and add/subtract operations ๐ค-mserialize-volatile,-mno-serialize-volatileโ when enabled, GCC inserts"MEMW"instructions before"volatile"memory references to guarantee sequential consistency. The default is-mserialize-volatile, and you use-mno-serialize-volatileto leave out the"MEMW"instructions ๐-mforce-no-picโ for targets like GNU/Linux, where all user-mode Xtensa code has to be position-independent code (PIC), this turns PIC off when compiling kernel code ๐-mtext-section-literals,-mno-text-section-literalsโ these control how literal pools are treated. The default is-mno-text-section-literals, which puts literals in a separate section in the output file. That lets the literal pool sit in data RAM/ROM, and it also lets the linker combine literal pools from separate object files to kill redundant literals and improve code size. With-mtext-section-literals, the literals get interspersed in the text section so they stay as close as possible to their references. This might be necessary for large assembly files. Literals for each function get placed right before that function ๐งต-mauto-litpools,-mno-auto-litpoolsโ also control how literal pools are treated. 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 interspersed the literals in the text section itself. GCC doesn't produce explicit".literal"directives, and it loads literals into registers with"MOVI"instructions instead of"L32R", so the assembler can do relaxation and place literals wherever they need to go. This option lets the assembler create several literal pools per function and assemble very big functions, which might not be possible with-mtext-section-literals๐-mtarget-align,-mno-target-alignโ when enabled, GCC tells the assembler to automatically align instructions to reduce branch penalties, at the cost of some code density. The assembler tries to widen density instructions to align branch targets and the instructions after call instructions. If there aren't enough safe density instructions before a target to align it, no widening happens. The default is-mtarget-align. These options don't touch auto-aligned instructions like"LOOP", 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 translate direct calls into indirect calls unless it can tell that the target of a 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 direct"CALL"instruction into an"L32R"followed by a"CALLX"instruction. The default is-mno-longcalls. Use this option in programs where the call target could be out of range ๐
This one is a bit sneaky. -mlongcalls is implemented in the assembler, not the compiler, so the assembly code GCC generates still shows direct call instructions. Check the disassembled object code if you want 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. The permissible values arecall0andwindowed. The default ABI is chosen by the Xtensa core configuration ๐-mabi=call0โ when enabled, function parameters are passed in registers"a2"through"a7", registers"a12"through"a15"are caller-saved, and register"a15"may be used as a frame pointer. When this version of the ABI is enabled, the C preprocessor symbol"__XTENSA_CALL0_ABI__"is defined ๐-mabi=windowedโ when enabled, function parameters are passed in registers"a10"through"a15". The called function rotates the register window by 8 registers on entry, so its arguments are found in registers"a2"through"a7". Register"a7"may be used as a frame pointer. The register window is rotated 8 registers back upon return. When this version of the ABI is enabled, the C preprocessor symbol"__XTENSA_WINDOWED_ABI__"is defined ๐ธ
zSeries Options
These are listed under
โจ ENVIRONMENT โจ
okay so ENVIRONMENT is where GCC checks the vibes around your build ๐ Several environment variables change how GCC works. Some tell it which directories or prefixes to search for files, and others set different parts of the compilation environment ๐ธ
Quick heads-up, bestie: you can also tell GCC where to search with options like -B, -I and -L. Those beat the environment variables, and the environment variables beat whatever GCC was configured with ๐ซถ
LANG
LC_CTYPE
LC_MESSAGES
LC_ALL
These four are all about localization, which is how GCC handles different national conventions ๐ GCC looks at the LC_CTYPE and LC_MESSAGES locale categories if it was configured to do that. You can set them 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_CTYPEโ this one handles character classification ๐ค GCC uses it to figure out where characters start and stop in a string. That matters for some multibyte encodings where quote and escape characters could otherwise be read as the end of a string or as an escape.LC_MESSAGESโ this sets the language for diagnostic messages, so GCC's error and warning text shows up in your language ๐ฌLC_ALLโ if this is set, it overrides LC_CTYPE and LC_MESSAGES. If it isn't set, LC_CTYPE and LC_MESSAGES fall back to the value ofLANG๐ If none of these are set, GCC defaults to traditional C English behavior.
TMPDIR
If TMPDIR is set, it picks the directory for temporary files ๐ GCC makes temp files to hold the output of one stage that becomes input for the next one. For example, the preprocessor's output is the input to the compiler proper โจ
GCC_COMPARE_DEBUG
Setting GCC_COMPARE_DEBUG is nearly the same as passing -fcompare-debug to the compiler driver ๐ Check that option's docs if you want the full tea.
GCC_EXEC_PREFIX
If GCC_EXEC_PREFIX is set, it gives a prefix for the names of the subprograms the compiler runs ๐ง No slash gets added when the prefix is joined with a subprogram name, so if you want a slash, end your prefix with one.
If GCC_EXEC_PREFIX isn't set, GCC tries to work out a good prefix from the pathname it was invoked with ๐ฆ If it can't find a subprogram with the prefix you gave, it checks the usual places instead.
The default value of GCC_EXEC_PREFIX is prefix/lib/gcc/, where prefix is the prefix of the installed compiler. In lots of cases, prefix is whatever you passed as "prefix" when you ran the configure script ๐ธ
Prefixes given with -B beat this one. This prefix is also how GCC finds files like crt0.o that it needs for linking ๐
Now, here's the unusual part, so pay attention ๐ The prefix also changes where GCC looks 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 right before it searches the standard /usr/local/lib/bar ๐
If a standard directory starts with the configured prefix, GCC replaces that prefix with the value of GCC_EXEC_PREFIX when it hunts for headers.
COMPILER_PATH
COMPILER_PATH is a colon-separated list of directories, kind of like PATH ๐ค๏ธ If GCC can't find a subprogram through GCC_EXEC_PREFIX, it tries these directories when searching for subprograms.
LIBRARY_PATH
LIBRARY_PATH is also a colon-separated list of directories, very much like PATH ๐ On a native compiler, GCC checks these directories for special linker files if it can't find them through GCC_EXEC_PREFIX. Linking with GCC also searches these directories for ordinary libraries used with the -l option, but anything you pass with -L goes first ๐ฅ
LANG
Okay, LANG again, because it has a whole second job ๐ This one passes locale info to the compiler. One thing the compiler uses it for is picking the character set for character literals, string literals and comments when it parses C and C++. If the compiler is set up to allow multibyte characters, it recognizes these LANG values:
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 some other value, 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 ๐ฉน The -fdiagnostics-parseable-fixits and -fno-diagnostics-parseable-fixits options win over this environment variable, so they're the boss here ๐
fixits-v1โ emits parseable fix-it hints, the same as-fdiagnostics-parseable-fixits๐งพ Columns are counted in bytes, starting at byte 1 for the first column.fixits-v2โ same asfixits-v1, except the columns are counted as display columns, like-fdiagnostics-column-unit=display๐
Some more environment variables change how the preprocessor behaves ๐งโโ๏ธ
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, a lot like PATH ๐๏ธ That special character is called "PATH_SEPARATOR". It's target-dependent and gets decided when GCC is built. On Microsoft Windows-based targets it's a semicolon, and on almost everything else it's a colon.
CPATH searches its directories as if you'd passed them with -I, but only after any paths given with -I on the command line. It gets used no matter which language is being preprocessed ๐
The other three only apply when preprocessing their specific language. Each one searches its directories as if you'd used -isystem, but after any paths given with -isystem on the command line ๐
In all of these variables, an empty element tells the compiler to search its current working directory ๐ Empty elements can show up at the start or the end of a path. For example, if CPATH is ":/special/include", that does the exact same thing as -I. -I/special/include โจ
DEPENDENCIES_OUTPUT
If this variable is set, its value says how to output Make dependencies based on the non-system header files the compiler processes ๐ ๏ธ System header files get ignored in the dependency output, so no judgement there ๐
The value can be just a file name. In that case, the Make rules get written to that file, and GCC guesses the target name from the source file name. Or the value can look like file target, which writes the rules to file and uses target as the target name ๐ฏ
Basically, this env var is the same as combining -MM and -MF, with an optional -MT thrown in too ๐
SUNPRO_DEPENDENCIES
This one is the same as DEPENDENCIES_OUTPUT (see above), except system header files are not ignored. So it implies -M instead of -MM ๐ The one catch is that the dependence on the main input file gets left out ๐ซ
SOURCE_DATE_EPOCH
If SOURCE_DATE_EPOCH is set, its value is a UNIX timestamp that replaces the current date and time in the __DATE__ and __TIME__ macros ๐ฐ๏ธ That way your embedded timestamps are reproducible, which is a whole vibe for builds ๐
The value has to be a UNIX timestamp, meaning the number of seconds (leap seconds don't count) since 01 Jan 1970 00:00:00, written in ASCII. It's the same output you'd get from date +%s on GNU/Linux and other systems that support the %s extension in the date command ๐งฎ
The value should be a known timestamp, like the last modification time of your source or package, and your build process should be the one that sets it ๐ ๏ธ
๐ BUGS ๐
For instructions on reporting bugs, check out <file:///usr/share/doc/gcc-11/README.Bugs> ๐ชฒ Go tell the devs what broke, bestie!
๐ 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 ๐ซง
โ ๏ธ Heads up, bestie: skipping the right flags can cause subtle defects, so this footnote is not one to skim ๐ญ
๐ SEE ALSO ๐
Want to go deeper? Check out gpl(7), gfdl(7), fsf-funding(7), cpp(1), gcov(1), as(1), ld(1), gdb(1), dbx(1), and the Info entries for gcc, cpp, as, ld, binutils and gdb ๐๐ธ
๐ฉโ๐ป AUTHOR ๐ฉโ๐ป
See the Info entry for gcc, or <http://gcc.gnu.org/onlinedocs/gcc/Contributors.html>, for the contributors to GCC ๐ซถ They're the real MVPs ๐
โ๏ธ COPYRIGHT โ๏ธ
Copyright (c) 1988-2021 Free Software Foundation, Inc. ๐
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. ๐
And that's the whole page, bestie ๐ฆ Stay curious, keep those environment variables tidy, and go give the GCC folks some love ๐โจ
๐ฆ where this page comes from
- ubuntu questing: g++-11-aarch64-linux-gnu 11.5.0-7ubuntu1.1cross1
- ubuntu questing: g++-11-aarch64-linux-gnu 11.5.0-7ubuntu1cross1
- ubuntu resolute: g++-11-aarch64-linux-gnu 11.5.0-11ubuntu2cross1
- ubuntu stonking: g++-11-aarch64-linux-gnu 11.5.0-11ubuntu2cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms